From f5476a3e9d7fdd9d8fc9f52511deb07bf05d4449 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Mon, 23 Oct 2023 18:36:56 -0400 Subject: [PATCH 1/4] Account id endpoint support --- .../views/endpoints_module.rb | 8 ++-- .../spec/endpoint_provider_spec_class.rb | 29 ++++++++----- .../templates/endpoints_module.mustache | 5 --- .../endpoint_provider_spec_class.mustache | 2 +- build_tools/services.rb | 4 +- gems/aws-sdk-core/CHANGELOG.md | 4 ++ .../aws-sdk-core/credential_provider_chain.rb | 11 ++++- .../lib/aws-sdk-core/credentials.rb | 19 +++++--- .../plugins/credentials_configuration.rb | 10 +++-- .../aws-sdk-core/plugins/regional_endpoint.rb | 20 +++++++++ .../lib/aws-sdk-core/shared_config.rb | 4 +- .../lib/aws-sdk-core/shared_credentials.rb | 7 --- .../aws/credential_provider_chain_spec.rb | 43 +++++++++++-------- .../aws-sdk-core/spec/aws/credentials_spec.rb | 17 +++++++- .../spec/aws/shared_config_spec.rb | 11 +++++ .../fixtures/credentials/mock_shared_config | 4 ++ 16 files changed, 136 insertions(+), 62 deletions(-) diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb index cd4a59a6d04..b2406e4cd95 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb @@ -42,10 +42,6 @@ def initialize(options) # @return [Array] attr_reader :parameters - - def has_endpoint_built_in? - parameters.any? { |p| p.param_data['builtIn'] == 'SDK::Endpoint' } - end end class EndpointParameter @@ -134,6 +130,8 @@ def built_in_client_context_param_value(param_data) else 'context.config.use_dualstack_endpoint' end + when 'AWS::Auth::AccountId' + "context.config.account_id_endpoint_mode == 'disabled' ? nil : context.config.credentials.credentials.account_id" when 'AWS::STS::UseGlobalEndpoint' "context.config.sts_regional_endpoints == 'legacy'" when 'AWS::S3::UseGlobalEndpoint' @@ -151,7 +149,7 @@ def built_in_client_context_param_value(param_data) when 'AWS::S3::DisableMultiRegionAccessPoints' 'context.config.s3_disable_multiregion_access_points' when 'SDK::Endpoint' - 'endpoint' + 'context.config.regional_endpoint ? nil : context.config.endpoint.to_s' end end diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb index 76965005875..274c53c1991 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb @@ -51,9 +51,9 @@ def initialize(options) operation_name: Underscore.underscore( operation_inputs_test['operationName'] ), - operation_params: operation_inputs_test['operationParams'] || [], - built_in_params: operation_inputs_test['builtInParams'] || [], - client_params: operation_inputs_test['clientParams'] || [] + operation_params: operation_inputs_test['operationParams'] || {}, + built_in_params: operation_inputs_test['builtInParams'] || {}, + client_params: operation_inputs_test['clientParams'] || {} ) end end @@ -113,12 +113,13 @@ def initialize(options) @client_params = options[:client_params].map do |k,v| Param.new(Underscore.underscore(k), v) end - @client_params += options[:built_in_params].map do |k,v| built_in_to_param(k, v) end - # the expected default of UseGlobalEndpoint does not match the SDK's default value - if @service.identifier == 's3' && !options[:built_in_params].include?('AWS::S3::UseGlobalEndpoint') + # the expected default of UseGlobalEndpoint in rules + # does not match the Ruby SDK's default value + if @service.identifier == 's3' && + !options[:built_in_params].include?('AWS::S3::UseGlobalEndpoint') @client_params << built_in_to_param('AWS::S3::UseGlobalEndpoint', false) end end @@ -154,6 +155,12 @@ def built_in_to_param(built_in, value) Param.new('use_fips_endpoint', value) when 'AWS::UseDualStack' Param.new('use_dualstack_endpoint', value) + when 'AWS::Auth::AccountId' + Param.new( + 'credentials', + "Aws::Credentials.new('stubbed-akid', 'stubbed-secret', account_id: '#{value}')", + true + ) when 'AWS::STS::UseGlobalEndpoint' Param.new('sts_regional_endpoints', value ? 'legacy' : 'regional') when 'AWS::S3::UseGlobalEndpoint' @@ -162,9 +169,7 @@ def built_in_to_param(built_in, value) Param.new('use_accelerate_endpoint', value) when 'AWS::S3::ForcePathStyle' Param.new('force_path_style', value) - when 'AWS::S3::UseArnRegion' - Param.new('s3_use_arn_region', value) - when 'AWS::S3Control::UseArnRegion' + when 'AWS::S3::UseArnRegion', 'AWS::S3Control::UseArnRegion' Param.new('s3_use_arn_region', value) when 'AWS::S3::DisableMultiRegionAccessPoints' Param.new('s3_disable_multiregion_access_points', value) @@ -177,14 +182,16 @@ def built_in_to_param(built_in, value) end class Param - def initialize(param, value) + def initialize(param, value, literal = false) @param = param @value = value + @literal = literal end + attr_accessor :param def value - if @value.is_a? String + if @value.is_a?(String) && !@literal "'#{@value}'" else @value diff --git a/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache b/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache index 7ae625341e5..a93a5860b8a 100644 --- a/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache +++ b/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache @@ -11,11 +11,6 @@ module {{module_name}} {{#endpoint_classes}} class {{name}} def self.build(context) - {{#has_endpoint_built_in?}} - unless context.config.regional_endpoint - endpoint = context.config.endpoint.to_s - end - {{/has_endpoint_built_in?}} {{module_name}}::EndpointParameters.new( {{#parameters}} {{#static_string?}} diff --git a/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache b/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache index 7b48f402d29..a610601784f 100644 --- a/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache +++ b/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache @@ -11,7 +11,7 @@ module {{module_name}} subject { {{module_name}}::EndpointProvider.new } {{#endpoint_tests}} - context '{{documentation}}' do + context '{{{documentation}}}' do let(:expected) do {{{expect}}} end diff --git a/build_tools/services.rb b/build_tools/services.rb index 4c04fbd4a15..279872a886b 100644 --- a/build_tools/services.rb +++ b/build_tools/services.rb @@ -10,10 +10,10 @@ class ServiceEnumerator MANIFEST_PATH = File.expand_path('../../services.json', __FILE__) # Minimum `aws-sdk-core` version for new gem builds - MINIMUM_CORE_VERSION = "3.184.0" + MINIMUM_CORE_VERSION = "3.186.0" # Minimum `aws-sdk-core` version for new S3 gem builds - MINIMUM_CORE_VERSION_S3 = "3.181.0" + MINIMUM_CORE_VERSION_S3 = "3.186.0" EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration" diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index f60fbf65680..2dae6d68549 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,6 +1,10 @@ Unreleased Changes ------------------ +* Feature - Support Account ID credentials using `ENV['AWS_ACCOUNT_ID']`, `aws_account_id` shared config, or the `account_id` Client configuration option. + +* Feature - Support Account ID endpoint mode using `ENV['AWS_ACCOUNT_ID_ENDPOINT_MODE']`, `aws_account_id_endpoint_mode` shared config, or the `account_id_endpoint_mode` Client configuration option. Defaults to `preferred`, which will use the account id endpoint if available. Set to `disabled` to disable account id endpoints. Set to `required` to require account id endpoint usage; an error is raised if credentials do not have an account id. + 3.185.1 (2023-10-05) ------------------ diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 7574659c937..f561a3f7b46 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -45,7 +45,8 @@ def static_credentials(options) Credentials.new( options[:config].access_key_id, options[:config].secret_access_key, - options[:config].session_token + options[:config].session_token, + account_id: options[:config].account_id ) end end @@ -94,7 +95,13 @@ def env_credentials(_options) key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] - Credentials.new(envar(key), envar(secret), envar(token)) + account_id = %w[AWS_ACCOUNT_ID] + Credentials.new( + envar(key), + envar(secret), + envar(token), + account_id: envar(account_id) + ) end def envar(keys) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 964074fe169..93bf3a0026f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -6,21 +6,28 @@ class Credentials # @param [String] access_key_id # @param [String] secret_access_key # @param [String] session_token (nil) - def initialize(access_key_id, secret_access_key, session_token = nil) + # @param [Hash] kwargs + # @option kwargs [String] :credential_scope (nil) + def initialize(access_key_id, secret_access_key, session_token = nil, + **kwargs) @access_key_id = access_key_id @secret_access_key = secret_access_key @session_token = session_token + @account_id = kwargs[:account_id] end - # @return [String, nil] + # @return [String] attr_reader :access_key_id - # @return [String, nil] + # @return [String] attr_reader :secret_access_key # @return [String, nil] attr_reader :session_token + # @return [String, nil] + attr_reader :account_id + # @return [Credentials] def credentials self @@ -30,9 +37,9 @@ def credentials # access key are both set. def set? !access_key_id.nil? && - !access_key_id.empty? && - !secret_access_key.nil? && - !secret_access_key.empty? + !access_key_id.empty? && + !secret_access_key.nil? && + !secret_access_key.empty? end # Removing the secret access key from the default inspect string. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/credentials_configuration.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/credentials_configuration.rb index b532731c300..59efe784bf0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/credentials_configuration.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/credentials_configuration.rb @@ -12,6 +12,8 @@ class CredentialsConfiguration < Seahorse::Client::Plugin option(:session_token, doc_type: String, docstring: '') + option(:account_id, doc_type: String, docstring: '') + option(:profile, doc_default: 'default', doc_type: String, @@ -57,13 +59,15 @@ class CredentialsConfiguration < Seahorse::Client::Plugin locations will be searched for credentials: * `Aws.config[:credentials]` -* The `:access_key_id`, `:secret_access_key`, and `:session_token` options. -* ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'] +* The `:access_key_id`, `:secret_access_key`, `:session_token`, and + `:account_id` options. +* ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'], + ENV['AWS_SESSION_TOKEN'], and ENV['AWS_ACCOUNT_ID'] * `~/.aws/credentials` * `~/.aws/config` * EC2/ECS IMDS instance profile - When used by default, the timeouts are very aggressive. Construct and pass an instance of - `Aws::InstanceProfileCredentails` or `Aws::ECSCredentials` to + `Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to enable retries and extended timeouts. Instance profile credential fetching can be disabled by setting ENV['AWS_EC2_METADATA_DISABLED'] to true. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb index 25b3254ba40..71623fb6135 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb @@ -56,6 +56,20 @@ class RegionalEndpoint < Seahorse::Client::Plugin resolve_ignore_configured_endpoint_urls(cfg) end + option(:account_id_endpoint_mode, + doc_type: String, + docstring: <<-DOCS) do |cfg| +The account ID endpoint mode to use. This can be one of the following values: +* `preferred` - The default behavior. Use the account ID endpoint if + available, otherwise use the standard endpoint. +* `disabled` - Never use the account ID endpoint. Only use the standard + endpoint. +* `required` - Always use the account ID endpoint. If the account ID + cannot be retrieved from credentials, an error is raised. + DOCS + resolve_account_id_endpoint_mode(cfg) + end + option(:endpoint, doc_type: String, docstring: <<-DOCS) do |cfg| The client endpoint is normally constructed from the `:region` option. You should only configure an `:endpoint` when connecting @@ -101,6 +115,12 @@ def resolve_ignore_configured_endpoint_urls(cfg) Aws::Util.str_2_bool(value&.downcase) || false end + def resolve_account_id_endpoint_mode(cfg) + value = ENV['AWS_ACCOUNT_ID_ENDPOINT_MODE'] + value ||= Aws.shared_config.account_id_endpoint_mode(profile: cfg.profile) + value || 'preferred' + end + # NOTE: with Endpoints 2.0, some of this logic is deprecated # but because new old service gems may depend on new core versions # we must preserve that behavior. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 3180e05de51..b97567a5bb5 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -198,6 +198,7 @@ def self.config_reader(*attrs) config_reader( :region, + :account_id_endpoint_mode, :ca_bundle, :credential_process, :endpoint_discovery_enabled, @@ -411,7 +412,8 @@ def credentials_from_profile(prof_config) creds = Credentials.new( prof_config['aws_access_key_id'], prof_config['aws_secret_access_key'], - prof_config['aws_session_token'] + prof_config['aws_session_token'], + account_id: prof_config['aws_account_id'] ) creds if creds.set? end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index 836dd3f6273..9508080f19f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -7,13 +7,6 @@ class SharedCredentials include CredentialProvider - # @api private - KEY_MAP = { - 'aws_access_key_id' => 'access_key_id', - 'aws_secret_access_key' => 'secret_access_key', - 'aws_session_token' => 'session_token', - } - # Constructs a new SharedCredentials object. This will load static # (access_key_id, secret_access_key and session_token) AWS access # credentials from an ini file, which supports profiles. The default diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 164abe62037..3d9a19c92cf 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -6,8 +6,12 @@ module Aws describe CredentialProviderChain do def random_creds - { access_key_id: SecureRandom.hex, - secret_access_key: SecureRandom.hex, session_token: SecureRandom.hex } + { + access_key_id: SecureRandom.hex, + secret_access_key: SecureRandom.hex, + session_token: SecureRandom.hex, + account_id: SecureRandom.hex + } end def with_shared_credentials(profile_name = SecureRandom.hex, credentials_file = nil) @@ -19,6 +23,7 @@ def with_shared_credentials(profile_name = SecureRandom.hex, credentials_file = aws_access_key_id = #{creds[:access_key_id]} aws_secret_access_key = #{creds[:secret_access_key]} aws_session_token = #{creds[:session_token]} +aws_account_id = #{creds[:account_id]} CREDS allow(Dir).to receive(:home).and_return('HOME') allow(File).to receive(:exist?).with(path).and_return(true) @@ -29,9 +34,10 @@ def with_shared_credentials(profile_name = SecureRandom.hex, credentials_file = def with_env_credentials creds = random_creds - env['AWS_ACCESS_KEY_ID'] = creds[:access_key_id] - env['AWS_SECRET_ACCESS_KEY'] = creds[:secret_access_key] - env['AWS_SESSION_TOKEN'] = creds[:session_token] + ENV['AWS_ACCESS_KEY_ID'] = creds[:access_key_id] + ENV['AWS_SECRET_ACCESS_KEY'] = creds[:secret_access_key] + ENV['AWS_SESSION_TOKEN'] = creds[:session_token] + ENV['AWS_ACCOUNT_ID'] = creds[:account_id] creds end @@ -40,6 +46,7 @@ def with_config_credentials allow(config).to receive(:access_key_id).and_return(creds[:access_key_id]) allow(config).to receive(:secret_access_key).and_return(creds[:secret_access_key]) allow(config).to receive(:session_token).and_return(creds[:session_token]) + allow(config).to receive(:account_id).and_return(creds[:account_id]) creds end @@ -49,15 +56,15 @@ def validate_credentials(expected_creds) expect(creds.access_key_id).to eq(expected_creds[:access_key_id]) expect(creds.secret_access_key).to eq(expected_creds[:secret_access_key]) expect(creds.session_token).to eq(expected_creds[:session_token]) + expect(creds.account_id).to eq(expected_creds[:account_id]) end - let(:env) { {} } - let(:config) do double('config', access_key_id: nil, secret_access_key: nil, session_token: nil, + account_id: nil, profile: nil, region: nil, instance_profile_credentials_timeout: 1, @@ -71,7 +78,6 @@ def validate_credentials(expected_creds) let(:credentials) { chain.resolve } before(:each) do - stub_const('ENV', env) allow(InstanceProfileCredentials).to receive(:new).and_return(mock_instance_creds) end @@ -82,31 +88,32 @@ def validate_credentials(expected_creds) it 'hydrates credentials from ENV with prefix AWS_' do expected_creds = random_creds - env['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] - env['AWS_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] - env['AWS_SESSION_TOKEN'] = expected_creds[:session_token] + ENV['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] + ENV['AWS_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] + ENV['AWS_SESSION_TOKEN'] = expected_creds[:session_token] + ENV['AWS_ACCOUNT_ID'] = expected_creds[:account_id] validate_credentials(expected_creds) end it 'hydrates credentials from ENV with prefix AMAZON_' do expected_creds = random_creds - env['AMAZON_ACCESS_KEY_ID'] = expected_creds[:access_key_id] - env['AMAZON_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] - env['AMAZON_SESSION_TOKEN'] = expected_creds[:session_token] + ENV['AMAZON_ACCESS_KEY_ID'] = expected_creds[:access_key_id] + ENV['AMAZON_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] + ENV['AMAZON_SESSION_TOKEN'] = expected_creds[:session_token] validate_credentials(expected_creds) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY & AWS_SECRET_KEY' do expected_creds = random_creds.merge(session_token: nil) - env['AWS_ACCESS_KEY'] = expected_creds[:access_key_id] - env['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] + ENV['AWS_ACCESS_KEY'] = expected_creds[:access_key_id] + ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY_ID & AWS_SECRET_KEY' do expected_creds = random_creds.merge(session_token: nil) - env['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] - env['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] + ENV['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] + ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) end diff --git a/gems/aws-sdk-core/spec/aws/credentials_spec.rb b/gems/aws-sdk-core/spec/aws/credentials_spec.rb index 598c5a122f8..3c65274667c 100644 --- a/gems/aws-sdk-core/spec/aws/credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credentials_spec.rb @@ -13,7 +13,7 @@ module Aws expect(Credentials.new('akid', 'secret').secret_access_key).to eq('secret') end - it 'provides access to the session tokey' do + it 'provides access to the session token' do creds = Credentials.new('akid', 'secret', 'token') expect(creds.session_token).to eq('token') end @@ -22,6 +22,21 @@ module Aws expect(Credentials.new('akid', 'secret').session_token).to be(nil) end + it 'takes extra properties after session token' do + expect do + Credentials.new('akid', 'secret', nil, foo: 'bar') + end.to_not raise_error + end + + it 'provides access to the account id' do + creds = Credentials.new('akid', 'secret', account_id: 'account_id') + expect(creds.account_id).to eq('account_id') + end + + it 'defaults the account id to nil' do + expect(Credentials.new('akid', 'secret').account_id).to be(nil) + end + describe '#set?' do it 'returns true when the key and secret are both non nil values' do diff --git a/gems/aws-sdk-core/spec/aws/shared_config_spec.rb b/gems/aws-sdk-core/spec/aws/shared_config_spec.rb index 73962b9fed9..193877d5ff0 100644 --- a/gems/aws-sdk-core/spec/aws/shared_config_spec.rb +++ b/gems/aws-sdk-core/spec/aws/shared_config_spec.rb @@ -146,6 +146,17 @@ module Aws end end + context 'account_id_endpoint_mode selection' do + it 'can resolve account_id_endpoint_mode from config file' do + config = SharedConfig.new( + config_path: mock_config_file, + config_enabled: true, + profile_name: 'account_id_endpoint_mode' + ) + expect(config.account_id_endpoint_mode).to eq('disabled') + end + end + context 'ca_bundle selection' do it 'can resolve ca_bundle from config file' do config = SharedConfig.new( diff --git a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config index d6f08fba9bc..06e4accb84a 100644 --- a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config +++ b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config @@ -6,6 +6,7 @@ region = us-east-1 aws_access_key_id = ACCESS_KEY_SHARED aws_secret_access_key = SECRET_KEY_SHARED aws_session_token = TOKEN_SHARED +aws_account_id = ACCOUNT_ID_SHARED [profile assumerole_prof] role_arn = arn:aws:iam:123456789012:role/foo @@ -111,6 +112,9 @@ aws_access_key_id = ACCESS_KEY_ARPC aws_secret_access_key = SECRET_KEY_ARPC aws_session_token = TOKEN_ARPC +[profile account_id_endpoint_mode] +account_id_endpoint_mode = disabled + [profile ca_bundle] ca_bundle = /path/to/bundle.crt From 3fe53e959820f204f9c9a9e214a42c51732103d6 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Tue, 24 Oct 2023 13:15:08 -0400 Subject: [PATCH 2/4] Credential provider tests --- .../aws-sdk-core/assume_role_credentials.rb | 12 +++-- .../assume_role_web_identity_credentials.rb | 13 +++--- .../lib/aws-sdk-core/process_credentials.rb | 3 +- .../lib/aws-sdk-core/sso_credentials.rb | 3 +- .../spec/aws/assume_role_credentials_spec.rb | 33 +++++++++---- ...sume_role_web_identity_credentials_spec.rb | 46 +++++++++++-------- .../aws/credential_provider_chain_spec.rb | 6 +-- .../aws/credential_resolution_chain_spec.rb | 34 +++++++------- .../spec/aws/process_credentials_spec.rb | 13 +++--- .../spec/aws/shared_credentials_spec.rb | 1 + .../spec/aws/sso_credentials_spec.rb | 10 +++- .../credentials/mock_shared_credentials | 1 + 12 files changed, 107 insertions(+), 68 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 7f7ecc0f825..981025daab6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -62,13 +62,15 @@ def initialize(options = {}) private def refresh - c = @client.assume_role(@assume_role_params).credentials + c = @client.assume_role(@assume_role_params) + creds = c.credentials @credentials = Credentials.new( - c.access_key_id, - c.secret_access_key, - c.session_token + creds.access_key_id, + creds.secret_access_key, + creds.session_token, + account_id: ARNParser.parse(c.assumed_role_user.arn).account_id ) - @expiration = c.expiration + @expiration = creds.expiration end class << self diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 9d9c44c93e9..c424885055b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -73,14 +73,15 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - c = @client.assume_role_with_web_identity( - @assume_role_web_identity_params).credentials + c = @client.assume_role_with_web_identity(@assume_role_web_identity_params) + creds = c.credentials @credentials = Credentials.new( - c.access_key_id, - c.secret_access_key, - c.session_token + creds.access_key_id, + creds.secret_access_key, + creds.session_token, + account_id: ARNParser.parse(c.assumed_role_user.arn).account_id ) - @expiration = c.expiration + @expiration = creds.expiration end def _token_from_file(path) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 0a778ef8423..b9a2ae3ec80 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -59,7 +59,8 @@ def _parse_payload_format_v1(creds_json) creds = Credentials.new( creds_json['AccessKeyId'], creds_json['SecretAccessKey'], - creds_json['SessionToken'] + creds_json['SessionToken'], + account_id: creds_json['AccountId'] ) @expiration = creds_json['Expiration'] ? Time.iso8601(creds_json['Expiration']) : nil diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 5613d357470..3c4785f5c8c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -156,7 +156,8 @@ def refresh @credentials = Credentials.new( c.access_key_id, c.secret_access_key, - c.session_token + c.session_token, + account_id: @sso_account_id ) @expiration = Time.at(c.expiration / 1000.0) end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index 2f16c518777..bd24099289a 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -5,28 +5,43 @@ module Aws describe AssumeRoleCredentials do - let(:client) { + let(:client) do STS::Client.new( region: 'us-east-1', credentials: credentials, stub_responses: true ) - } + end let(:in_one_hour) { Time.now + 60 * 60 } let(:expiration) { in_one_hour } - let(:credentials) { - double('credentials', + let(:credentials) do + double( + 'credentials', access_key_id: 'akid', secret_access_key: 'secret', session_token: 'session', - expiration: expiration, + expiration: expiration ) - } + end - let(:resp) { double('client-resp', credentials: credentials) } + let(:assumed_role_user) do + double( + 'assumed_role_user', + arn: 'arn:aws:sts::123456789001:assumed-role/assume-role-test/Name', + assumed_role_id: 'role id' + ) + end + + let(:resp) do + double( + 'client-resp', + credentials: credentials, + assumed_role_user: assumed_role_user + ) + end before(:each) do allow(STS::Client).to receive(:new).and_return(client) @@ -93,11 +108,13 @@ module Aws it 'extracts credentials from the assume role response' do c = AssumeRoleCredentials.new( role_arn: 'arn', - role_session_name: 'session') + role_session_name: 'session' + ) expect(c).to be_set expect(c.credentials.access_key_id).to eq('akid') expect(c.credentials.secret_access_key).to eq('secret') expect(c.credentials.session_token).to eq('session') + expect(c.credentials.account_id).to eq('123456789001') expect(c.expiration).to eq(in_one_hour) end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 19dab462283..3118e445ec1 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -5,44 +5,49 @@ module Aws describe AssumeRoleWebIdentityCredentials do - let(:client) { + let(:client) do STS::Client.new( region: 'us-west-2', credentials: credentials, stub_responses: true ) - } + end let(:in_one_hour) { Time.now + 60 * 60 } let(:expiration) { in_one_hour } - let(:credentials) { - double('credentials', + let(:credentials) do + double( + 'credentials', access_key_id: 'akid', secret_access_key: 'secret', session_token: 'session', - expiration: expiration, + expiration: expiration ) - } - - let(:token_file) { - Tempfile.new("token.jwt") - } + end - let(:token_file_path) { - token_file.path - } + let(:assumed_role_user) do + double( + 'assumed_role_user', + arn: 'arn:aws:sts::123456789001:assumed-role/assume-role-test/Name', + assumed_role_id: 'role id' + ) + end - let(:uuid) { - "2d931510-d99f-494a-8c67-87feb05e1594" - } + let(:token_file) { Tempfile.new('token.jwt') } + let(:token_file_path) { token_file.path } + let(:uuid) { '2d931510-d99f-494a-8c67-87feb05e1594' } - let(:generate_name) { - Base64.strict_encode64(uuid) - } + let(:generate_name) { Base64.strict_encode64(uuid) } - let(:resp) {double('client-resp', credentials: credentials)} + let(:resp) do + double( + 'client-resp', + credentials: credentials, + assumed_role_user: assumed_role_user + ) + end before(:each) do allow(STS::Client).to receive(:new).and_return(client) @@ -160,6 +165,7 @@ module Aws expect(c.credentials.access_key_id).to eq('akid') expect(c.credentials.secret_access_key).to eq('secret') expect(c.credentials.session_token).to eq('session') + expect(c.credentials.account_id).to eq('123456789001') expect(c.expiration).to eq(in_one_hour) end diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 3d9a19c92cf..89debf334b8 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -96,7 +96,7 @@ def validate_credentials(expected_creds) end it 'hydrates credentials from ENV with prefix AMAZON_' do - expected_creds = random_creds + expected_creds = random_creds.merge(account_id: nil) ENV['AMAZON_ACCESS_KEY_ID'] = expected_creds[:access_key_id] ENV['AMAZON_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] ENV['AMAZON_SESSION_TOKEN'] = expected_creds[:session_token] @@ -104,14 +104,14 @@ def validate_credentials(expected_creds) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY & AWS_SECRET_KEY' do - expected_creds = random_creds.merge(session_token: nil) + expected_creds = random_creds.merge(session_token: nil, account_id: nil) ENV['AWS_ACCESS_KEY'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY_ID & AWS_SECRET_KEY' do - expected_creds = random_creds.merge(session_token: nil) + expected_creds = random_creds.merge(session_token: nil, account_id: nil) ENV['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 8cddbc7ae58..47c26fd6417 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -66,7 +66,7 @@ module Aws 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' ) assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'ACCESS_KEY_1', # from 'fooprofile' 'AR_AKID', 'AR_SECRET', @@ -80,7 +80,7 @@ module Aws it 'prefers assume role web identity over sso' do assume_role_web_identity_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'AR_AKID', 'AR_SECRET', 'AR_TOKEN' @@ -214,7 +214,7 @@ module Aws it 'prefers assume role over shared config' do assume_role_stub( - 'arn:aws:iam:123456789012:role/bar', + 'arn:aws:iam::123456789012:role/bar', 'ACCESS_KEY_1', # from 'fooprofile' 'AR_AKID', 'AR_SECRET', @@ -345,13 +345,13 @@ module Aws it 'supports :source_profile from assume_role_web_identity' do assume_role_web_identity_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'AR_AKID_WEB', 'AR_SECRET', 'AR_TOKEN' ) assume_role_stub( - 'arn:aws:iam:123456789012:role/bar', + 'arn:aws:iam::123456789012:role/bar', 'AR_AKID_WEB', # from web_only 'AR_AKID', 'AR_SECRET', @@ -372,7 +372,7 @@ module Aws it 'supports :source_profile from process credentials' do assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'AK_PROC1', 'AK_PROC1', 'SECRET_AK_PROC1', @@ -406,7 +406,7 @@ module Aws .and_return(double('SSOToken', set?: true)) assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'SSO_AKID', 'AR_AKID', 'SECRET_AK', @@ -423,7 +423,7 @@ module Aws it 'supports assume role chaining' do assume_role_stub( - 'arn:aws:iam:123456789012:role/role_b', + 'arn:aws:iam::123456789012:role/role_b', 'ACCESS_KEY_BASE', 'AK_1', 'SECRET_AK_1', @@ -431,7 +431,7 @@ module Aws ) assume_role_stub( - 'arn:aws:iam:123456789012:role/role_a', + 'arn:aws:iam::123456789012:role/role_a', 'AK_1', 'AK_2', 'SECRET_AK_2', @@ -448,7 +448,7 @@ module Aws it 'uses source credentials when source and static are both set' do assume_role_stub( - 'arn:aws:iam:123456789012:role/role_a', + 'arn:aws:iam::123456789012:role/role_a', 'ACCESS_KEY_BASE', 'AK_2', 'SECRET_AK_2', @@ -465,7 +465,7 @@ module Aws it 'uses static credentials when the profile self references' do assume_role_stub( - 'arn:aws:iam:123456789012:role/role_a', + 'arn:aws:iam::123456789012:role/role_a', 'ACCESS_KEY_SELF', 'AK_2', 'SECRET_AK_2', @@ -507,7 +507,7 @@ module Aws it 'will assume a role from shared credentials before shared config' do assume_role_stub( - 'arn:aws:iam:123456789012:role/bar', + 'arn:aws:iam::123456789012:role/bar', 'ACCESS_KEY_1', # from 'fooprofile' 'AR_AKID', 'AR_SECRET', @@ -523,7 +523,7 @@ module Aws it 'will then try to assume a role from shared config' do assume_role_stub( - 'arn:aws:iam:123456789012:role/bar', + 'arn:aws:iam::123456789012:role/bar', 'ACCESS_KEY_ARPC', # from 'ar_from_self' 'AR_AKID', 'AR_SECRET', @@ -539,7 +539,7 @@ module Aws it 'assumes a role from config using source in shared credentials' do assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'ACCESS_KEY_1', # from 'creds_from_sc' 'AR_AKID', 'AR_SECRET', @@ -555,7 +555,7 @@ module Aws it 'allows region to be resolved when unspecified' do assume_role_stub( - 'arn:aws:iam:123456789012:role/bar', + 'arn:aws:iam::123456789012:role/bar', 'ACCESS_KEY_ARPC', 'AR_AKID', 'AR_SECRET', @@ -590,7 +590,7 @@ module Aws } JSON assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'ACCESS_KEY_EC2', 'AR_AKID', 'AR_SECRET', @@ -634,7 +634,7 @@ module Aws stub_request(:get, "http://169.254.170.2#{path}") .to_return(status: 200, body: resp) assume_role_stub( - 'arn:aws:iam:123456789012:role/foo', + 'arn:aws:iam::123456789012:role/foo', 'ACCESS_KEY_ECS', 'AR_AKID', 'AR_SECRET', diff --git a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb index f7f6b9c44e9..8133ea80290 100644 --- a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb @@ -11,40 +11,41 @@ module Aws end it 'will read credentials from a process' do - creds = ProcessCredentials.new('echo \'{"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1"}\'').credentials + creds = ProcessCredentials.new('echo \'{"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}\'').credentials expect(creds.access_key_id).to eq('AK_PROC1') expect(creds.secret_access_key).to eq('SECRET_AK_PROC1') expect(creds.session_token).to eq('TOKEN_PROC1') + expect(creds.account_id).to eq('ACCOUNT_ID_PROC1') end it 'will throw an error when invalid JSON is returned' do expect { - creds = ProcessCredentials.new('echo \'{"Version":3,"AccessKeyId":"","SecretAccessKey":"","SessionToken":""\'').credentials + ProcessCredentials.new('echo \'{"Version":1,"AccessKeyId":"","SecretAccessKey":""\'').credentials }.to raise_error(Errors::InvalidProcessCredentialsPayload) end it 'will throw an error when the process credentials payload version is invalid' do expect { - creds = ProcessCredentials.new('echo \'{"Version":3,"AccessKeyId":"","SecretAccessKey":"","SessionToken":""}\'').credentials + ProcessCredentials.new('echo \'{"Version":3,"AccessKeyId":"","SecretAccessKey":""}\'').credentials }.to raise_error(Errors::InvalidProcessCredentialsPayload) end it 'will throw an error when the process credentials payload is malformed' do expect { - creds = ProcessCredentials.new('echo \'{"Version":1}\'').credentials + ProcessCredentials.new('echo \'{"Version":1}\'').credentials }.to raise_error(Errors::InvalidProcessCredentialsPayload) end it 'will throw an error and expose the stderr output when the credential process has a nonzero exit status' do expect { - creds = ProcessCredentials.new('>&2 echo "Credential Provider Error"; false').credentials + ProcessCredentials.new('>&2 echo "Credential Provider Error"; false').credentials }.to raise_error(Errors::InvalidProcessCredentialsPayload) .and output("Credential Provider Error\n").to_stderr_from_any_process end it 'will throw an error when the credential process cant be found' do expect { - creds = ProcessCredentials.new('fake_proc').credentials + ProcessCredentials.new('fake_proc').credentials }.to raise_error(Errors::InvalidProcessCredentialsPayload) end end diff --git a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb index f05d08eea77..1b0ca3f48fc 100644 --- a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb @@ -25,6 +25,7 @@ module Aws expect(creds.access_key_id).to eq('ACCESS_KEY_0') expect(creds.secret_access_key).to eq('SECRET_KEY_0') expect(creds.session_token).to eq('TOKEN_0') + expect(creds.account_id).to eq('ACCOUNT_ID_0') end it 'supports fetching profiles from ENV' do diff --git a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb index 0ebd50cf557..5cc05286a6d 100644 --- a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb @@ -12,7 +12,7 @@ module Aws ) end - let(:time) { Time.at(Time.now.to_i) } + let(:time) { Time.now.round } let(:in_one_hour) { time + 60 * 60 } let(:one_hour_ago) { time - 60 * 60 } let(:expiration) { in_one_hour } @@ -117,6 +117,10 @@ def mock_token_file(start_url, cached_token) ).and_call_original sso_creds = SSOCredentials.new(sso_opts) expect(sso_creds.credentials.access_key_id).to eq('akid') + expect(sso_creds.credentials.secret_access_key).to eq('secret') + expect(sso_creds.credentials.session_token).to eq('session') + expect(sso_creds.credentials.account_id).to eq(sso_account_id) + expect(sso_creds.expiration).to eq(expiration) end it 'calls the TokenProvider to get a new token for each refresh' do @@ -259,6 +263,10 @@ def mock_token_file(start_url, cached_token) ).and_call_original sso_creds = SSOCredentials.new(sso_opts) expect(sso_creds.credentials.access_key_id).to eq('akid') + expect(sso_creds.credentials.secret_access_key).to eq('secret') + expect(sso_creds.credentials.session_token).to eq('session') + expect(sso_creds.credentials.account_id).to eq(sso_account_id) + expect(sso_creds.expiration).to eq(expiration) end it 'reads a new token from disc for each refresh' do diff --git a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_credentials b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_credentials index b164395aa9d..dcad9812b6e 100644 --- a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_credentials +++ b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_credentials @@ -2,6 +2,7 @@ aws_access_key_id = ACCESS_KEY_0 aws_secret_access_key = SECRET_KEY_0 aws_session_token = TOKEN_0 +aws_account_id = ACCOUNT_ID_0 [fooprofile] aws_access_key_id = ACCESS_KEY_1 From 20c1cca9617a90f3fa006610588500bcbbeccf7c Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Tue, 24 Oct 2023 13:31:04 -0400 Subject: [PATCH 3/4] Endpoint mode tests --- .../endpoint_provider_spec_class.mustache | 2 +- .../aws/plugins/regional_endpoint_spec.rb | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache b/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache index a610601784f..c80760fa532 100644 --- a/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache +++ b/build_tools/aws-sdk-code-generator/templates/spec/endpoint_provider_spec_class.mustache @@ -11,7 +11,7 @@ module {{module_name}} subject { {{module_name}}::EndpointProvider.new } {{#endpoint_tests}} - context '{{{documentation}}}' do + context "{{{documentation}}}" do let(:expected) do {{{expect}}} end diff --git a/gems/aws-sdk-core/spec/aws/plugins/regional_endpoint_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/regional_endpoint_spec.rb index 7da82fda205..5953d76337c 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/regional_endpoint_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/regional_endpoint_spec.rb @@ -341,6 +341,28 @@ module Plugins expect(client.config.use_fips_endpoint).to eq false end end + + describe 'account id endpoint mode option' do + it 'is configured to use preferred by default' do + client = client_class.new(region: region) + expect(client.config.account_id_endpoint_mode).to eq 'preferred' + end + + it 'can be configured using shared config' do + allow_any_instance_of(Aws::SharedConfig) + .to receive(:account_id_endpoint_mode).and_return('disabled') + client = client_class.new(region: region) + expect(client.config.account_id_endpoint_mode).to eq 'disabled' + end + + it 'can be configured using ENV with precedence over shared config' do + allow_any_instance_of(Aws::SharedConfig) + .to receive(:account_id_endpoint_mode).and_return('disabled') + ENV['AWS_ACCOUNT_ID_ENDPOINT_MODE'] = 'required' + client = client_class.new(region: region) + expect(client.config.account_id_endpoint_mode).to eq 'required' + end + end end end end From c391f25ea331104f0589298b023dd84b967b7142 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Mon, 19 Feb 2024 15:41:16 -0500 Subject: [PATCH 4/4] Add endpoint mode --- .../lib/aws-sdk-code-generator/views/endpoints_module.rb | 4 +++- .../views/spec/endpoint_provider_spec_class.rb | 2 ++ services.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb index b2406e4cd95..3397c226856 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb @@ -131,7 +131,9 @@ def built_in_client_context_param_value(param_data) 'context.config.use_dualstack_endpoint' end when 'AWS::Auth::AccountId' - "context.config.account_id_endpoint_mode == 'disabled' ? nil : context.config.credentials.credentials.account_id" + 'context.config.credentials.credentials.account_id' + when 'AWS::Auth::AccountIdEndpointMode' + 'context.config.account_id_endpoint_mode' when 'AWS::STS::UseGlobalEndpoint' "context.config.sts_regional_endpoints == 'legacy'" when 'AWS::S3::UseGlobalEndpoint' diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb index 2fbc57c9200..0ab96126c5d 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb @@ -165,6 +165,8 @@ def built_in_to_param(built_in, value) "Aws::Credentials.new('stubbed-akid', 'stubbed-secret', account_id: '#{value}')", true ) + when 'AWS::Auth::AccountIdEndpointMode' + Param.new('account_id_endpoint_mode', value) when 'AWS::STS::UseGlobalEndpoint' Param.new('sts_regional_endpoints', value ? 'legacy' : 'regional') when 'AWS::S3::UseGlobalEndpoint' diff --git a/services.json b/services.json index f4dd4216861..0301386c90b 100644 --- a/services.json +++ b/services.json @@ -390,7 +390,7 @@ }, "EC2": { "models": "ec2/2016-11-15", - "addPlugins": [ser + "addPlugins": [ "Aws::EC2::Plugins::CopyEncryptedSnapshot", "Aws::EC2::Plugins::RegionValidation" ]