aws-sdk-s3 1.61.2 → 1.83.1
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 +5 -5
- data/lib/aws-sdk-s3.rb +5 -2
- data/lib/aws-sdk-s3/arn/access_point_arn.rb +62 -0
- data/lib/aws-sdk-s3/arn/outpost_access_point_arn.rb +71 -0
- data/lib/aws-sdk-s3/bucket.rb +61 -10
- data/lib/aws-sdk-s3/bucket_acl.rb +7 -0
- data/lib/aws-sdk-s3/bucket_cors.rb +15 -2
- data/lib/aws-sdk-s3/bucket_lifecycle.rb +14 -1
- data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +14 -1
- data/lib/aws-sdk-s3/bucket_logging.rb +7 -0
- data/lib/aws-sdk-s3/bucket_notification.rb +7 -0
- data/lib/aws-sdk-s3/bucket_policy.rb +14 -1
- data/lib/aws-sdk-s3/bucket_region_cache.rb +2 -0
- data/lib/aws-sdk-s3/bucket_request_payment.rb +7 -0
- data/lib/aws-sdk-s3/bucket_tagging.rb +14 -1
- data/lib/aws-sdk-s3/bucket_versioning.rb +17 -0
- data/lib/aws-sdk-s3/bucket_website.rb +18 -3
- data/lib/aws-sdk-s3/client.rb +2521 -1187
- data/lib/aws-sdk-s3/client_api.rb +188 -18
- data/lib/aws-sdk-s3/customizations.rb +3 -0
- data/lib/aws-sdk-s3/customizations/bucket.rb +11 -4
- data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
- data/lib/aws-sdk-s3/customizations/object.rb +23 -5
- data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
- data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
- data/lib/aws-sdk-s3/encryption.rb +4 -0
- data/lib/aws-sdk-s3/encryption/client.rb +18 -5
- data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +72 -26
- data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
- data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
- data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
- data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
- data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +34 -3
- data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
- data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
- data/lib/aws-sdk-s3/encryptionV2/client.rb +566 -0
- data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +226 -0
- data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
- data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
- data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +69 -0
- data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
- data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
- data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
- data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
- data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
- data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +169 -0
- data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
- data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
- data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
- data/lib/aws-sdk-s3/errors.rb +2 -0
- data/lib/aws-sdk-s3/event_streams.rb +7 -0
- data/lib/aws-sdk-s3/file_downloader.rb +10 -8
- data/lib/aws-sdk-s3/file_part.rb +2 -0
- data/lib/aws-sdk-s3/file_uploader.rb +14 -1
- data/lib/aws-sdk-s3/legacy_signer.rb +2 -0
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +39 -2
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +3 -1
- data/lib/aws-sdk-s3/multipart_upload.rb +18 -1
- data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
- data/lib/aws-sdk-s3/multipart_upload_part.rb +66 -7
- data/lib/aws-sdk-s3/object.rb +174 -23
- data/lib/aws-sdk-s3/object_acl.rb +15 -0
- data/lib/aws-sdk-s3/object_copier.rb +2 -0
- data/lib/aws-sdk-s3/object_multipart_copier.rb +2 -0
- data/lib/aws-sdk-s3/object_summary.rb +185 -20
- data/lib/aws-sdk-s3/object_version.rb +44 -4
- data/lib/aws-sdk-s3/plugins/accelerate.rb +29 -38
- data/lib/aws-sdk-s3/plugins/arn.rb +187 -0
- data/lib/aws-sdk-s3/plugins/bucket_dns.rb +2 -2
- data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +3 -1
- data/lib/aws-sdk-s3/plugins/dualstack.rb +5 -1
- data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +3 -4
- data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +2 -0
- data/lib/aws-sdk-s3/plugins/http_200_errors.rb +11 -3
- data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +3 -1
- data/lib/aws-sdk-s3/plugins/location_constraint.rb +2 -0
- data/lib/aws-sdk-s3/plugins/md5s.rb +26 -25
- data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
- data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
- data/lib/aws-sdk-s3/plugins/s3_signer.rb +31 -7
- data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
- data/lib/aws-sdk-s3/plugins/streaming_retry.rb +118 -0
- data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
- data/lib/aws-sdk-s3/presigned_post.rb +68 -32
- data/lib/aws-sdk-s3/presigner.rb +102 -34
- data/lib/aws-sdk-s3/resource.rb +4 -2
- data/lib/aws-sdk-s3/types.rb +2016 -256
- data/lib/aws-sdk-s3/waiters.rb +2 -0
- metadata +23 -6
- data/lib/aws-sdk-s3/plugins/bucket_arn.rb +0 -211
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# utility classes
|
|
2
4
|
require 'aws-sdk-s3/bucket_region_cache'
|
|
3
5
|
require 'aws-sdk-s3/encryption'
|
|
6
|
+
require 'aws-sdk-s3/encryption_v2'
|
|
4
7
|
require 'aws-sdk-s3/file_part'
|
|
5
8
|
require 'aws-sdk-s3/file_uploader'
|
|
6
9
|
require 'aws-sdk-s3/file_downloader'
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'uri'
|
|
2
4
|
|
|
3
5
|
module Aws
|
|
@@ -5,16 +7,17 @@ module Aws
|
|
|
5
7
|
class Bucket
|
|
6
8
|
# Save the old initialize method so that we can call 'super'.
|
|
7
9
|
old_initialize = instance_method(:initialize)
|
|
10
|
+
# Make the method redefinable
|
|
11
|
+
alias_method :initialize, :initialize
|
|
8
12
|
# Define a new initialize method that extracts out a bucket ARN.
|
|
9
13
|
define_method(:initialize) do |*args|
|
|
10
14
|
old_initialize.bind(self).call(*args)
|
|
11
|
-
|
|
15
|
+
resolved_region, arn = Plugins::ARN.resolve_arn!(
|
|
12
16
|
name,
|
|
13
17
|
client.config.region,
|
|
14
18
|
client.config.s3_use_arn_region
|
|
15
19
|
)
|
|
16
|
-
@
|
|
17
|
-
@client.config.region = region
|
|
20
|
+
@resolved_region = resolved_region
|
|
18
21
|
@arn = arn
|
|
19
22
|
end
|
|
20
23
|
|
|
@@ -98,7 +101,11 @@ module Aws
|
|
|
98
101
|
if options[:virtual_host]
|
|
99
102
|
"http://#{name}"
|
|
100
103
|
elsif @arn
|
|
101
|
-
Plugins::
|
|
104
|
+
Plugins::ARN.resolve_url!(
|
|
105
|
+
client.config.endpoint.dup,
|
|
106
|
+
@arn,
|
|
107
|
+
@resolved_region
|
|
108
|
+
).to_s
|
|
102
109
|
else
|
|
103
110
|
s3_bucket_url
|
|
104
111
|
end
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Aws
|
|
2
4
|
module S3
|
|
3
5
|
class Object
|
|
4
6
|
alias size content_length
|
|
5
7
|
|
|
8
|
+
# Make the method redefinable
|
|
9
|
+
alias_method :copy_from, :copy_from
|
|
10
|
+
|
|
6
11
|
# Copies another object to this object. Use `multipart_copy: true`
|
|
7
12
|
# for large objects. This is required for objects that exceed 5GB.
|
|
8
13
|
#
|
|
@@ -25,7 +30,8 @@ module Aws
|
|
|
25
30
|
#
|
|
26
31
|
# @option options [Integer] :content_length Only used when
|
|
27
32
|
# `:multipart_copy` is `true`. Passing this options avoids a HEAD
|
|
28
|
-
# request to query the source object size.
|
|
33
|
+
# request to query the source object size. Raises an `ArgumentError` if
|
|
34
|
+
# this option is provided when `:multipart_copy` is `false` or not set.
|
|
29
35
|
#
|
|
30
36
|
# @option options [S3::Client] :copy_source_client Only used when
|
|
31
37
|
# `:multipart_copy` is `true` and the source object is in a
|
|
@@ -276,8 +282,8 @@ module Aws
|
|
|
276
282
|
# # small files are uploaded in a single API call
|
|
277
283
|
# obj.upload_file('/path/to/file')
|
|
278
284
|
#
|
|
279
|
-
# Files larger than `:multipart_threshold` are uploaded
|
|
280
|
-
# Amazon S3 multipart upload APIs.
|
|
285
|
+
# Files larger than or equal to `:multipart_threshold` are uploaded
|
|
286
|
+
# using the Amazon S3 multipart upload APIs.
|
|
281
287
|
#
|
|
282
288
|
# # large files are automatically split into parts
|
|
283
289
|
# # and the parts are uploaded in parallel
|
|
@@ -290,6 +296,14 @@ module Aws
|
|
|
290
296
|
# etag = response.etag
|
|
291
297
|
# end
|
|
292
298
|
#
|
|
299
|
+
# You can provide a callback to monitor progress of the upload:
|
|
300
|
+
#
|
|
301
|
+
# # bytes and totals are each an array with 1 entry per part
|
|
302
|
+
# progress = Proc.new do |bytes, totals|
|
|
303
|
+
# puts bytes.map.with_index { |b, i| "Part #{i+1}: #{b} / #{totals[i]}"}.join(' ') + "Total: #{100.0 * bytes.sum / totals.sum }%" }
|
|
304
|
+
# end
|
|
305
|
+
# obj.upload_file('/path/to/file')
|
|
306
|
+
#
|
|
293
307
|
# @param [String, Pathname, File, Tempfile] source A file on the local
|
|
294
308
|
# file system that will be uploaded as this object. This can either be
|
|
295
309
|
# a String or Pathname to the file, an open File object, or an open
|
|
@@ -299,13 +313,18 @@ module Aws
|
|
|
299
313
|
# will be empty.
|
|
300
314
|
#
|
|
301
315
|
# @option options [Integer] :multipart_threshold (15728640) Files larger
|
|
302
|
-
# than `:multipart_threshold` are uploaded using the S3
|
|
316
|
+
# than or equal to `:multipart_threshold` are uploaded using the S3
|
|
317
|
+
# multipart APIs.
|
|
303
318
|
# Default threshold is 15MB.
|
|
304
319
|
#
|
|
305
320
|
# @option options [Integer] :thread_count (10) The number of parallel
|
|
306
321
|
# multipart uploads. This option is not used if the file is smaller than
|
|
307
322
|
# `:multipart_threshold`.
|
|
308
323
|
#
|
|
324
|
+
# @option options [Proc] :progress_callback
|
|
325
|
+
# A Proc that will be called when each chunk of the upload is sent.
|
|
326
|
+
# It will be invoked with [bytes_read], [total_sizes]
|
|
327
|
+
#
|
|
309
328
|
# @raise [MultipartUploadError] If an object is being uploaded in
|
|
310
329
|
# parts, and the upload can not be completed, then the upload is
|
|
311
330
|
# aborted and this error is raised. The raised error has a `#errors`
|
|
@@ -314,7 +333,6 @@ module Aws
|
|
|
314
333
|
#
|
|
315
334
|
# @return [Boolean] Returns `true` when the object is uploaded
|
|
316
335
|
# without any errors.
|
|
317
|
-
#
|
|
318
336
|
def upload_file(source, options = {})
|
|
319
337
|
uploading_options = options.dup
|
|
320
338
|
uploader = FileUploader.new(
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Aws
|
|
2
4
|
module S3
|
|
3
5
|
class ObjectSummary
|
|
4
6
|
|
|
5
7
|
alias content_length size
|
|
6
8
|
|
|
9
|
+
# Make the method redefinable
|
|
10
|
+
alias_method :copy_from, :copy_from
|
|
11
|
+
|
|
7
12
|
# @param (see Object#copy_from)
|
|
8
13
|
# @options (see Object#copy_from)
|
|
9
14
|
# @return (see Object#copy_from)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'aws-sdk-s3/encryption/client'
|
|
2
4
|
require 'aws-sdk-s3/encryption/decrypt_handler'
|
|
3
5
|
require 'aws-sdk-s3/encryption/default_cipher_provider'
|
|
@@ -15,5 +17,7 @@ require 'aws-sdk-s3/encryption/default_key_provider'
|
|
|
15
17
|
module Aws
|
|
16
18
|
module S3
|
|
17
19
|
module Encryption; end
|
|
20
|
+
AES_GCM_TAG_LEN_BYTES = 16
|
|
21
|
+
EC_USER_AGENT = 'S3CryptoV1n'
|
|
18
22
|
end
|
|
19
23
|
end
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
|
|
3
5
|
module Aws
|
|
4
6
|
module S3
|
|
5
7
|
|
|
8
|
+
# [MAINTENANCE MODE] There is a new version of the Encryption Client.
|
|
9
|
+
# AWS strongly recommends upgrading to the {Aws::S3::EncryptionV2::Client},
|
|
10
|
+
# which provides updated data security best practices.
|
|
11
|
+
# See documentation for {Aws::S3::EncryptionV2::Client}.
|
|
6
12
|
# Provides an encryption client that encrypts and decrypts data client-side,
|
|
7
13
|
# storing the encrypted data in Amazon S3.
|
|
8
14
|
#
|
|
@@ -181,7 +187,7 @@ module Aws
|
|
|
181
187
|
|
|
182
188
|
extend Deprecations
|
|
183
189
|
extend Forwardable
|
|
184
|
-
def_delegators :@client, :config, :delete_object, :head_object
|
|
190
|
+
def_delegators :@client, :config, :delete_object, :head_object, :build_request
|
|
185
191
|
|
|
186
192
|
# Creates a new encryption client. You must provide one of the following
|
|
187
193
|
# options:
|
|
@@ -227,6 +233,13 @@ module Aws
|
|
|
227
233
|
@envelope_location = extract_location(options)
|
|
228
234
|
@instruction_file_suffix = extract_suffix(options)
|
|
229
235
|
end
|
|
236
|
+
deprecated :initialize,
|
|
237
|
+
message:
|
|
238
|
+
'[MAINTENANCE MODE] This version of the S3 Encryption client is currently in maintenance mode. ' \
|
|
239
|
+
'AWS strongly recommends upgrading to the Aws::S3::EncryptionV2::Client, ' \
|
|
240
|
+
'which provides updated data security best practices. ' \
|
|
241
|
+
'See documentation for Aws::S3::EncryptionV2::Client.'
|
|
242
|
+
|
|
230
243
|
|
|
231
244
|
# @return [S3::Client]
|
|
232
245
|
attr_reader :client
|
|
@@ -331,7 +344,7 @@ module Aws
|
|
|
331
344
|
elsif options[:encryption_key]
|
|
332
345
|
DefaultKeyProvider.new(options)
|
|
333
346
|
else
|
|
334
|
-
msg =
|
|
347
|
+
msg = 'you must pass a :kms_key_id, :key_provider, or :encryption_key'
|
|
335
348
|
raise ArgumentError, msg
|
|
336
349
|
end
|
|
337
350
|
end
|
|
@@ -351,8 +364,8 @@ module Aws
|
|
|
351
364
|
if [:metadata, :instruction_file].include?(location)
|
|
352
365
|
location
|
|
353
366
|
else
|
|
354
|
-
msg =
|
|
355
|
-
|
|
367
|
+
msg = ':envelope_location must be :metadata or :instruction_file '\
|
|
368
|
+
"got #{location.inspect}"
|
|
356
369
|
raise ArgumentError, msg
|
|
357
370
|
end
|
|
358
371
|
end
|
|
@@ -362,7 +375,7 @@ module Aws
|
|
|
362
375
|
if String === suffix
|
|
363
376
|
suffix
|
|
364
377
|
else
|
|
365
|
-
msg =
|
|
378
|
+
msg = ':instruction_file_suffix must be a String'
|
|
366
379
|
raise ArgumentError, msg
|
|
367
380
|
end
|
|
368
381
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'base64'
|
|
2
4
|
|
|
3
5
|
module Aws
|
|
@@ -5,6 +7,7 @@ module Aws
|
|
|
5
7
|
module Encryption
|
|
6
8
|
# @api private
|
|
7
9
|
class DecryptHandler < Seahorse::Client::Handler
|
|
10
|
+
@@warned_response_target_proc = false
|
|
8
11
|
|
|
9
12
|
V1_ENVELOPE_KEYS = %w(
|
|
10
13
|
x-amz-key
|
|
@@ -20,7 +23,17 @@ module Aws
|
|
|
20
23
|
x-amz-matdesc
|
|
21
24
|
)
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
V2_OPTIONAL_KEYS = %w(x-amz-tag-len)
|
|
27
|
+
|
|
28
|
+
POSSIBLE_ENVELOPE_KEYS = (V1_ENVELOPE_KEYS +
|
|
29
|
+
V2_ENVELOPE_KEYS + V2_OPTIONAL_KEYS).uniq
|
|
30
|
+
|
|
31
|
+
POSSIBLE_WRAPPING_FORMATS = %w(
|
|
32
|
+
AES/GCM
|
|
33
|
+
kms
|
|
34
|
+
kms+context
|
|
35
|
+
RSA-OAEP-SHA1
|
|
36
|
+
)
|
|
24
37
|
|
|
25
38
|
POSSIBLE_ENCRYPTION_FORMATS = %w(
|
|
26
39
|
AES/GCM/NoPadding
|
|
@@ -28,8 +41,21 @@ module Aws
|
|
|
28
41
|
AES/CBC/PKCS7Padding
|
|
29
42
|
)
|
|
30
43
|
|
|
44
|
+
AUTH_REQUIRED_CEK_ALGS = %w(AES/GCM/NoPadding)
|
|
45
|
+
|
|
31
46
|
def call(context)
|
|
32
47
|
attach_http_event_listeners(context)
|
|
48
|
+
apply_cse_user_agent(context)
|
|
49
|
+
|
|
50
|
+
if context[:response_target].is_a?(Proc) && !@@warned_response_target_proc
|
|
51
|
+
@@warned_response_target_proc = true
|
|
52
|
+
warn(':response_target is a Proc, or a block was provided. ' \
|
|
53
|
+
'Read the entire object to the ' \
|
|
54
|
+
'end before you start using the decrypted data. This is to ' \
|
|
55
|
+
'verify that the object has not been modified since it ' \
|
|
56
|
+
'was encrypted.')
|
|
57
|
+
end
|
|
58
|
+
|
|
33
59
|
@handler.call(context)
|
|
34
60
|
end
|
|
35
61
|
|
|
@@ -38,9 +64,9 @@ module Aws
|
|
|
38
64
|
def attach_http_event_listeners(context)
|
|
39
65
|
|
|
40
66
|
context.http_response.on_headers(200) do
|
|
41
|
-
cipher = decryption_cipher(context)
|
|
42
|
-
decrypter = body_contains_auth_tag?(
|
|
43
|
-
authenticated_decrypter(context, cipher) :
|
|
67
|
+
cipher, envelope = decryption_cipher(context)
|
|
68
|
+
decrypter = body_contains_auth_tag?(envelope) ?
|
|
69
|
+
authenticated_decrypter(context, cipher, envelope) :
|
|
44
70
|
IODecrypter.new(cipher, context.http_response.body)
|
|
45
71
|
context.http_response.body = decrypter
|
|
46
72
|
end
|
|
@@ -60,8 +86,13 @@ module Aws
|
|
|
60
86
|
end
|
|
61
87
|
|
|
62
88
|
def decryption_cipher(context)
|
|
63
|
-
if envelope = get_encryption_envelope(context)
|
|
64
|
-
context[:encryption][:cipher_provider]
|
|
89
|
+
if (envelope = get_encryption_envelope(context))
|
|
90
|
+
cipher = context[:encryption][:cipher_provider]
|
|
91
|
+
.decryption_cipher(
|
|
92
|
+
envelope,
|
|
93
|
+
context[:encryption]
|
|
94
|
+
)
|
|
95
|
+
[cipher, envelope]
|
|
65
96
|
else
|
|
66
97
|
raise Errors::DecryptionError, "unable to locate encryption envelope"
|
|
67
98
|
end
|
|
@@ -97,13 +128,12 @@ module Aws
|
|
|
97
128
|
end
|
|
98
129
|
|
|
99
130
|
def extract_envelope(hash)
|
|
131
|
+
return nil unless hash
|
|
100
132
|
return v1_envelope(hash) if hash.key?('x-amz-key')
|
|
101
133
|
return v2_envelope(hash) if hash.key?('x-amz-key-v2')
|
|
102
134
|
if hash.keys.any? { |key| key.match(/^x-amz-key-(.+)$/) }
|
|
103
135
|
msg = "unsupported envelope encryption version #{$1}"
|
|
104
136
|
raise Errors::DecryptionError, msg
|
|
105
|
-
else
|
|
106
|
-
nil # no envelope found
|
|
107
137
|
end
|
|
108
138
|
end
|
|
109
139
|
|
|
@@ -117,39 +147,31 @@ module Aws
|
|
|
117
147
|
msg = "unsupported content encrypting key (cek) format: #{alg}"
|
|
118
148
|
raise Errors::DecryptionError, msg
|
|
119
149
|
end
|
|
120
|
-
unless envelope['x-amz-wrap-alg']
|
|
121
|
-
# possible to support
|
|
122
|
-
# RSA/ECB/OAEPWithSHA-256AndMGF1Padding
|
|
150
|
+
unless POSSIBLE_WRAPPING_FORMATS.include? envelope['x-amz-wrap-alg']
|
|
123
151
|
alg = envelope['x-amz-wrap-alg'].inspect
|
|
124
152
|
msg = "unsupported key wrapping algorithm: #{alg}"
|
|
125
153
|
raise Errors::DecryptionError, msg
|
|
126
154
|
end
|
|
127
|
-
unless V2_ENVELOPE_KEYS
|
|
155
|
+
unless (missing_keys = V2_ENVELOPE_KEYS - envelope.keys).empty?
|
|
128
156
|
msg = "incomplete v2 encryption envelope:\n"
|
|
129
|
-
msg += "
|
|
130
|
-
msg += " got: #{envelope_keys.join(', ')}"
|
|
157
|
+
msg += " missing: #{missing_keys.join(',')}\n"
|
|
131
158
|
raise Errors::DecryptionError, msg
|
|
132
159
|
end
|
|
133
160
|
envelope
|
|
134
161
|
end
|
|
135
162
|
|
|
136
|
-
# When the x-amz-meta-x-amz-tag-len header is present, it indicates
|
|
137
|
-
# that the body of this object has a trailing auth tag. The header
|
|
138
|
-
# indicates the length of that tag.
|
|
139
|
-
#
|
|
140
163
|
# This method fetches the tag from the end of the object by
|
|
141
164
|
# making a GET Object w/range request. This auth tag is used
|
|
142
165
|
# to initialize the cipher, and the decrypter truncates the
|
|
143
166
|
# auth tag from the body when writing the final bytes.
|
|
144
|
-
def authenticated_decrypter(context, cipher)
|
|
167
|
+
def authenticated_decrypter(context, cipher, envelope)
|
|
145
168
|
if RUBY_VERSION.match(/1.9/)
|
|
146
|
-
raise "authenticated decryption not supported by
|
|
169
|
+
raise "authenticated decryption not supported by OpenSSL in Ruby version ~> 1.9"
|
|
147
170
|
raise Aws::Errors::NonSupportedRubyVersionError, msg
|
|
148
171
|
end
|
|
149
172
|
http_resp = context.http_response
|
|
150
173
|
content_length = http_resp.headers['content-length'].to_i
|
|
151
|
-
auth_tag_length =
|
|
152
|
-
auth_tag_length = auth_tag_length.to_i / 8
|
|
174
|
+
auth_tag_length = auth_tag_length(envelope)
|
|
153
175
|
|
|
154
176
|
auth_tag = context.client.get_object(
|
|
155
177
|
bucket: context.params[:bucket],
|
|
@@ -161,16 +183,40 @@ module Aws
|
|
|
161
183
|
cipher.auth_data = ''
|
|
162
184
|
|
|
163
185
|
# The encrypted object contains both the cipher text
|
|
164
|
-
# plus a trailing auth tag.
|
|
165
|
-
# expect for the trailing auth tag.
|
|
186
|
+
# plus a trailing auth tag.
|
|
166
187
|
IOAuthDecrypter.new(
|
|
167
188
|
io: http_resp.body,
|
|
168
189
|
encrypted_content_length: content_length - auth_tag_length,
|
|
169
190
|
cipher: cipher)
|
|
170
191
|
end
|
|
171
192
|
|
|
172
|
-
def body_contains_auth_tag?(
|
|
173
|
-
|
|
193
|
+
def body_contains_auth_tag?(envelope)
|
|
194
|
+
AUTH_REQUIRED_CEK_ALGS.include?(envelope['x-amz-cek-alg'])
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Determine the auth tag length from the algorithm
|
|
198
|
+
# Validate it against the value provided in the x-amz-tag-len
|
|
199
|
+
# Return the tag length in bytes
|
|
200
|
+
def auth_tag_length(envelope)
|
|
201
|
+
tag_length =
|
|
202
|
+
case envelope['x-amz-cek-alg']
|
|
203
|
+
when 'AES/GCM/NoPadding' then AES_GCM_TAG_LEN_BYTES
|
|
204
|
+
else
|
|
205
|
+
raise ArgumentError, 'Unsupported cek-alg: ' \
|
|
206
|
+
"#{envelope['x-amz-cek-alg']}"
|
|
207
|
+
end
|
|
208
|
+
if (tag_length * 8) != envelope['x-amz-tag-len'].to_i
|
|
209
|
+
raise Errors::DecryptionError, 'x-amz-tag-len does not match expected'
|
|
210
|
+
end
|
|
211
|
+
tag_length
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def apply_cse_user_agent(context)
|
|
215
|
+
if context.config.user_agent_suffix.nil?
|
|
216
|
+
context.config.user_agent_suffix = EC_USER_AGENT
|
|
217
|
+
elsif !context.config.user_agent_suffix.include? EC_USER_AGENT
|
|
218
|
+
context.config.user_agent_suffix += " #{EC_USER_AGENT}"
|
|
219
|
+
end
|
|
174
220
|
end
|
|
175
221
|
|
|
176
222
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'base64'
|
|
2
4
|
|
|
3
5
|
module Aws
|
|
@@ -24,11 +26,48 @@ module Aws
|
|
|
24
26
|
|
|
25
27
|
# @return [Cipher] Given an encryption envelope, returns a
|
|
26
28
|
# decryption cipher.
|
|
27
|
-
def decryption_cipher(envelope)
|
|
29
|
+
def decryption_cipher(envelope, options = {})
|
|
28
30
|
master_key = @key_provider.key_for(envelope['x-amz-matdesc'])
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
if envelope.key? 'x-amz-key'
|
|
32
|
+
# Support for decryption of legacy objects
|
|
33
|
+
key = Utils.decrypt(master_key, decode64(envelope['x-amz-key']))
|
|
34
|
+
iv = decode64(envelope['x-amz-iv'])
|
|
35
|
+
Utils.aes_decryption_cipher(:CBC, key, iv)
|
|
36
|
+
else
|
|
37
|
+
if envelope['x-amz-cek-alg'] != 'AES/GCM/NoPadding'
|
|
38
|
+
raise ArgumentError, 'Unsupported cek-alg: ' \
|
|
39
|
+
"#{envelope['x-amz-cek-alg']}"
|
|
40
|
+
end
|
|
41
|
+
key =
|
|
42
|
+
case envelope['x-amz-wrap-alg']
|
|
43
|
+
when 'AES/GCM'
|
|
44
|
+
if master_key.is_a? OpenSSL::PKey::RSA
|
|
45
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
|
46
|
+
' with an RSA key and the x-amz-wrap-alg is AES/GCM.'
|
|
47
|
+
end
|
|
48
|
+
Utils.decrypt_aes_gcm(master_key,
|
|
49
|
+
decode64(envelope['x-amz-key-v2']),
|
|
50
|
+
envelope['x-amz-cek-alg'])
|
|
51
|
+
when 'RSA-OAEP-SHA1'
|
|
52
|
+
unless master_key.is_a? OpenSSL::PKey::RSA
|
|
53
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
|
54
|
+
' with an AES key and the x-amz-wrap-alg is RSA-OAEP-SHA1.'
|
|
55
|
+
end
|
|
56
|
+
key, cek_alg = Utils.decrypt_rsa(master_key, decode64(envelope['x-amz-key-v2']))
|
|
57
|
+
raise Errors::DecryptionError unless cek_alg == envelope['x-amz-cek-alg']
|
|
58
|
+
key
|
|
59
|
+
when 'kms+context'
|
|
60
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
|
61
|
+
' with a user provided key and the x-amz-wrap-alg is' \
|
|
62
|
+
' kms+context. Please configure the client with the' \
|
|
63
|
+
' required kms_key_id'
|
|
64
|
+
else
|
|
65
|
+
raise ArgumentError, 'Unsupported wrap-alg: ' \
|
|
66
|
+
"#{envelope['x-amz-wrap-alg']}"
|
|
67
|
+
end
|
|
68
|
+
iv = decode64(envelope['x-amz-iv'])
|
|
69
|
+
Utils.aes_decryption_cipher(:GCM, key, iv)
|
|
70
|
+
end
|
|
32
71
|
end
|
|
33
72
|
|
|
34
73
|
private
|
|
@@ -56,7 +95,6 @@ module Aws
|
|
|
56
95
|
def decode64(str)
|
|
57
96
|
Base64.decode64(str)
|
|
58
97
|
end
|
|
59
|
-
|
|
60
98
|
end
|
|
61
99
|
end
|
|
62
100
|
end
|