Skip to content

Commit 0d9a603

Browse files
authored
Support auth scheme preference config (#3268)
1 parent da47b00 commit 0d9a603

File tree

9 files changed

+253
-124
lines changed

9 files changed

+253
-124
lines changed

gems/aws-sdk-core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Unreleased Changes
22
------------------
33

4+
* Feature - Support an auth scheme signing preference list using `ENV['AWS_AUTH_SCHEME_PREFERENCE']` or `auth_scheme_preference` in shared configuration.
5+
46
* Feature - Support metric tracking for Bedrock Bearer tokens.
57

68
3.226.3 (2025-07-17)

gems/aws-sdk-core/lib/aws-sdk-core/endpoints.rb

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,28 @@
1919
module Aws
2020
# @api private
2121
module Endpoints
22-
SUPPORTED_AUTH_TRAITS = %w[
23-
aws.auth#sigv4
24-
aws.auth#sigv4a
25-
smithy.api#httpBearerAuth
26-
smithy.api#noAuth
27-
].freeze
22+
# Maps config auth scheme preferences to endpoint auth scheme names.
23+
ENDPOINT_AUTH_PREFERENCE_MAP = {
24+
'sigv4' => %w[sigv4 sigv4-s3express],
25+
'sigv4a' => ['sigv4a'],
26+
'httpBearerAuth' => ['bearer'],
27+
'noAuth' => ['none']
28+
}.freeze
29+
SUPPORTED_ENDPOINT_AUTH = ENDPOINT_AUTH_PREFERENCE_MAP.values.flatten.freeze
30+
31+
# Maps configured auth scheme preferences to modeled auth traits.
32+
MODELED_AUTH_PREFERENCE_MAP = {
33+
'sigv4' => 'aws.auth#sigv4',
34+
'sigv4a' => 'aws.auth#sigv4a',
35+
'httpBearerAuth' => 'smithy.api#httpBearerAuth',
36+
'noAuth' => 'smithy.api#noAuth'
37+
}.freeze
38+
SUPPORTED_MODELED_AUTH = MODELED_AUTH_PREFERENCE_MAP.values.freeze
2839

2940
class << self
3041
def resolve_auth_scheme(context, endpoint)
3142
if endpoint && (auth_schemes = endpoint.properties['authSchemes'])
32-
auth_scheme = auth_schemes.find do |scheme|
33-
Aws::Plugins::Sign::SUPPORTED_AUTH_TYPES.include?(scheme['name'])
34-
end
43+
auth_scheme = endpoint_auth_scheme_preference(auth_schemes, context.config.auth_scheme_preference)
3544
raise 'No supported auth scheme for this endpoint.' unless auth_scheme
3645

3746
merge_signing_defaults(auth_scheme, context.config)
@@ -42,6 +51,16 @@ def resolve_auth_scheme(context, endpoint)
4251

4352
private
4453

54+
def endpoint_auth_scheme_preference(auth_schemes, preferred_auth)
55+
ordered_auth = preferred_auth.each_with_object([]) do |pref, list|
56+
next unless ENDPOINT_AUTH_PREFERENCE_MAP.key?(pref)
57+
58+
ENDPOINT_AUTH_PREFERENCE_MAP[pref].each { |name| list << { 'name' => name } }
59+
end
60+
ordered_auth += auth_schemes
61+
ordered_auth.find { |auth| SUPPORTED_ENDPOINT_AUTH.include?(auth['name']) }
62+
end
63+
4564
def merge_signing_defaults(auth_scheme, config)
4665
if %w[sigv4 sigv4a sigv4-s3express].include?(auth_scheme['name'])
4766
auth_scheme['signingName'] ||= sigv4_name(config)
@@ -64,13 +83,12 @@ def merge_signing_defaults(auth_scheme, config)
6483
end
6584

6685
def sigv4_name(config)
67-
config.api.metadata['signingName'] ||
68-
config.api.metadata['endpointPrefix']
86+
config.api.metadata['signingName'] || config.api.metadata['endpointPrefix']
6987
end
7088

7189
def default_auth_scheme(context)
72-
if (auth_list = default_api_auth(context))
73-
auth = auth_list.find { |a| SUPPORTED_AUTH_TRAITS.include?(a) }
90+
if (modeled_auth = default_api_auth(context))
91+
auth = modeled_auth_scheme_preference(modeled_auth, context.config.auth_scheme_preference)
7492
case auth
7593
when 'aws.auth#sigv4', 'aws.auth#sigv4a'
7694
auth_scheme = { 'name' => auth.split('#').last }
@@ -93,6 +111,12 @@ def default_auth_scheme(context)
93111
end
94112
end
95113

114+
def modeled_auth_scheme_preference(modeled_auth, preferred_auth)
115+
ordered_auth = preferred_auth.map { |pref| MODELED_AUTH_PREFERENCE_MAP[pref] }.compact
116+
ordered_auth += modeled_auth
117+
ordered_auth.find { |auth| SUPPORTED_MODELED_AUTH.include?(auth) }
118+
end
119+
96120
def default_api_auth(context)
97121
context.config.api.operation(context.operation_name)['auth'] ||
98122
context.config.api.metadata['auth']

gems/aws-sdk-core/lib/aws-sdk-core/plugins/credentials_configuration.rb

Lines changed: 85 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,61 +17,66 @@ class CredentialsConfiguration < Seahorse::Client::Plugin
1717
option(:profile,
1818
doc_default: 'default',
1919
doc_type: String,
20-
docstring: <<-DOCS)
21-
Used when loading credentials from the shared credentials file
22-
at HOME/.aws/credentials. When not specified, 'default' is used.
20+
docstring: <<~DOCS)
21+
Used when loading credentials from the shared credentials file at `HOME/.aws/credentials`.
22+
When not specified, 'default' is used.
2323
DOCS
2424

