Skip to content

Commit

Permalink
Remove CRT SigV4a
Browse files Browse the repository at this point in the history
  • Loading branch information
mullermp committed Sep 16, 2024
1 parent 1b44486 commit 409484b
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 222 deletions.
4 changes: 2 additions & 2 deletions build_tools/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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.205.0"
MINIMUM_CORE_VERSION = "3.206.0"

# Minimum `aws-sdk-core` version for new S3 gem builds
MINIMUM_CORE_VERSION_S3 = "3.205.0"
MINIMUM_CORE_VERSION_S3 = "3.206.0"

EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration"

Expand Down
2 changes: 2 additions & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Support `sigv4a` endpoint auth without CRT.

3.205.0 (2024-09-11)
------------------

Expand Down
2 changes: 1 addition & 1 deletion gems/aws-sdk-core/aws-sdk-core.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Gem::Specification.new do |spec|

spec.add_dependency('jmespath', '~> 1', '>= 1.6.1') # necessary for secure jmespath JSON parsing
spec.add_dependency('aws-partitions', '~> 1', '>= 1.651.0') # necessary for new endpoint resolution
spec.add_dependency('aws-sigv4', '~> 1.9') # necessary for s3 express auth/native sigv4a support
spec.add_dependency('aws-sigv4', '~> 1.10') # necessary for pure ruby sigv4a support
spec.add_dependency('aws-eventstream', '~> 1', '>= 1.3.0') # necessary for binary eventstream

