Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Auth trait for Sigv4a #2923

Merged
merged 28 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d68609b
Update fixtures to latest and add auth/unsigned payload where appropr…
mullermp Oct 4, 2023
6be90dd
Auth and unsignedPayload trait support
mullermp Oct 4, 2023
9278d7c
Endpoints.rb changes
mullermp Oct 4, 2023
701d303
Fix tests from updating fixtures
mullermp Oct 6, 2023
16a3f74
S3 and S3v4 case for endpoint properties
mullermp Oct 6, 2023
c6180ab
Update sign and transfer encoding to handle unsigned payload
mullermp Oct 6, 2023
7c94142
Add build tests for transfer_encoding and unsigned payload, rename le…
mullermp Oct 9, 2023
18af4bb
Undo transfer encoding changes. Fix build. Improve sigv4a region test
mullermp Oct 11, 2023
3ea47d4
Remove unsignedPayload
mullermp Oct 11, 2023
d13887b
sigv4a signing region set config and tests
mullermp Oct 11, 2023
7463baf
Add changelog and minimum core version
mullermp Oct 11, 2023
ad89f93
Merge branch 'version-3' into auth-trait
mullermp Oct 11, 2023
b9a609f
PR feedback
mullermp Oct 13, 2023
384fdca
Merge branch 'version-3' into auth-trait
mullermp Jun 24, 2024
c0f77a1
Fix tests potentially
mullermp Jun 24, 2024
3309d6c
Update noAuth
mullermp Jun 24, 2024
1ceea74
Potentially fix rbs
mullermp Jun 24, 2024
d91e2b5
Sync models
mullermp Jun 24, 2024
9921865
Update fixtures
mullermp Jun 24, 2024
cd13ec4
Fix ddb fixture
mullermp Jun 24, 2024
8cdc0d2
Merge branch 'version-3' into auth-trait
mullermp Jun 24, 2024
81e2c42
Revert "Sync models"
mullermp Jun 24, 2024
b78628c
version-3 models
mullermp Jun 24, 2024
67e5f1e
Fix tests
mullermp Jun 24, 2024
c7bf874
Merge branch 'version-3' into auth-trait
mullermp Jun 25, 2024
32c3a6b
Latest models
mullermp Jun 25, 2024
775896e
Revert "Latest models"
mullermp Jun 25, 2024
cbf00c8
Merge branch 'version-3' into auth-trait
mullermp Jun 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def initialize(options)
@protocol_settings = api.fetch('metadata')['protocolSettings'] || {}
@api_version = api.fetch('metadata')['apiVersion']
@signature_version = api.fetch('metadata')['signatureVersion']
@auth = api.fetch('metadata')['auth']
@full_name = api.fetch('metadata')['serviceFullName']
@short_name = api.fetch('metadata')['serviceAbbreviation'] || @full_name
@require_endpoint_discovery = api.fetch('operations', []).any? do |_, o|
Expand Down Expand Up @@ -136,6 +137,9 @@ def included_in_core?
# @return [String] The signature version, e.g. "v4"
attr_reader :signature_version

# @return [Array<String>] A list of supported auth types
attr_reader :auth

# @return [String] The full product name for the service,
# e.g. "Amazon Simple Storage Service".
attr_reader :full_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class ClientApiModule < View
# keep all
'endpointPrefix' => true,
'signatureVersion' => true,
'auth' => true,
'signingName' => true,
'serviceFullName' => true,
'protocol' => true,
Expand Down Expand Up @@ -246,6 +247,7 @@ def operations
end
o.authorizer = operation['authorizer'] if operation.key?('authorizer')
o.authtype = operation['authtype'] if operation.key?('authtype')
o.auth = operation['auth'] if operation.key?('auth')
o.require_apikey = operation['requiresApiKey'] if operation.key?('requiresApiKey')
o.pager = pager(operation_name)
o.async = @service.protocol_settings['h2'] == 'eventstream' &&
Expand Down Expand Up @@ -581,6 +583,9 @@ def initialize
# @return [String,nil]
attr_accessor :authtype

# @return [Array<String>]
attr_accessor :auth

# @return [Boolean]
attr_accessor :endpoint_trait

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
describe 'Client Interface:' do
describe 'SignatureVersion: bearer' do
before(:all) do
SpecHelper.generate_service(['BearerAuth'], multiple_files: false)
SpecHelper.generate_service(['LegacySignBearerAuth'], multiple_files: false)
end

let(:token) { 'token' }

let(:token_provider) { Aws::StaticTokenProvider.new(token) }