2525
option(:credentials,
2626
required: true,
2727
doc_type: 'Aws::CredentialProvider',
2828
rbs_type: 'untyped',
29-
docstring: <<-DOCS
30-
Your AWS credentials. This can be an instance of any one of the
31-
following classes:
32-
33-
* `Aws::Credentials` - Used for configuring static, non-refreshing
34-
credentials.
35-
36-
* `Aws::SharedCredentials` - Used for loading static credentials from a
37-
shared file, such as `~/.aws/config`.
38-
39-
* `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
40-
41-
* `Aws::AssumeRoleWebIdentityCredentials` - Used when you need to
42-
assume a role after providing credentials via the web.
43-
44-
* `Aws::SSOCredentials` - Used for loading credentials from AWS SSO using an
45-
access token generated from `aws login`.
46-
47-
* `Aws::ProcessCredentials` - Used for loading credentials from a
48-
process that outputs to stdout.
49-
50-
* `Aws::InstanceProfileCredentials` - Used for loading credentials
51-
from an EC2 IMDS on an EC2 instance.
52-
53-
* `Aws::ECSCredentials` - Used for loading credentials from
54-
instances running in ECS.
55-
56-
* `Aws::CognitoIdentityCredentials` - Used for loading credentials
57-
from the Cognito Identity service.
58-
59-
When `:credentials` are not configured directly, the following
60-
locations will be searched for credentials:
61-
62-
* `Aws.config[:credentials]`
63-
* The `:access_key_id`, `:secret_access_key`, `:session_token`, and
64-
`:account_id` options.
65-
* ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'],
66-
ENV['AWS_SESSION_TOKEN'], and ENV['AWS_ACCOUNT_ID']
67-
* `~/.aws/credentials`
68-
* `~/.aws/config`
69-
* EC2/ECS IMDS instance profile - When used by default, the timeouts
70-
are very aggressive. Construct and pass an instance of
71-
`Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to
72-
enable retries and extended timeouts. Instance profile credential
73-
fetching can be disabled by setting ENV['AWS_EC2_METADATA_DISABLED']
74-
to true.
29+
docstring: <<~DOCS
30+
Your AWS credentials used for authentication. This can be an instance of any one of the
31+
following classes:
32+
33+
* `Aws::Credentials` - Used for configuring static, non-refreshing
34+
credentials.
35+
36+
* `Aws::SharedCredentials` - Used for loading static credentials from a
37+
shared file, such as `~/.aws/config`.
38+
39+
* `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
40+
41+
* `Aws::AssumeRoleWebIdentityCredentials` - Used when you need to
42+
assume a role after providing credentials via the web.
43+
44+
* `Aws::SSOCredentials` - Used for loading credentials from AWS SSO using an
45+
access token generated from `aws login`.
46+
47+
* `Aws::ProcessCredentials` - Used for loading credentials from a
48+
process that outputs to stdout.
49+
50+
* `Aws::InstanceProfileCredentials` - Used for loading credentials
51+
from an EC2 IMDS on an EC2 instance.
52+
53+
* `Aws::ECSCredentials` - Used for loading credentials from
54+
instances running in ECS.
55+
56+
* `Aws::CognitoIdentityCredentials` - Used for loading credentials
57+
from the Cognito Identity service.
58+
59+
When `:credentials` are not configured directly, the following
60+
locations will be searched for credentials:
61+
62+
* `Aws.config[:credentials]`
63+
64+
* The `:access_key_id`, `:secret_access_key`, `:session_token`, and
65+
`:account_id` options.
66+
67+
* `ENV['AWS_ACCESS_KEY_ID']`, `ENV['AWS_SECRET_ACCESS_KEY']`,
68+
`ENV['AWS_SESSION_TOKEN']`, and `ENV['AWS_ACCOUNT_ID']`.
69+
70+
* `~/.aws/credentials`
71+
72+
* `~/.aws/config`
73+
74+
* EC2/ECS IMDS instance profile - When used by default, the timeouts
75+
are very aggressive. Construct and pass an instance of
76+
`Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to
77+
enable retries and extended timeouts. Instance profile credential
78+
fetching can be disabled by setting `ENV['AWS_EC2_METADATA_DISABLED']`
79+
to `true`.
7580
DOCS
7681
) do |config|
7782
CredentialProviderChain.new(config).resolve
@@ -82,25 +87,40 @@ class CredentialsConfiguration < Seahorse::Client::Plugin
8287
option(:instance_profile_credentials_timeout, 1)
8388

