AWSCredentials: fix interaction with metadata server (#32532)

* No need to call metadata server if environment variables are set.
* AWS_SESSION_TOKEN is optional.
pull/32687/head
Carl Lundin 2 years ago committed by GitHub
parent f04e1a9589
commit 87818f60fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      src/core/lib/security/credentials/external/aws_external_account_credentials.cc
  2. 1
      src/core/lib/security/credentials/external/aws_external_account_credentials.h
  3. 85
      test/core/security/credentials_test.cc

@ -174,6 +174,13 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials(
}
}
bool AwsExternalAccountCredentials::ShouldUseMetadataServer() {
return !((GetEnv(kRegionEnvVar).has_value() ||
GetEnv(kDefaultRegionEnvVar).has_value()) &&
(GetEnv(kAccessKeyIdEnvVar).has_value() &&
GetEnv(kSecretAccessKeyEnvVar).has_value()));
}
void AwsExternalAccountCredentials::RetrieveSubjectToken(
HTTPRequestContext* ctx, const Options& /*options*/,
std::function<void(std::string, grpc_error_handle)> cb) {
@ -186,7 +193,7 @@ void AwsExternalAccountCredentials::RetrieveSubjectToken(
}
ctx_ = ctx;
cb_ = cb;
if (!imdsv2_session_token_url_.empty()) {
if (!imdsv2_session_token_url_.empty() && ShouldUseMetadataServer()) {
RetrieveImdsV2SessionToken();
} else if (signer_ != nullptr) {
BuildSubjectToken();
@ -381,10 +388,12 @@ void AwsExternalAccountCredentials::RetrieveSigningKeys() {
auto secret_access_key_from_env = GetEnv(kSecretAccessKeyEnvVar);
auto token_from_env = GetEnv(kSessionTokenEnvVar);
if (access_key_id_from_env.has_value() &&
secret_access_key_from_env.has_value() && token_from_env.has_value()) {
secret_access_key_from_env.has_value()) {
access_key_id_ = std::move(*access_key_id_from_env);
secret_access_key_ = std::move(*secret_access_key_from_env);
token_ = std::move(*token_from_env);
if (token_from_env.has_value()) {
token_ = std::move(*token_from_env);
}
BuildSubjectToken();
return;
}

@ -45,6 +45,7 @@ class AwsExternalAccountCredentials final : public ExternalAccountCredentials {
grpc_error_handle* error);
private:
bool ShouldUseMetadataServer();
void RetrieveSubjectToken(
HTTPRequestContext* ctx, const Options& options,
std::function<void(std::string, grpc_error_handle)> cb) override;

@ -2938,6 +2938,91 @@ TEST(CredentialsTest, TestAwsImdsv2ExternalAccountCredsSuccess) {
HttpRequest::SetOverride(nullptr, nullptr, nullptr);
}
TEST(CredentialsTest,
TestAwsImdsv2ExternalAccountCredShouldNotUseMetadataServer) {
ExecCtx exec_ctx;
SetEnv("AWS_REGION", "test_regionz");
SetEnv("AWS_ACCESS_KEY_ID", "test_access_key_id");
SetEnv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
SetEnv("AWS_SESSION_TOKEN", "test_token");
auto credential_source = Json::Parse(
valid_aws_imdsv2_external_account_creds_options_credential_source);
GPR_ASSERT(credential_source.ok());
ExternalAccountCredentials::Options options = {
"external_account", // type;
"audience", // audience;
"subject_token_type", // subject_token_type;
"", // service_account_impersonation_url;
"https://foo.com:5555/token", // token_url;
"https://foo.com:5555/token_info", // token_info_url;
*credential_source, // credential_source;
"quota_project_id", // quota_project_id;
"client_id", // client_id;
"client_secret", // client_secret;
"", // workforce_pool_user_project;
};
grpc_error_handle error;
auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
GPR_ASSERT(creds != nullptr);
GPR_ASSERT(error.ok());
GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
auto state = RequestMetadataState::NewInstance(
absl::OkStatus(), "authorization: Bearer token_exchange_access_token");
HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
aws_external_account_creds_httpcli_post_success,
httpcli_put_should_not_be_called);
state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
kTestPath);
ExecCtx::Get()->Flush();
HttpRequest::SetOverride(nullptr, nullptr, nullptr);
UnsetEnv("AWS_REGION");
UnsetEnv("AWS_ACCESS_KEY_ID");
UnsetEnv("AWS_SECRET_ACCESS_KEY");
UnsetEnv("AWS_SESSION_TOKEN");
}
TEST(
CredentialsTest,
TestAwsImdsv2ExternalAccountCredShouldNotUseMetadataServerOptionalTokenMissing) {
ExecCtx exec_ctx;
SetEnv("AWS_REGION", "test_regionz");
SetEnv("AWS_ACCESS_KEY_ID", "test_access_key_id");
SetEnv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key");
auto credential_source = Json::Parse(
valid_aws_imdsv2_external_account_creds_options_credential_source);
GPR_ASSERT(credential_source.ok());
ExternalAccountCredentials::Options options = {
"external_account", // type;
"audience", // audience;
"subject_token_type", // subject_token_type;
"", // service_account_impersonation_url;
"https://foo.com:5555/token", // token_url;
"https://foo.com:5555/token_info", // token_info_url;
*credential_source, // credential_source;
"quota_project_id", // quota_project_id;
"client_id", // client_id;
"client_secret", // client_secret;
"", // workforce_pool_user_project;
};
grpc_error_handle error;
auto creds = AwsExternalAccountCredentials::Create(options, {}, &error);
GPR_ASSERT(creds != nullptr);
GPR_ASSERT(error.ok());
GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY);
auto state = RequestMetadataState::NewInstance(
absl::OkStatus(), "authorization: Bearer token_exchange_access_token");
HttpRequest::SetOverride(aws_external_account_creds_httpcli_get_success,
aws_external_account_creds_httpcli_post_success,
httpcli_put_should_not_be_called);
state->RunRequestMetadataTest(creds.get(), kTestUrlScheme, kTestAuthority,
kTestPath);
ExecCtx::Get()->Flush();
HttpRequest::SetOverride(nullptr, nullptr, nullptr);
UnsetEnv("AWS_REGION");
UnsetEnv("AWS_ACCESS_KEY_ID");
UnsetEnv("AWS_SECRET_ACCESS_KEY");
}
TEST(CredentialsTest, TestAwsExternalAccountCredsSuccessIpv6) {
ExecCtx exec_ctx;
auto credential_source = Json::Parse(

Loading…
Cancel
Save