spec.metadata = {
Expand Down
9 changes: 6 additions & 3 deletions gems/aws-sdk-core/lib/aws-sdk-core/endpoints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
module Aws
# @api private
module Endpoints
supported_auth_traits = %w[aws.auth#sigv4 smithy.api#httpBearerAuth smithy.api#noAuth]
supported_auth_traits += ['aws.auth#sigv4a'] if Aws::Sigv4::Signer.use_crt?
SUPPORTED_AUTH_TRAITS = supported_auth_traits.freeze
SUPPORTED_AUTH_TRAITS = %w[
aws.auth#sigv4
aws.auth#sigv4a
smithy.api#httpBearerAuth
smithy.api#noAuth
].freeze

class << self
def resolve_auth_scheme(context, endpoint)
Expand Down
4 changes: 0 additions & 4 deletions gems/aws-sdk-s3/features/client/step_definitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,6 @@ def create_bucket(options = {})
end

When(/I have access to an MRAP bucket and CRT/) do
unless Aws::Sigv4::Signer.use_crt?
pending("CRT is not available")
end

begin
@client.head_bucket(bucket: 'ruby-sdk-integtest-mrap-bucket')
rescue
Expand Down
4 changes: 0 additions & 4 deletions gems/aws-sdk-s3/spec/presigner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ def initialize(expiration_time)
end

it 'can sign with additional whitelisted headers' do
skip("CRT does not support whitelisting user-agent") if Aws::Sigv4::Signer.use_crt?

actual_url = subject.presigned_url(
:get_object,
bucket: 'examplebucket',
Expand Down Expand Up @@ -256,8 +254,6 @@ def initialize(expiration_time)
end

it 'can sign with additional whitelisted headers' do
skip("CRT is unable to whitelist user-agent") if Aws::Sigv4::Signer.use_crt?

actual_url, = subject.presigned_request(
:get_object,
bucket: 'examplebucket',
Expand Down
2 changes: 2 additions & 0 deletions gems/aws-sigv4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Remove CRT `sigv4a` signing capability.

1.9.1 (2024-07-29)
------------------

Expand Down
147 changes: 0 additions & 147 deletions gems/aws-sigv4/lib/aws-sigv4/signer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,6 @@ module Sigv4
# and `#session_token`.
#
class Signer

@@use_crt =
begin
require 'aws-crt'
true
rescue LoadError
false
end

# @overload initialize(service:, region:, access_key_id:, secret_access_key:, session_token:nil, **options)
# @param [String] :service The service signing name, e.g. 's3'.
# @param [String] :region The region name, e.g. 'us-east-1'. When signing
Expand Down Expand Up @@ -154,13 +145,6 @@ def initialize(options = {})
@signing_algorithm = options.fetch(:signing_algorithm, :sigv4)
@normalize_path = options.fetch(:normalize_path, true)
@omit_session_token = options.fetch(:omit_session_token, false)

if @signing_algorithm == 'sigv4-s3express'.to_sym &&
Signer.use_crt? && Aws::Crt::GEM_VERSION <= '0.1.9'
raise ArgumentError,
'This version of aws-crt does not support S3 Express. Please
update this gem to at least version 0.2.0.'
end
end

# @return [String]
Expand Down Expand Up @@ -236,9 +220,6 @@ def initialize(options = {})
# a `#headers` method. The headers must be applied to your request.
#
def sign_request(request)

return crt_sign_request(request) if Signer.use_crt?

creds, _ = fetch_credentials

http_method = extract_http_method(request)
Expand Down Expand Up @@ -344,7 +325,6 @@ def sign_request(request)
# signature value (a binary string) used at ':chunk-signature' needs to converted to
# hex-encoded string using #unpack
def sign_event(prior_signature, payload, encoder)
# Note: CRT does not currently provide event stream signing, so we always use the ruby implementation.
creds, _ = fetch_credentials
time = Time.now
headers = {}
Expand Down Expand Up @@ -431,9 +411,6 @@ def sign_event(prior_signature, payload, encoder)
# @return [HTTPS::URI, HTTP::URI]
#
def presign_url(options)

return crt_presign_url(options) if Signer.use_crt?

creds, expiration = fetch_credentials

http_method = extract_http_method(options)
Expand Down Expand Up @@ -801,131 +778,7 @@ def presigned_url_expiration(options, expiration, datetime)
end
end

### CRT Code

# the credentials used by CRT must be a
# CRT StaticCredentialsProvider object
def crt_fetch_credentials
creds, expiration = fetch_credentials
crt_creds = Aws::Crt::Auth::StaticCredentialsProvider.new(
creds.access_key_id,
creds.secret_access_key,
creds.session_token
)
[crt_creds, expiration]
end

def crt_sign_request(request)
creds, _ = crt_fetch_credentials
http_method = extract_http_method(request)
url = extract_url(request)
headers = downcase_headers(request[:headers])

datetime =
if headers.include? 'x-amz-date'
Time.parse(headers.delete('x-amz-date'))
end

content_sha256 = headers.delete('x-amz-content-sha256')
content_sha256 ||= sha256_hexdigest(request[:body] || '')

sigv4_headers = {}
sigv4_headers['host'] = headers['host'] || host(url)

# Modify the user-agent to add usage of crt-signer
# This should be temporary during developer preview only
if headers.include? 'user-agent'
headers['user-agent'] = "#{headers['user-agent']} crt-signer/#{@signing_algorithm}/#{Aws::Sigv4::VERSION}"
sigv4_headers['user-agent'] = headers['user-agent']
end

headers = headers.merge(sigv4_headers) # merge so we do not modify given headers hash

config = Aws::Crt::Auth::SigningConfig.new(
algorithm: @signing_algorithm,
signature_type: :http_request_headers,
region: @region,
service: @service,
date: datetime,
signed_body_value: content_sha256,
signed_body_header_type: @apply_checksum_header ?
:sbht_content_sha256 : :sbht_none,
credentials: creds,
unsigned_headers: @unsigned_headers,
use_double_uri_encode: @uri_escape_path,
should_normalize_uri_path: @normalize_path,
omit_session_token: @omit_session_token
)
http_request = Aws::Crt::Http::Message.new(
http_method, url.to_s, headers
)
signable = Aws::Crt::Auth::Signable.new(http_request)

signing_result = Aws::Crt::Auth::Signer.sign_request(config, signable)

Signature.new(
headers: sigv4_headers.merge(
downcase_headers(signing_result[:headers])
),
string_to_sign: 'CRT_INTERNAL',
canonical_request: 'CRT_INTERNAL',
content_sha256: content_sha256,
extra: {config: config, signable: signable}
)
end

def crt_presign_url(options)
creds, expiration = crt_fetch_credentials

http_method = extract_http_method(options)
url = extract_url(options)
headers = downcase_headers(options[:headers])
headers['host'] ||= host(url)

datetime = Time.strptime(headers.delete('x-amz-date'), "%Y%m%dT%H%M%S%Z") if headers['x-amz-date']
datetime ||= (options[:time] || Time.now)

content_sha256 = headers.delete('x-amz-content-sha256')
content_sha256 ||= options[:body_digest]
content_sha256 ||= sha256_hexdigest(options[:body] || '')

config = Aws::Crt::Auth::SigningConfig.new(
algorithm: @signing_algorithm,
signature_type: :http_request_query_params,
region: @region,
service: @service,
date: datetime,
signed_body_value: content_sha256,
signed_body_header_type: @apply_checksum_header ?
:sbht_content_sha256 : :sbht_none,
credentials: creds,
unsigned_headers: @unsigned_headers,
use_double_uri_encode: @uri_escape_path,
should_normalize_uri_path: @normalize_path,
omit_session_token: @omit_session_token,
expiration_in_seconds: presigned_url_expiration(options, expiration, datetime)
)
http_request = Aws::Crt::Http::Message.new(
http_method, url.to_s, headers
)
signable = Aws::Crt::Auth::Signable.new(http_request)

signing_result = Aws::Crt::Auth::Signer.sign_request(config, signable, http_method, url.to_s)
url = URI.parse(signing_result[:path])

if options[:extra] && options[:extra].is_a?(Hash)
options[:extra][:config] = config
options[:extra][:signable] = signable
end
url
end

class << self

def use_crt?
@@use_crt
end

# @api private
def uri_escape_path(path)
path.gsub(/[^\/]+/) { |part| uri_escape(part) }
Expand Down
9 changes: 0 additions & 9 deletions gems/aws-sigv4/spec/signer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ module Sigv4
end

it 'escapes path for the canonical request by default' do
skip("CRT does not provide canonical request") if Signer.use_crt?

signature = Signer.new(options).sign_request(
http_method: 'GET',
url: 'https://domain.com/foo%bar'
Expand All @@ -367,8 +365,6 @@ module Sigv4
end

it 'escapes path for the canonical request if :uri_escape_path is true' do
skip("CRT does not provide canonical request") if Signer.use_crt?

options[:uri_escape_path] = true
signature = Signer.new(options).sign_request(
http_method: 'GET',
Expand All @@ -378,8 +374,6 @@ module Sigv4
end

it 'does not escape path for the canonical request if :uri_escape_path is false' do
skip("CRT does not provide canonical request") if Signer.use_crt?

options[:uri_escape_path] = false
signature = Signer.new(options).sign_request(
http_method: 'GET',
Expand Down Expand Up @@ -427,9 +421,6 @@ module Sigv4
end

context ':canonical_request' do

before { skip("CRT Signer does not expose canonical request") if Signer.use_crt? }

it 'lower-cases and sort all header keys except authorization' do
signature = Signer.new(options).sign_request(
http_method: 'PUT',
Expand Down
Loading

0 comments on commit 409484b

Please sign in to comment.