8489
option(:token_provider,
85-
required: false,
86-
doc_type: 'Aws::TokenProvider',
87-
rbs_type: 'untyped',
88-
docstring: <<-DOCS
89-
A Bearer Token Provider. This can be an instance of any one of the
90-
following classes:
91-
92-
* `Aws::StaticTokenProvider` - Used for configuring static, non-refreshing
93-
tokens.
94-
95-
* `Aws::SSOTokenProvider` - Used for loading tokens from AWS SSO using an
96-
access token generated from `aws login`.
97-
98-
When `:token_provider` is not configured directly, the `Aws::TokenProviderChain`
99-
will be used to search for tokens configured for your profile in shared configuration files.
100-
DOCS
90+
doc_type: 'Aws::TokenProvider',
91+
rbs_type: 'untyped',
92+
docstring: <<~DOCS
93+
Your Bearer token used for authentication. This can be an instance of any one of the
94+
following classes:
95+
96+
* `Aws::StaticTokenProvider` - Used for configuring static, non-refreshing
97+
tokens.
98+
99+
* `Aws::SSOTokenProvider` - Used for loading tokens from AWS SSO using an
100+
access token generated from `aws login`.
101+
102+
When `:token_provider` is not configured directly, the `Aws::TokenProviderChain`
103+
will be used to search for tokens configured for your profile in shared configuration files.
104+
DOCS
101105
) do |config|
102106
TokenProviderChain.new(config).resolve
103107
end
108+
109+
option(:auth_scheme_preference,
110+
doc_type: 'Array<String>',
111+
rbs_type: 'Array[String]',
112+
docstring: <<~DOCS
113+
A list of preferred authentication schemes to use when making a request. Supported values are:
114+
`sigv4`, `sigv4a`, `httpBearerAuth`, and `noAuth`. When set using `ENV['AWS_AUTH_SCHEME_PREFERENCE']` or in
115+
shared config as `auth_scheme_preference`, the value should be a comma-separated list.
116+
DOCS
117+
) do |config|
118+
value =
119+
ENV['AWS_AUTH_SCHEME_PREFERENCE'] ||
120+
Aws.shared_config.auth_scheme_preference(profile: config.profile) ||
121+
''
122+
value.gsub(' ', '').gsub("\t", '').split(',')
123+
end
104124
end
105125
end
106126
end

gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ class Sign < Seahorse::Client::Plugin
1313
option(:sigv4_region)
1414
option(:unsigned_operations, default: [])
1515

16-
SUPPORTED_AUTH_TYPES = %w[sigv4 bearer sigv4-s3express sigv4a none].freeze
17-
1816
def add_handlers(handlers, cfg)
1917
operations = cfg.api.operation_names - cfg.unsigned_operations
2018
handlers.add(Handler, step: :sign, operations: operations)

gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def self.config_reader(*attrs)
203203
config_reader(
204204
:region,
205205
:account_id_endpoint_mode,
206+
:auth_scheme_preference,
206207
:sigv4a_signing_region_set,
207208
:ca_bundle,
208209
:credential_process,

0 commit comments

Comments
 (0)