aws-sigv4 1.3.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/VERSION +1 -1
- data/lib/aws-sigv4/signature.rb +2 -0
- data/lib/aws-sigv4/signer.rb +207 -14
- data/lib/aws-sigv4.rb +6 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 482b4ffa8bd9e9e2d7dab0d61ab15553f0e8d05e1be2923b388157664a47a9fa
|
4
|
+
data.tar.gz: c5caa84527ca213826f8c802195430caacb25750530609f1b8d7267810808574
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c16c5df7f8c6ca10cf073c25984506ce938f26823f99d82813b5bde3fb283d23a3c480adec2945b98975946a7b32efe57a0058cd65bb383606c5ee5228711381
|
7
|
+
data.tar.gz: b72ea1894eb1c419179325f8e715fb454ab02ae2d1ac243b90ed2f4032c0fd966ba157287a12009587908d0a6a2f62261c78e319a230196792b6ec4206a20718
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,46 @@
|
|
1
1
|
Unreleased Changes
|
2
2
|
------------------
|
3
3
|
|
4
|
+
1.8.0 (2023-11-28)
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* Feature - Support `sigv4-s3express` signing algorithm.
|
8
|
+
|
9
|
+
1.7.0 (2023-11-22)
|
10
|
+
------------------
|
11
|
+
|
12
|
+
* Feature - AWS SDK for Ruby no longer supports Ruby runtime versions 2.3 and 2.4.
|
13
|
+
|
14
|
+
1.6.1 (2023-10-25)
|
15
|
+
------------------
|
16
|
+
|
17
|
+
* Issue - (Static Stability) use provided `expires_in` in presigned url when credentials are expired.
|
18
|
+
|
19
|
+
1.6.0 (2023-06-28)
|
20
|
+
------------------
|
21
|
+
|
22
|
+
* Feature - Select the minimum expiration time for presigned urls between the expiration time option and the credential expiration time.
|
23
|
+
|
24
|
+
1.5.2 (2022-09-30)
|
25
|
+
------------------
|
26
|
+
|
27
|
+
* Issue - Fix an issue where quoted strings with multiple spaces are not trimmed. (#2758)
|
28
|
+
|
29
|
+
1.5.1 (2022-07-19)
|
30
|
+
------------------
|
31
|
+
|
32
|
+
* Issue - Fix performance regression when checking if `aws-crt` is available. (#2729)
|
33
|
+
|
34
|
+
1.5.0 (2022-04-20)
|
35
|
+
------------------
|
36
|
+
|
37
|
+
* Feature - Use CRT based signers if `aws-crt` is available - provides support for `sigv4a`.
|
38
|
+
|
39
|
+
1.4.0 (2021-09-02)
|
40
|
+
------------------
|
41
|
+
|
42
|
+
* Feature - add `signing_algorithm` option with `sigv4` default.
|
43
|
+
|
4
44
|
1.3.0 (2021-09-01)
|
5
45
|
------------------
|
6
46
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.8.0
|
data/lib/aws-sigv4/signature.rb
CHANGED
data/lib/aws-sigv4/signer.rb
CHANGED
@@ -74,6 +74,14 @@ module Aws
|
|
74
74
|
#
|
75
75
|
class Signer
|
76
76
|
|
77
|
+
@@use_crt =
|
78
|
+
begin
|
79
|
+
require 'aws-crt'
|
80
|
+
true
|
81
|
+
rescue LoadError
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
77
85
|
# @overload initialize(service:, region:, access_key_id:, secret_access_key:, session_token:nil, **options)
|
78
86
|
# @param [String] :service The service signing name, e.g. 's3'.
|
79
87
|
# @param [String] :region The region name, e.g. 'us-east-1'.
|
@@ -118,6 +126,18 @@ module Aws
|
|
118
126
|
# headers. This is required for AWS Glacier, and optional for
|
119
127
|
# every other AWS service as of late 2016.
|
120
128
|
#
|
129
|
+
# @option options [Symbol] :signing_algorithm (:sigv4) The
|
130
|
+
# algorithm to use for signing. :sigv4a is only supported when
|
131
|
+
# `aws-crt` is available.
|
132
|
+
#
|
133
|
+
# @option options [Boolean] :omit_session_token (false)
|
134
|
+
# (Supported only when `aws-crt` is available) If `true`,
|
135
|
+
# then security token is added to the final signing result,
|
136
|
+
# but is treated as "unsigned" and does not contribute
|
137
|
+
# to the authorization signature.
|
138
|
+
#
|
139
|
+
# @option options [Boolean] :normalize_path (true) (Supported only when `aws-crt` is available)
|
140
|
+
# When `true`, the uri paths will be normalized when building the canonical request
|
121
141
|
def initialize(options = {})
|
122
142
|
@service = extract_service(options)
|
123
143
|
@region = extract_region(options)
|
@@ -126,8 +146,23 @@ module Aws
|
|
126
146
|
@unsigned_headers << 'authorization'
|
127
147
|
@unsigned_headers << 'x-amzn-trace-id'
|
128
148
|
@unsigned_headers << 'expect'
|
129
|
-
|
130
|
-
|
149
|
+
@uri_escape_path = options.fetch(:uri_escape_path, true)
|
150
|
+
@apply_checksum_header = options.fetch(:apply_checksum_header, true)
|
151
|
+
@signing_algorithm = options.fetch(:signing_algorithm, :sigv4)
|
152
|
+
@normalize_path = options.fetch(:normalize_path, true)
|
153
|
+
@omit_session_token = options.fetch(:omit_session_token, false)
|
154
|
+
|
155
|
+
if @signing_algorithm == :sigv4a && !Signer.use_crt?
|
156
|
+
raise ArgumentError, 'You are attempting to sign a' \
|
157
|
+
' request with sigv4a which requires the `aws-crt` gem.'\
|
158
|
+
' Please install the gem or add it to your gemfile.'
|
159
|
+
end
|
160
|
+
|
161
|
+
if @signing_algorithm == 'sigv4-s3express'.to_sym &&
|
162
|
+
Signer.use_crt? && Aws::Crt::GEM_VERSION <= '0.1.9'
|
163
|
+
raise ArgumentError,
|
164
|
+
'This version of aws-crt does not support S3 Express. Please
|
165
|
+
update this gem to at least version 0.2.0.'
|
131
166
|
end
|
132
167
|
end
|
133
168
|
|
@@ -205,7 +240,9 @@ module Aws
|
|
205
240
|
#
|
206
241
|
def sign_request(request)
|
207
242
|
|
208
|
-
|
243
|
+
return crt_sign_request(request) if Signer.use_crt?
|
244
|
+
|
245
|
+
creds, _ = fetch_credentials
|
209
246
|
|
210
247
|
http_method = extract_http_method(request)
|
211
248
|
url = extract_url(request)
|
@@ -221,7 +258,14 @@ module Aws
|
|
221
258
|
sigv4_headers = {}
|
222
259
|
sigv4_headers['host'] = headers['host'] || host(url)
|
223
260
|
sigv4_headers['x-amz-date'] = datetime
|
224
|
-
|
261
|
+
if creds.session_token
|
262
|
+
if @signing_algorithm == 'sigv4-s3express'.to_sym
|
263
|
+
sigv4_headers['x-amz-s3session-token'] = creds.session_token
|
264
|
+
else
|
265
|
+
sigv4_headers['x-amz-security-token'] = creds.session_token
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
225
269
|
sigv4_headers['x-amz-content-sha256'] ||= content_sha256 if @apply_checksum_header
|
226
270
|
|
227
271
|
headers = headers.merge(sigv4_headers) # merge so we do not modify given headers hash
|
@@ -283,7 +327,8 @@ module Aws
|
|
283
327
|
# signature value (a binary string) used at ':chunk-signature' needs to converted to
|
284
328
|
# hex-encoded string using #unpack
|
285
329
|
def sign_event(prior_signature, payload, encoder)
|
286
|
-
|
330
|
+
# Note: CRT does not currently provide event stream signing, so we always use the ruby implementation.
|
331
|
+
creds, _ = fetch_credentials
|
287
332
|
time = Time.now
|
288
333
|
headers = {}
|
289
334
|
|
@@ -370,7 +415,9 @@ module Aws
|
|
370
415
|
#
|
371
416
|
def presign_url(options)
|
372
417
|
|
373
|
-
|
418
|
+
return crt_presign_url(options) if Signer.use_crt?
|
419
|
+
|
420
|
+
creds, expiration = fetch_credentials
|
374
421
|
|
375
422
|
http_method = extract_http_method(options)
|
376
423
|
url = extract_url(options)
|
@@ -390,8 +437,14 @@ module Aws
|
|
390
437
|
params['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'
|
391
438
|
params['X-Amz-Credential'] = credential(creds, date)
|
392
439
|
params['X-Amz-Date'] = datetime
|
393
|
-
params['X-Amz-Expires'] =
|
394
|
-
|
440
|
+
params['X-Amz-Expires'] = presigned_url_expiration(options, expiration, Time.strptime(datetime, "%Y%m%dT%H%M%S%Z")).to_s
|
441
|
+
if creds.session_token
|
442
|
+
if @signing_algorithm == 'sigv4-s3express'.to_sym
|
443
|
+
params['X-Amz-S3session-Token'] = creds.session_token
|
444
|
+
else
|
445
|
+
params['X-Amz-Security-Token'] = creds.session_token
|
446
|
+
end
|
447
|
+
end
|
395
448
|
params['X-Amz-SignedHeaders'] = signed_headers(headers)
|
396
449
|
|
397
450
|
params = params.map do |key, value|
|
@@ -493,7 +546,6 @@ module Aws
|
|
493
546
|
hmac(k_credentials, string_to_sign)
|
494
547
|
end
|
495
548
|
|
496
|
-
|
497
549
|
def path(url)
|
498
550
|
path = url.path
|
499
551
|
path = '/' if path == ''
|
@@ -556,7 +608,7 @@ module Aws
|
|
556
608
|
end
|
557
609
|
|
558
610
|
def canonical_header_value(value)
|
559
|
-
value.
|
611
|
+
value.gsub(/\s+/, ' ').strip
|
560
612
|
end
|
561
613
|
|
562
614
|
def host(uri)
|
@@ -649,8 +701,8 @@ module Aws
|
|
649
701
|
|
650
702
|
def extract_expires_in(options)
|
651
703
|
case options[:expires_in]
|
652
|
-
when nil then 900
|
653
|
-
when Integer then options[:expires_in]
|
704
|
+
when nil then 900
|
705
|
+
when Integer then options[:expires_in]
|
654
706
|
else
|
655
707
|
msg = "expected :expires_in to be a number of seconds"
|
656
708
|
raise ArgumentError, msg
|
@@ -665,11 +717,14 @@ module Aws
|
|
665
717
|
self.class.uri_escape_path(string)
|
666
718
|
end
|
667
719
|
|
668
|
-
|
669
720
|
def fetch_credentials
|
670
721
|
credentials = @credentials_provider.credentials
|
671
722
|
if credentials_set?(credentials)
|
672
|
-
|
723
|
+
expiration = nil
|
724
|
+
if @credentials_provider.respond_to?(:expiration)
|
725
|
+
expiration = @credentials_provider.expiration
|
726
|
+
end
|
727
|
+
[credentials, expiration]
|
673
728
|
else
|
674
729
|
raise Errors::MissingCredentialsError,
|
675
730
|
'unable to sign request without credentials set'
|
@@ -687,8 +742,146 @@ module Aws
|
|
687
742
|
!credentials.secret_access_key.empty?
|
688
743
|
end
|
689
744
|
|
745
|
+
def presigned_url_expiration(options, expiration, datetime)
|
746
|
+
expires_in = extract_expires_in(options)
|
747
|
+
return expires_in unless expiration
|
748
|
+
|
749
|
+
expiration_seconds = (expiration - datetime).to_i
|
750
|
+
# In the static stability case, credentials may expire in the past
|
751
|
+
# but still be valid. For those cases, use the user configured
|
752
|
+
# expires_in and ingore expiration.
|
753
|
+
if expiration_seconds <= 0
|
754
|
+
expires_in
|
755
|
+
else
|
756
|
+
[expires_in, expiration_seconds].min
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
### CRT Code
|
761
|
+
|
762
|
+
# the credentials used by CRT must be a
|
763
|
+
# CRT StaticCredentialsProvider object
|
764
|
+
def crt_fetch_credentials
|
765
|
+
creds, expiration = fetch_credentials
|
766
|
+
crt_creds = Aws::Crt::Auth::StaticCredentialsProvider.new(
|
767
|
+
creds.access_key_id,
|
768
|
+
creds.secret_access_key,
|
769
|
+
creds.session_token
|
770
|
+
)
|
771
|
+
[crt_creds, expiration]
|
772
|
+
end
|
773
|
+
|
774
|
+
def crt_sign_request(request)
|
775
|
+
creds, _ = crt_fetch_credentials
|
776
|
+
http_method = extract_http_method(request)
|
777
|
+
url = extract_url(request)
|
778
|
+
headers = downcase_headers(request[:headers])
|
779
|
+
|
780
|
+
datetime =
|
781
|
+
if headers.include? 'x-amz-date'
|
782
|
+
Time.parse(headers.delete('x-amz-date'))
|
783
|
+
end
|
784
|
+
|
785
|
+
content_sha256 = headers.delete('x-amz-content-sha256')
|
786
|
+
content_sha256 ||= sha256_hexdigest(request[:body] || '')
|
787
|
+
|
788
|
+
sigv4_headers = {}
|
789
|
+
sigv4_headers['host'] = headers['host'] || host(url)
|
790
|
+
|
791
|
+
# Modify the user-agent to add usage of crt-signer
|
792
|
+
# This should be temporary during developer preview only
|
793
|
+
if headers.include? 'user-agent'
|
794
|
+
headers['user-agent'] = "#{headers['user-agent']} crt-signer/#{@signing_algorithm}/#{Aws::Sigv4::VERSION}"
|
795
|
+
sigv4_headers['user-agent'] = headers['user-agent']
|
796
|
+
end
|
797
|
+
|
798
|
+
headers = headers.merge(sigv4_headers) # merge so we do not modify given headers hash
|
799
|
+
|
800
|
+
config = Aws::Crt::Auth::SigningConfig.new(
|
801
|
+
algorithm: @signing_algorithm,
|
802
|
+
signature_type: :http_request_headers,
|
803
|
+
region: @region,
|
804
|
+
service: @service,
|
805
|
+
date: datetime,
|
806
|
+
signed_body_value: content_sha256,
|
807
|
+
signed_body_header_type: @apply_checksum_header ?
|
808
|
+
:sbht_content_sha256 : :sbht_none,
|
809
|
+
credentials: creds,
|
810
|
+
unsigned_headers: @unsigned_headers,
|
811
|
+
use_double_uri_encode: @uri_escape_path,
|
812
|
+
should_normalize_uri_path: @normalize_path,
|
813
|
+
omit_session_token: @omit_session_token
|
814
|
+
)
|
815
|
+
http_request = Aws::Crt::Http::Message.new(
|
816
|
+
http_method, url.to_s, headers
|
817
|
+
)
|
818
|
+
signable = Aws::Crt::Auth::Signable.new(http_request)
|
819
|
+
|
820
|
+
signing_result = Aws::Crt::Auth::Signer.sign_request(config, signable)
|
821
|
+
|
822
|
+
Signature.new(
|
823
|
+
headers: sigv4_headers.merge(
|
824
|
+
downcase_headers(signing_result[:headers])
|
825
|
+
),
|
826
|
+
string_to_sign: 'CRT_INTERNAL',
|
827
|
+
canonical_request: 'CRT_INTERNAL',
|
828
|
+
content_sha256: content_sha256,
|
829
|
+
extra: {config: config, signable: signable}
|
830
|
+
)
|
831
|
+
end
|
832
|
+
|
833
|
+
def crt_presign_url(options)
|
834
|
+
creds, expiration = crt_fetch_credentials
|
835
|
+
|
836
|
+
http_method = extract_http_method(options)
|
837
|
+
url = extract_url(options)
|
838
|
+
headers = downcase_headers(options[:headers])
|
839
|
+
headers['host'] ||= host(url)
|
840
|
+
|
841
|
+
datetime = Time.strptime(headers.delete('x-amz-date'), "%Y%m%dT%H%M%S%Z") if headers['x-amz-date']
|
842
|
+
datetime ||= (options[:time] || Time.now)
|
843
|
+
|
844
|
+
content_sha256 = headers.delete('x-amz-content-sha256')
|
845
|
+
content_sha256 ||= options[:body_digest]
|
846
|
+
content_sha256 ||= sha256_hexdigest(options[:body] || '')
|
847
|
+
|
848
|
+
config = Aws::Crt::Auth::SigningConfig.new(
|
849
|
+
algorithm: @signing_algorithm,
|
850
|
+
signature_type: :http_request_query_params,
|
851
|
+
region: @region,
|
852
|
+
service: @service,
|
853
|
+
date: datetime,
|
854
|
+
signed_body_value: content_sha256,
|
855
|
+
signed_body_header_type: @apply_checksum_header ?
|
856
|
+
:sbht_content_sha256 : :sbht_none,
|
857
|
+
credentials: creds,
|
858
|
+
unsigned_headers: @unsigned_headers,
|
859
|
+
use_double_uri_encode: @uri_escape_path,
|
860
|
+
should_normalize_uri_path: @normalize_path,
|
861
|
+
omit_session_token: @omit_session_token,
|
862
|
+
expiration_in_seconds: presigned_url_expiration(options, expiration, datetime)
|
863
|
+
)
|
864
|
+
http_request = Aws::Crt::Http::Message.new(
|
865
|
+
http_method, url.to_s, headers
|
866
|
+
)
|
867
|
+
signable = Aws::Crt::Auth::Signable.new(http_request)
|
868
|
+
|
869
|
+
signing_result = Aws::Crt::Auth::Signer.sign_request(config, signable, http_method, url.to_s)
|
870
|
+
url = URI.parse(signing_result[:path])
|
871
|
+
|
872
|
+
if options[:extra] && options[:extra].is_a?(Hash)
|
873
|
+
options[:extra][:config] = config
|
874
|
+
options[:extra][:signable] = signable
|
875
|
+
end
|
876
|
+
url
|
877
|
+
end
|
878
|
+
|
690
879
|
class << self
|
691
880
|
|
881
|
+
def use_crt?
|
882
|
+
@@use_crt
|
883
|
+
end
|
884
|
+
|
692
885
|
# @api private
|
693
886
|
def uri_escape_path(path)
|
694
887
|
path.gsub(/[^\/]+/) { |part| uri_escape(part) }
|
data/lib/aws-sigv4.rb
CHANGED
@@ -4,3 +4,9 @@ require_relative 'aws-sigv4/credentials'
|
|
4
4
|
require_relative 'aws-sigv4/errors'
|
5
5
|
require_relative 'aws-sigv4/signature'
|
6
6
|
require_relative 'aws-sigv4/signer'
|
7
|
+
|
8
|
+
module Aws
|
9
|
+
module Sigv4
|
10
|
+
VERSION = File.read(File.expand_path('../VERSION', __dir__)).strip
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-sigv4
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-eventstream
|
@@ -60,7 +60,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '2.
|
63
|
+
version: '2.5'
|
64
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|