From c3bd5e9a1e4759f3b0b8e76d4228440555f6d74f Mon Sep 17 00:00:00 2001 From: Jin Date: Fri, 24 Mar 2023 16:22:22 -0700 Subject: [PATCH] fix: gRPC: Remove AWS URL validation (#32674) As of adding support in future for TPC support. We removed all url validations from Credentials. AWS url validation doesn't make sense here either. --- .../aws_external_account_credentials.cc | 32 --- test/core/security/credentials_test.cc | 238 +++++------------- 2 files changed, 63 insertions(+), 207 deletions(-) diff --git a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc index f51e044089e..c2ab4e3972f 100644 --- a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc @@ -38,7 +38,6 @@ #include #include "src/core/lib/gprpp/env.h" -#include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/http/httpcli_ssl_credentials.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/json/json.h" @@ -49,9 +48,6 @@ namespace grpc_core { namespace { -const char* awsEc2MetadataIpv4Address = "169.254.169.254"; -const char* awsEc2MetadataIpv6Address = "fd00:ec2::254"; - const char* kExpectedEnvironmentId = "aws1"; const char* kRegionEnvVar = "AWS_REGION"; @@ -78,15 +74,6 @@ std::string UrlEncode(const absl::string_view& s) { return result; } -bool ValidateAwsUrl(const std::string& urlString) { - absl::StatusOr url = URI::Parse(urlString); - if (!url.ok()) return false; - absl::string_view host; - absl::string_view port; - SplitHostPort(url->authority(), &host, &port); - return host == awsEc2MetadataIpv4Address || host == awsEc2MetadataIpv6Address; -} - } // namespace RefCountedPtr @@ -129,22 +116,10 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials( return; } region_url_ = it->second.string_value(); - if (!ValidateAwsUrl(region_url_)) { - *error = GRPC_ERROR_CREATE(absl::StrFormat( - "Invalid host for region_url field, expecting %s or %s.", - awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address)); - return; - } it = options.credential_source.object_value().find("url"); if (it != options.credential_source.object_value().end() && it->second.type() == Json::Type::STRING) { url_ = it->second.string_value(); - if (!ValidateAwsUrl(url_)) { - *error = GRPC_ERROR_CREATE(absl::StrFormat( - "Invalid host for url field, expecting %s or %s.", - awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address)); - return; - } } it = options.credential_source.object_value().find( "regional_cred_verification_url"); @@ -164,13 +139,6 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials( if (it != options.credential_source.object_value().end() && it->second.type() == Json::Type::STRING) { imdsv2_session_token_url_ = it->second.string_value(); - if (!ValidateAwsUrl(imdsv2_session_token_url_)) { - *error = GRPC_ERROR_CREATE(absl::StrFormat( - "Invalid host for imdsv2_session_token_url field, expecting %s or " - "%s.", - awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address)); - return; - } } } diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 364e4c9ff96..49637bb61d3 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -268,30 +268,6 @@ const char "\"regional_cred_verification_url\":\"https://foo.com:5555/" "regional_cred_verification_url_{region}\"}"; -const char - invalid_aws_external_account_creds_options_credential_source_invalid_region_url_host - [] = "{\"environment_id\":\"aws1\"," - "\"region_url\":\"https://fakeurl.com/url\"," - "\"url\":\"https://169.254.169.254:5555/url\"," - "\"regional_cred_verification_url\":\"https://foo.com:5555/" - "regional_cred_verification_url_{region}\"}"; - -const char - invalid_aws_external_account_creds_options_credential_source_invalid_url_host - [] = "{\"environment_id\":\"aws1\"," - "\"region_url\":\"https://169.254.169.254:5555/region_url\"," - "\"url\":\"https://fake.com/url\"," - "\"regional_cred_verification_url\":\"https://foo.com:5555/" - "regional_cred_verification_url_{region}\"}"; - -const char - invalid_aws_external_account_creds_options_credential_source_missing_role_name - [] = "{\"environment_id\":\"aws1\"," - "\"region_url\":\"https://169.254.169.254:5555/region_url\"," - "\"url\":\"https://169.254.169.254:5555/url_no_role_name\"," - "\"regional_cred_verification_url\":\"https://foo.com:5555/" - "regional_cred_verification_url_{region}\"}"; - const char invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url [] = "{\"environment_id\":\"aws1\"," @@ -301,12 +277,10 @@ const char "verification_url\"}"; const char - invalid_aws_external_account_creds_options_credential_source_invalid_imdsv2_url_host + invalid_aws_external_account_creds_options_credential_source_missing_role_name [] = "{\"environment_id\":\"aws1\"," "\"region_url\":\"https://169.254.169.254:5555/region_url\"," - "\"url\":\"https://169.254.169.254:5555/url\"," - "\"imdsv2_session_token_url\":\"https://foo.com/" - "imdsv2_session_token_url\"," + "\"url\":\"https://169.254.169.254:5555/url_no_role_name\"," "\"regional_cred_verification_url\":\"https://foo.com:5555/" "regional_cred_verification_url_{region}\"}"; @@ -3344,6 +3318,60 @@ TEST(CredentialsTest, UnsetEnv("AWS_SESSION_TOKEN"); } +TEST(CredentialsTest, TestExternalAccountCredentialsCreateSuccess) { + // url credentials + const char* url_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/" + "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":" + "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":" + "\"access_token\"}},\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* url_scopes_string = "scope1,scope2"; + grpc_call_credentials* url_creds = grpc_external_account_credentials_create( + url_options_string, url_scopes_string); + GPR_ASSERT(url_creds != nullptr); + url_creds->Unref(); + // file credentials + const char* file_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* file_scopes_string = "scope1,scope2"; + grpc_call_credentials* file_creds = grpc_external_account_credentials_create( + file_options_string, file_scopes_string); + GPR_ASSERT(file_creds != nullptr); + file_creds->Unref(); + // aws credentials + const char* aws_options_string = + "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" + "token_type\":\"subject_token_type\",\"service_account_impersonation_" + "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" + "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" + "token_info\",\"credential_source\":{\"environment_id\":\"aws1\"," + "\"region_url\":\"https://169.254.169.254:5555/" + "region_url\",\"url\":\"https://" + "169.254.169.254:5555/url\",\"regional_cred_verification_url\":\"https://" + "foo.com:5555/regional_cred_verification_url_{region}\"}," + "\"quota_project_id\":\"quota_" + "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" + "secret\"}"; + const char* aws_scopes_string = "scope1,scope2"; + grpc_call_credentials* aws_creds = grpc_external_account_credentials_create( + aws_options_string, aws_scopes_string); + GPR_ASSERT(aws_creds != nullptr); + aws_creds->Unref(); +} + TEST(CredentialsTest, TestAwsExternalAccountCredsFailureUnmatchedEnvironmentId) { auto credential_source = Json::Parse( @@ -3372,10 +3400,11 @@ TEST(CredentialsTest, GPR_ASSERT(expected_error == actual_error); } -TEST(CredentialsTest, TestAwsExternalAccountCredsFailureMissingRoleName) { +TEST(CredentialsTest, + TestAwsExternalAccountCredsFailureInvalidRegionalCredVerificationUrl) { ExecCtx exec_ctx; auto credential_source = Json::Parse( - invalid_aws_external_account_creds_options_credential_source_missing_role_name); + invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url); GPR_ASSERT(credential_source.ok()); ExternalAccountCredentials::Options options = { "external_account", // type; @@ -3395,7 +3424,7 @@ TEST(CredentialsTest, TestAwsExternalAccountCredsFailureMissingRoleName) { GPR_ASSERT(creds != nullptr); GPR_ASSERT(error.ok()); GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); - error = GRPC_ERROR_CREATE("Missing role name when retrieving signing keys."); + error = GRPC_ERROR_CREATE("Creating aws request signer failed."); grpc_error_handle expected_error = GRPC_ERROR_CREATE_REFERENCING( "Error occurred when fetching oauth2 token.", &error, 1); auto state = RequestMetadataState::NewInstance(expected_error, {}); @@ -3408,11 +3437,10 @@ TEST(CredentialsTest, TestAwsExternalAccountCredsFailureMissingRoleName) { HttpRequest::SetOverride(nullptr, nullptr, nullptr); } -TEST(CredentialsTest, - TestAwsExternalAccountCredsFailureInvalidRegionalCredVerificationUrl) { +TEST(CredentialsTest, TestAwsExternalAccountCredsFailureMissingRoleName) { ExecCtx exec_ctx; auto credential_source = Json::Parse( - invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url); + invalid_aws_external_account_creds_options_credential_source_missing_role_name); GPR_ASSERT(credential_source.ok()); ExternalAccountCredentials::Options options = { "external_account", // type; @@ -3432,7 +3460,7 @@ TEST(CredentialsTest, GPR_ASSERT(creds != nullptr); GPR_ASSERT(error.ok()); GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); - error = GRPC_ERROR_CREATE("Creating aws request signer failed."); + error = GRPC_ERROR_CREATE("Missing role name when retrieving signing keys."); grpc_error_handle expected_error = GRPC_ERROR_CREATE_REFERENCING( "Error occurred when fetching oauth2 token.", &error, 1); auto state = RequestMetadataState::NewInstance(expected_error, {}); @@ -3445,146 +3473,6 @@ TEST(CredentialsTest, HttpRequest::SetOverride(nullptr, nullptr, nullptr); } -TEST(CredentialsTest, TestAwsExternalAccountCredsFailureInvalidUrlHost) { - auto credential_source = Json::Parse( - invalid_aws_external_account_creds_options_credential_source_invalid_url_host); - 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); - std::string expected_error = - "Invalid host for url field, expecting 169.254.169.254 or fd00:ec2::254."; - std::string actual_error; - GPR_ASSERT(grpc_error_get_str(error, StatusStrProperty::kDescription, - &actual_error)); - GPR_ASSERT(expected_error == actual_error); -} - -TEST(CredentialsTest, TestAwsExternalAccountCredsFailureInvalidRegionUrlHost) { - auto credential_source = Json::Parse( - invalid_aws_external_account_creds_options_credential_source_invalid_region_url_host); - 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); - std::string expected_error = - "Invalid host for region_url field, expecting 169.254.169.254 or " - "fd00:ec2::254."; - std::string actual_error; - GPR_ASSERT(grpc_error_get_str(error, StatusStrProperty::kDescription, - &actual_error)); - GPR_ASSERT(expected_error == actual_error); -} - -TEST(CredentialsTest, TestAwsExternalAccountCredsFailureInvalidImdsv2UrlHost) { - auto credential_source = Json::Parse( - invalid_aws_external_account_creds_options_credential_source_invalid_imdsv2_url_host); - 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); - std::string expected_error = - "Invalid host for imdsv2_session_token_url field, expecting " - "169.254.169.254 or fd00:ec2::254."; - std::string actual_error; - GPR_ASSERT(grpc_error_get_str(error, StatusStrProperty::kDescription, - &actual_error)); - GPR_ASSERT(expected_error == actual_error); -} - -TEST(CredentialsTest, TestExternalAccountCredentialsCreateSuccess) { - // url credentials - const char* url_options_string = - "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" - "token_type\":\"subject_token_type\",\"service_account_impersonation_" - "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" - "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" - "token_info\",\"credential_source\":{\"url\":\"https://foo.com:5555/" - "generate_subject_token_format_json\",\"headers\":{\"Metadata-Flavor\":" - "\"Google\"},\"format\":{\"type\":\"json\",\"subject_token_field_name\":" - "\"access_token\"}},\"quota_project_id\":\"quota_" - "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" - "secret\"}"; - const char* url_scopes_string = "scope1,scope2"; - grpc_call_credentials* url_creds = grpc_external_account_credentials_create( - url_options_string, url_scopes_string); - GPR_ASSERT(url_creds != nullptr); - url_creds->Unref(); - // file credentials - const char* file_options_string = - "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" - "token_type\":\"subject_token_type\",\"service_account_impersonation_" - "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" - "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" - "token_info\",\"credential_source\":{\"file\":\"credentials_file_path\"}," - "\"quota_project_id\":\"quota_" - "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" - "secret\"}"; - const char* file_scopes_string = "scope1,scope2"; - grpc_call_credentials* file_creds = grpc_external_account_credentials_create( - file_options_string, file_scopes_string); - GPR_ASSERT(file_creds != nullptr); - file_creds->Unref(); - // aws credentials - const char* aws_options_string = - "{\"type\":\"external_account\",\"audience\":\"audience\",\"subject_" - "token_type\":\"subject_token_type\",\"service_account_impersonation_" - "url\":\"service_account_impersonation_url\",\"token_url\":\"https://" - "foo.com:5555/token\",\"token_info_url\":\"https://foo.com:5555/" - "token_info\",\"credential_source\":{\"environment_id\":\"aws1\"," - "\"region_url\":\"https://169.254.169.254:5555/" - "region_url\",\"url\":\"https://" - "169.254.169.254:5555/url\",\"regional_cred_verification_url\":\"https://" - "foo.com:5555/regional_cred_verification_url_{region}\"}," - "\"quota_project_id\":\"quota_" - "project_id\",\"client_id\":\"client_id\",\"client_secret\":\"client_" - "secret\"}"; - const char* aws_scopes_string = "scope1,scope2"; - grpc_call_credentials* aws_creds = grpc_external_account_credentials_create( - aws_options_string, aws_scopes_string); - GPR_ASSERT(aws_creds != nullptr); - aws_creds->Unref(); -} - TEST(CredentialsTest, TestExternalAccountCredentialsCreateFailureInvalidJsonFormat) { const char* options_string = "invalid_json";