let(:client) do
BearerAuth::Client.new(
LegacySignBearerAuth::Client.new(
region: 'us-west-2',
stub_responses: true,
token_provider: token_provider,
Expand Down Expand Up @@ -51,15 +51,15 @@

describe 'SignatureVersion: v4' do
before(:all) do
SpecHelper.generate_service(['V4WithBearer'], multiple_files: false)
SpecHelper.generate_service(['LegacySignV4WithBearer'], multiple_files: false)
end

let(:token) { 'token' }

let(:token_provider) { Aws::StaticTokenProvider.new(token) }

let(:client) do
V4WithBearer::Client.new(
LegacySignV4WithBearer::Client.new(
region: 'us-west-2',
stub_responses: true,
token_provider: token_provider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@
end

let(:client) do
TransferEncoding::Client.new(
region: 'us-west-2',
access_key_id: 'akid',
secret_access_key: 'secret',
stub_responses: true,
endpoint: 'https://svc.us-west-2.amazonaws.com'
)
TransferEncoding::Client.new(stub_responses: true)
end

it 'adds `Transfer-Encoding` header for `v4-unsigned-body` auth types' do
Expand Down Expand Up @@ -69,6 +63,5 @@
resp = client.non_streaming(body: 'heyhey')
expect(resp.context.http_request.headers['Content-Length']).to eq('19')
end

end
end
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ module {{module_name}}
{{#authtype}}
o['authtype'] = "{{.}}"
{{/authtype}}
{{#auth}}
o['auth'] = {{&auth}}
{{/auth}}
{{#endpoint_trait}}
o.endpoint_pattern = {
{{#endpoint_pattern}}
Expand Down
9 changes: 8 additions & 1 deletion build_tools/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ 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"
Expand Down Expand Up @@ -151,6 +151,13 @@ def gem_dependencies(api, dependencies)
core_version_string = "', '>= #{min_core}"
dependencies['aws-sdk-core'] = "~> #{version_file.split('.')[0]}#{core_version_string}"

api['metadata'].fetch('auth', []).each do |auth|
if %w[aws.auth#sigv4 aws.auth#sigv4a].include?(auth)
dependencies['aws-sigv4'] = '~> 1.1'
mullermp marked this conversation as resolved.
Show resolved Hide resolved
end
end

# deprecated auth but a reasonable fallback
case api['metadata']['signatureVersion']
when 'v4' then dependencies['aws-sigv4'] = '~> 1.1'
when 'v2' then dependencies['aws-sigv2'] = '~> 1.0'
Expand Down
4 changes: 4 additions & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Unreleased Changes
------------------

* Feature - Support `auth` trait to enable SigV4a based services.

* Feature - Support configuration for sigv4a signing regions using `ENV['AWS_SIGV4A_SIGNING_REGION_SET']`, `sigv4a_signing_region_set` shared config, or the `sigv4a_signing_region_set` client option.

3.185.1 (2023-10-05)
------------------

Expand Down
72 changes: 54 additions & 18 deletions gems/aws-sdk-core/lib/aws-sdk-core/endpoints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,60 @@ def resolve_auth_scheme(context, endpoint)

private

def merge_signing_defaults(auth_scheme, config)
if %w[sigv4 sigv4a].include?(auth_scheme['name'])
auth_scheme['signingName'] ||= sigv4_name(config)
if auth_scheme['name'] == 'sigv4a'
auth_scheme['signingRegionSet'] ||= config.sigv4a_signing_region_set
mullermp marked this conversation as resolved.
Show resolved Hide resolved
else
auth_scheme['signingRegion'] ||= config.region
end
end
auth_scheme
end

def sigv4_name(config)
config.api.metadata['signingName'] ||
config.api.metadata['endpointPrefix']
end

def default_auth_scheme(context)
case default_api_authtype(context)
if (auth_list = default_api_auth(context))
auth = auth_list.first
mullermp marked this conversation as resolved.
Show resolved Hide resolved
case auth
when 'aws.auth#sigv4', 'aws.auth#sigv4a'
auth_scheme = { 'name' => auth.split('#').last }
if s3_or_s3v4_signature_version?(context)
auth_scheme = auth_scheme.merge(
'disableDoubleEncoding' => true,
'disableNormalizePath' => true
)
end
merge_signing_defaults(auth_scheme, context.config)
when 'smithy.api#httpBearerAuth'
{ 'name' => 'bearer' }
when 'smithy.auth#noAuth'
{ 'name' => 'none' }
end
else
legacy_default_auth_scheme(context)
end
end

def default_api_auth(context)
context.config.api.operation(context.operation_name)['auth'] ||
context.config.api.metadata['auth']
end

def s3_or_s3v4_signature_version?(context)
%w[s3 s3v4].include?(context.config.api.metadata['signatureVersion'])
end

# Legacy auth resolution - looks for deprecated signatureVersion
# and authType traits.

def legacy_default_auth_scheme(context)
case legacy_default_api_authtype(context)
when 'v4', 'v4-unsigned-body'
auth_scheme = { 'name' => 'sigv4' }
merge_signing_defaults(auth_scheme, context.config)
Expand All @@ -52,27 +104,11 @@ def default_auth_scheme(context)
end
end

def merge_signing_defaults(auth_scheme, config)
if %w[sigv4 sigv4a].include?(auth_scheme['name'])
auth_scheme['signingName'] ||= sigv4_name(config)
if auth_scheme['name'] == 'sigv4a'
auth_scheme['signingRegionSet'] ||= ['*']
else
auth_scheme['signingRegion'] ||= config.region
end
end
auth_scheme
end

def default_api_authtype(context)
def legacy_default_api_authtype(context)
context.config.api.operation(context.operation_name)['authtype'] ||
context.config.api.metadata['signatureVersion']
end

def sigv4_name(config)
config.api.metadata['signingName'] ||
config.api.metadata['endpointPrefix']
end
end
end
end
9 changes: 9 additions & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,15 @@ def initialize(*args)
end
end

# Raised when a client is constructed and the sigv4a region set is invalid.
# It is invalid when it is empty and/or contains empty strings.
class InvalidRegionSetError < ArgumentError
def initialize(*args)
msg = 'The provided sigv4a region set was empty or invalid.'
super(msg)
end
end

# Raised when a client is contsructed and the region is not valid.
class InvalidRegionError < ArgumentError
def initialize(*args)
Expand Down
31 changes: 28 additions & 3 deletions gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ class RegionalEndpoint < Seahorse::Client::Plugin
resolve_region(cfg)
end

option(:sigv4a_signing_region_set,
doc_type: Array,
docstring: <<-DOCS) do |cfg|
A list of regions that should be signed with SigV4a signing. When
not passed, a default `:sigv4a_signing_region_set` is searched for
in the following locations:

* `Aws.config[:sigv4a_signing_region_set]`
* `ENV['AWS_SIGV4A_SIGNING_REGION_SET']`
* `~/.aws/config`
DOCS
resolve_sigv4a_signing_region_set(cfg)
end

option(:use_dualstack_endpoint,
doc_type: 'Boolean',
docstring: <<-DOCS) do |cfg|
Expand Down Expand Up @@ -65,9 +79,13 @@ class RegionalEndpoint < Seahorse::Client::Plugin
end

def after_initialize(client)
if client.config.region.nil? || client.config.region == ''
raise Errors::MissingRegionError
end
region = client.config.region
raise Errors::MissingRegionError if region.nil? || region == ''

region_set = client.config.sigv4a_signing_region_set
raise Errors::InvalidRegionSetError if region_set.nil? || region_set.empty?
region_set = region_set.compact.reject(&:empty?)
client.config.sigv4a_signing_region_set = region_set
end

class << self
Expand All @@ -81,6 +99,13 @@ def resolve_region(cfg)
env_region || cfg_region
end

def resolve_sigv4a_signing_region_set(cfg)
value = ENV['AWS_SIGV4A_SIGNING_REGION_SET']
value ||= Aws.shared_config.sigv4a_signing_region_set(profile: cfg.profile)
value ||= cfg.region || ''
mullermp marked this conversation as resolved.
Show resolved Hide resolved
value.split(',')
end

def resolve_use_dualstack_endpoint(cfg)
value = ENV['AWS_USE_DUALSTACK_ENDPOINT']
value ||= Aws.shared_config.use_dualstack_endpoint(
Expand Down
2 changes: 1 addition & 1 deletion gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def initialize(auth_scheme, config, region_override = nil)
end

region = if scheme_name == 'sigv4a'
auth_scheme['signingRegionSet'].first
auth_scheme['signingRegionSet'].join(',')
mullermp marked this conversation as resolved.
Show resolved Hide resolved
else
auth_scheme['signingRegion']
end
Expand Down
1 change: 1 addition & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ def self.config_reader(*attrs)

config_reader(
:region,
:sigv4a_signing_region_set,
:ca_bundle,
:credential_process,
:endpoint_discovery_enabled,
Expand Down
Loading
Loading