aws-sdk-s3 1.65.0 → 1.69.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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/lib/aws-sdk-s3.rb +3 -1
  3. data/lib/aws-sdk-s3/bucket.rb +5 -3
  4. data/lib/aws-sdk-s3/bucket_acl.rb +2 -0
  5. data/lib/aws-sdk-s3/bucket_cors.rb +3 -1
  6. data/lib/aws-sdk-s3/bucket_lifecycle.rb +2 -0
  7. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +2 -0
  8. data/lib/aws-sdk-s3/bucket_logging.rb +2 -0
  9. data/lib/aws-sdk-s3/bucket_notification.rb +2 -0
  10. data/lib/aws-sdk-s3/bucket_policy.rb +2 -0
  11. data/lib/aws-sdk-s3/bucket_region_cache.rb +2 -0
  12. data/lib/aws-sdk-s3/bucket_request_payment.rb +2 -0
  13. data/lib/aws-sdk-s3/bucket_tagging.rb +2 -0
  14. data/lib/aws-sdk-s3/bucket_versioning.rb +2 -0
  15. data/lib/aws-sdk-s3/bucket_website.rb +6 -2
  16. data/lib/aws-sdk-s3/client.rb +530 -649
  17. data/lib/aws-sdk-s3/client_api.rb +40 -18
  18. data/lib/aws-sdk-s3/customizations.rb +3 -0
  19. data/lib/aws-sdk-s3/customizations/bucket.rb +4 -0
  20. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  21. data/lib/aws-sdk-s3/customizations/object.rb +5 -0
  22. data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
  23. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
  24. data/lib/aws-sdk-s3/encryption.rb +2 -0
  25. data/lib/aws-sdk-s3/encryption/client.rb +3 -1
  26. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +11 -0
  27. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +2 -0
  28. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
  29. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +11 -0
  30. data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
  31. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
  32. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +8 -1
  33. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
  34. data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
  35. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +2 -0
  36. data/lib/aws-sdk-s3/encryption/materials.rb +2 -0
  37. data/lib/aws-sdk-s3/encryption/utils.rb +2 -0
  38. data/lib/aws-sdk-s3/encryptionV2/client.rb +378 -0
  39. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +194 -0
  40. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +104 -0
  41. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +38 -0
  42. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +63 -0
  43. data/lib/aws-sdk-s3/encryptionV2/errors.rb +13 -0
  44. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +56 -0
  45. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +30 -0
  46. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +67 -0
  47. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +29 -0
  48. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +84 -0
  49. data/lib/aws-sdk-s3/encryptionV2/materials.rb +58 -0
  50. data/lib/aws-sdk-s3/encryptionV2/utils.rb +116 -0
  51. data/lib/aws-sdk-s3/encryption_v2.rb +20 -0
  52. data/lib/aws-sdk-s3/errors.rb +2 -0
  53. data/lib/aws-sdk-s3/event_streams.rb +7 -0
  54. data/lib/aws-sdk-s3/file_downloader.rb +2 -0
  55. data/lib/aws-sdk-s3/file_part.rb +2 -0
  56. data/lib/aws-sdk-s3/file_uploader.rb +2 -0
  57. data/lib/aws-sdk-s3/legacy_signer.rb +2 -0
  58. data/lib/aws-sdk-s3/multipart_file_uploader.rb +2 -0
  59. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +2 -0
  60. data/lib/aws-sdk-s3/multipart_upload.rb +3 -1
  61. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  62. data/lib/aws-sdk-s3/multipart_upload_part.rb +2 -0
  63. data/lib/aws-sdk-s3/object.rb +16 -4
  64. data/lib/aws-sdk-s3/object_acl.rb +2 -0
  65. data/lib/aws-sdk-s3/object_copier.rb +2 -0
  66. data/lib/aws-sdk-s3/object_multipart_copier.rb +2 -0
  67. data/lib/aws-sdk-s3/object_summary.rb +14 -3
  68. data/lib/aws-sdk-s3/object_version.rb +17 -1
  69. data/lib/aws-sdk-s3/plugins/accelerate.rb +2 -0
  70. data/lib/aws-sdk-s3/plugins/bucket_arn.rb +2 -0
  71. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +2 -0
  72. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +2 -0
  73. data/lib/aws-sdk-s3/plugins/dualstack.rb +2 -0
  74. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +3 -4
  75. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +2 -0
  76. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +3 -1
  77. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +2 -0
  78. data/lib/aws-sdk-s3/plugins/location_constraint.rb +2 -0
  79. data/lib/aws-sdk-s3/plugins/md5s.rb +23 -24
  80. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  81. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  82. data/lib/aws-sdk-s3/plugins/s3_signer.rb +2 -0
  83. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +2 -0
  84. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
  85. data/lib/aws-sdk-s3/presigned_post.rb +2 -0
  86. data/lib/aws-sdk-s3/presigner.rb +2 -0
  87. data/lib/aws-sdk-s3/resource.rb +3 -1
  88. data/lib/aws-sdk-s3/types.rb +140 -37
  89. data/lib/aws-sdk-s3/waiters.rb +2 -0
  90. metadata +18 -4
@@ -0,0 +1,30 @@
1
+ module Aws
2
+ module S3
3
+ module EncryptionV2
4
+ # @api private
5
+ class IODecrypter
6
+
7
+ # @param [OpenSSL::Cipher] cipher
8
+ # @param [IO#write] io An IO-like object that responds to `#write`.
9
+ def initialize(cipher, io)
10
+ @cipher = cipher.clone
11
+ # Ensure that IO is reset between retries
12
+ @io = io.tap { |io| io.truncate(0) if io.respond_to?(:truncate) }
13
+ end
14
+
15
+ # @return [#write]
16
+ attr_reader :io
17
+
18
+ def write(chunk)
19
+ # decrypt and write
20
+ @io.write(@cipher.update(chunk))
21
+ end
22
+
23
+ def finalize
24
+ @io.write(@cipher.final)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+ require 'stringio'
2
+ require 'tempfile'
3
+
4
+ module Aws
5
+ module S3
6
+ module EncryptionV2
7
+
8
+ # Provides an IO wrapper encrypting a stream of data.
9
+ # @api private
10
+ class IOEncrypter
11
+
12
+ # @api private
13
+ ONE_MEGABYTE = 1024 * 1024
14
+
15
+ def initialize(cipher, io)
16
+ @encrypted = io.size <= ONE_MEGABYTE ?
17
+ encrypt_to_stringio(cipher, io.read) :
18
+ encrypt_to_tempfile(cipher, io)
19
+ @size = @encrypted.size
20
+ end
21
+
22
+ # @return [Integer]
23
+ attr_reader :size
24
+
25
+ def read(bytes = nil, output_buffer = nil)
26
+ if @encrypted.is_a?(Tempfile) && @encrypted.closed?
27
+ @encrypted.open
28
+ @encrypted.binmode
29
+ end
30
+ @encrypted.read(bytes, output_buffer)
31
+ end
32
+
33
+ def rewind
34
+ @encrypted.rewind
35
+ end
36
+
37
+ # @api private
38
+ def close
39
+ @encrypted.close if @encrypted.is_a?(Tempfile)
40
+ end
41
+
42
+ private
43
+
44
+ def encrypt_to_stringio(cipher, plain_text)
45
+ if plain_text.empty?
46
+ StringIO.new(cipher.final + cipher.auth_tag)
47
+ else
48
+ StringIO.new(cipher.update(plain_text) + cipher.final + cipher.auth_tag)
49
+ end
50
+ end
51
+
52
+ def encrypt_to_tempfile(cipher, io)
53
+ encrypted = Tempfile.new(self.object_id.to_s)
54
+ encrypted.binmode
55
+ while chunk = io.read(ONE_MEGABYTE)
56
+ encrypted.write(cipher.update(chunk))
57
+ end
58
+ encrypted.write(cipher.final)
59
+ encrypted.write(cipher.auth_tag)
60
+ encrypted.rewind
61
+ encrypted
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,29 @@
1
+ module Aws
2
+ module S3
3
+ module EncryptionV2
4
+
5
+ # This module defines the interface required for a {Client#key_provider}.
6
+ # A key provider is any object that:
7
+ #
8
+ # * Responds to {#encryption_materials} with an {Materials} object.
9
+ #
10
+ # * Responds to {#key_for}, receiving a JSON document String,
11
+ # returning an encryption key. The returned encryption key
12
+ # must be one of:
13
+ #
14
+ # * `OpenSSL::PKey::RSA` - for asymmetric encryption
15
+ # * `String` - 32, 24, or 16 bytes long, for symmetric encryption
16
+ #
17
+ module KeyProvider
18
+
19
+ # @return [Materials]
20
+ def encryption_materials; end
21
+
22
+ # @param [String<JSON>] materials_description
23
+ # @return [OpenSSL::PKey::RSA, String] encryption_key
24
+ def key_for(materials_description); end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,84 @@
1
+ require 'base64'
2
+
3
+ module Aws
4
+ module S3
5
+ module EncryptionV2
6
+ # @api private
7
+ class KmsCipherProvider
8
+
9
+ def initialize(options = {})
10
+ @kms_key_id = options[:kms_key_id]
11
+ @kms_client = options[:kms_client]
12
+ end
13
+
14
+ # @return [Array<Hash,Cipher>] Creates and returns a new encryption
15
+ # envelope and encryption cipher.
16
+ def encryption_cipher
17
+ cek_alg = 'AES/GCM/NoPadding'
18
+ encryption_context = {
19
+ 'aws:x-amz-cek-alg' => cek_alg
20
+ }
21
+ key_data = @kms_client.generate_data_key(
22
+ key_id: @kms_key_id,
23
+ encryption_context: encryption_context,
24
+ key_spec: 'AES_256',
25
+ )
26
+ cipher = Utils.aes_encryption_cipher(:GCM)
27
+ cipher.key = key_data.plaintext
28
+ envelope = {
29
+ 'x-amz-key-v2' => encode64(key_data.ciphertext_blob),
30
+ 'x-amz-iv' => encode64(cipher.iv = cipher.random_iv),
31
+ 'x-amz-cek-alg' => cek_alg,
32
+ 'x-amz-tag-len' => 16 * 8,
33
+ 'x-amz-wrap-alg' => 'kms+context',
34
+ 'x-amz-matdesc' => Json.dump(encryption_context)
35
+ }
36
+ cipher.auth_data = '' # auth_data must be set after key and iv
37
+ [envelope, cipher]
38
+ end
39
+
40
+ # @return [Cipher] Given an encryption envelope, returns a
41
+ # decryption cipher.
42
+ def decryption_cipher(envelope)
43
+ encryption_context = Json.load(envelope['x-amz-matdesc'])
44
+ key = @kms_client.decrypt(
45
+ ciphertext_blob: decode64(envelope['x-amz-key-v2']),
46
+ encryption_context: encryption_context
47
+ ).plaintext
48
+ cek_alg = envelope['x-amz-wrap-alg'] == 'kms+context' ?
49
+ encryption_context['aws:x-amz-cek-alg'] : envelope['x-amz-cek-alg']
50
+ if cek_alg != envelope['x-amz-cek-alg']
51
+ raise Errors::DecryptionError, 'Value of cek-alg from envelope'\
52
+ ' does not match the value in the encryption context'
53
+ end
54
+ iv = decode64(envelope['x-amz-iv'])
55
+ block_mode =
56
+ case cek_alg
57
+ when 'AES/CBC/PKCS5Padding'
58
+ :CBC
59
+ when 'AES/CBC/PKCS7Padding'
60
+ :CBC
61
+ when 'AES/GCM/NoPadding'
62
+ :GCM
63
+ else
64
+ type = envelope['x-amz-cek-alg'].inspect
65
+ msg = "unsupported content encrypting key (cek) format: #{type}"
66
+ raise Errors::DecryptionError, msg
67
+ end
68
+ Utils.aes_decryption_cipher(block_mode, key, iv)
69
+ end
70
+
71
+ private
72
+
73
+ def encode64(str)
74
+ Base64.encode64(str).split("\n") * ""
75
+ end
76
+
77
+ def decode64(str)
78
+ Base64.decode64(str)
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,58 @@
1
+ require 'base64'
2
+
3
+ module Aws
4
+ module S3
5
+ module EncryptionV2
6
+ class Materials
7
+
8
+ # @option options [required, OpenSSL::PKey::RSA, String] :key
9
+ # The master key to use for encrypting/decrypting all objects.
10
+ #
11
+ # @option options [String<JSON>] :description ('{}')
12
+ # The encryption materials description. This is must be
13
+ # a JSON document string.
14
+ #
15
+ def initialize(options = {})
16
+ @key = validate_key(options[:key])
17
+ @description = validate_desc(options[:description])
18
+ end
19
+
20
+ # @return [OpenSSL::PKey::RSA, String]
21
+ attr_reader :key
22
+
23
+ # @return [String<JSON>]
24
+ attr_reader :description
25
+
26
+ private
27
+
28
+ def validate_key(key)
29
+ case key
30
+ when OpenSSL::PKey::RSA then key
31
+ when String
32
+ if [32, 24, 16].include?(key.bytesize)
33
+ key
34
+ else
35
+ msg = 'invalid key, symmetric key required to be 16, 24, or '\
36
+ '32 bytes in length, saw length ' + key.bytesize.to_s
37
+ raise ArgumentError, msg
38
+ end
39
+ else
40
+ msg = 'invalid encryption key, expected an OpenSSL::PKey::RSA key '\
41
+ '(for asymmetric encryption) or a String (for symmetric '\
42
+ 'encryption).'
43
+ raise ArgumentError, msg
44
+ end
45
+ end
46
+
47
+ def validate_desc(description)
48
+ Json.load(description)
49
+ description
50
+ rescue Json::ParseError, EncodingError
51
+ msg = 'expected description to be a valid JSON document string'
52
+ raise ArgumentError, msg
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,116 @@
1
+ require 'openssl'
2
+
3
+ module Aws
4
+ module S3
5
+ module EncryptionV2
6
+ # @api private
7
+ module Utils
8
+
9
+ UNSAFE_MSG = "unsafe encryption, data is longer than key length"
10
+
11
+ class << self
12
+
13
+ def encrypt(key, data)
14
+ case key
15
+ when OpenSSL::PKey::RSA # asymmetric encryption
16
+ warn(UNSAFE_MSG) if key.public_key.n.num_bits < cipher_size(data)
17
+ key.public_encrypt(data)
18
+ when String # symmetric encryption
19
+ warn(UNSAFE_MSG) if cipher_size(key) < cipher_size(data)
20
+ cipher = aes_encryption_cipher(:ECB, key)
21
+ cipher.update(data) + cipher.final
22
+ end
23
+ end
24
+
25
+ def encrypt_aes_gcm(key, data, auth_data)
26
+ warn(UNSAFE_MSG) if cipher_size(key) < cipher_size(data)
27
+ cipher = aes_encryption_cipher(:GCM, key)
28
+ cipher.iv = (iv = cipher.random_iv)
29
+ cipher.auth_data = auth_data
30
+
31
+ iv + cipher.update(data) + cipher.final + cipher.auth_tag
32
+ end
33
+
34
+ def encrypt_rsa(key, data, auth_data)
35
+ # Plaintext must be KeyLengthInBytes (1 Byte) + DataKey + AuthData
36
+ buf = [data.bytesize] + data.unpack('C*') + auth_data.unpack('C*')
37
+ key.public_encrypt(buf.pack('C*'), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
38
+ end
39
+
40
+ def decrypt(key, data)
41
+ begin
42
+ case key
43
+ when OpenSSL::PKey::RSA # asymmetric decryption
44
+ key.private_decrypt(data)
45
+ when String # symmetric Decryption
46
+ cipher = aes_cipher(:decrypt, :ECB, key, nil)
47
+ cipher.update(data) + cipher.final
48
+ end
49
+ rescue OpenSSL::Cipher::CipherError
50
+ msg = 'decryption failed, possible incorrect key'
51
+ raise Errors::DecryptionError, msg
52
+ end
53
+ end
54
+
55
+ def decrypt_aes_gcm(key, data, auth_data)
56
+ # data is iv (12B) + key + tag (16B)
57
+ buf = data.unpack('C*')
58
+ iv = buf[0,12].pack('C*') # iv will always be 12 bytes
59
+ tag = buf[-16, 16].pack('C*') # tag is 16 bytes
60
+ enc_key = buf[12, buf.size - (12+16)].pack('C*')
61
+ cipher = aes_cipher(:decrypt, :GCM, key, iv)
62
+ cipher.auth_tag = tag
63
+ cipher.auth_data = auth_data
64
+ cipher.update(enc_key) + cipher.final
65
+ end
66
+
67
+ # returns the decrypted data + auth_data
68
+ def decrypt_rsa(key, enc_data)
69
+ # Plaintext must be KeyLengthInBytes (1 Byte) + DataKey + AuthData
70
+ buf = key.private_decrypt(enc_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING).unpack('C*')
71
+ key_length = buf[0]
72
+ data = buf[1, key_length].pack('C*')
73
+ auth_data = buf[key_length+1, buf.length - key_length].pack('C*')
74
+ [data, auth_data]
75
+ end
76
+
77
+ # @param [String] block_mode "CBC" or "ECB"
78
+ # @param [OpenSSL::PKey::RSA, String, nil] key
79
+ # @param [String, nil] iv The initialization vector
80
+ def aes_encryption_cipher(block_mode, key = nil, iv = nil)
81
+ aes_cipher(:encrypt, block_mode, key, iv)
82
+ end
83
+
84
+ # @param [String] block_mode "CBC" or "ECB"
85
+ # @param [OpenSSL::PKey::RSA, String, nil] key
86
+ # @param [String, nil] iv The initialization vector
87
+ def aes_decryption_cipher(block_mode, key = nil, iv = nil)
88
+ aes_cipher(:decrypt, block_mode, key, iv)
89
+ end
90
+
91
+ # @param [String] mode "encrypt" or "decrypt"
92
+ # @param [String] block_mode "CBC" or "ECB"
93
+ # @param [OpenSSL::PKey::RSA, String, nil] key
94
+ # @param [String, nil] iv The initialization vector
95
+ def aes_cipher(mode, block_mode, key, iv)
96
+ cipher = key ?
97
+ OpenSSL::Cipher.new("aes-#{cipher_size(key)}-#{block_mode.downcase}") :
98
+ OpenSSL::Cipher.new("aes-256-#{block_mode.downcase}")
99
+ cipher.send(mode) # encrypt or decrypt
100
+ cipher.key = key if key
101
+ cipher.iv = iv if iv
102
+ cipher
103
+ end
104
+
105
+ # @param [String] key
106
+ # @return [Integer]
107
+ # @raise ArgumentError
108
+ def cipher_size(key)
109
+ key.bytesize * 8
110
+ end
111
+
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,20 @@
1
+ require 'aws-sdk-s3/encryptionV2/client'
2
+ require 'aws-sdk-s3/encryptionV2/decrypt_handler'
3
+ require 'aws-sdk-s3/encryptionV2/default_cipher_provider'
4
+ require 'aws-sdk-s3/encryptionV2/encrypt_handler'
5
+ require 'aws-sdk-s3/encryptionV2/errors'
6
+ require 'aws-sdk-s3/encryptionV2/io_encrypter'
7
+ require 'aws-sdk-s3/encryptionV2/io_decrypter'
8
+ require 'aws-sdk-s3/encryptionV2/io_auth_decrypter'
9
+ require 'aws-sdk-s3/encryptionV2/key_provider'
10
+ require 'aws-sdk-s3/encryptionV2/kms_cipher_provider'
11
+ require 'aws-sdk-s3/encryptionV2/materials'
12
+ require 'aws-sdk-s3/encryptionV2/utils'
13
+ require 'aws-sdk-s3/encryptionV2/default_key_provider'
14
+
15
+ module Aws
16
+ module S3
17
+ module EncryptionV2; end
18
+ end
19
+ end
20
+
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # WARNING ABOUT GENERATED CODE
2
4
  #
3
5
  # This file is generated. See the contributing guide for more information:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # WARNING ABOUT GENERATED CODE
2
4
  #
3
5
  # This file is generated. See the contributing guide for more information:
@@ -41,6 +43,10 @@ module Aws::S3
41
43
  @event_emitter.on(:initial_response, block) if block_given?
42
44
  end
43
45
 
46
+ def on_unknown_event(&block)
47
+ @event_emitter.on(:unknown_event, block) if block_given?
48
+ end
49
+
44
50
  def on_event(&block)
45
51
  on_records_event(&block)
46
52
  on_stats_event(&block)
@@ -49,6 +55,7 @@ module Aws::S3
49
55
  on_end_event(&block)
50
56
  on_error_event(&block)
51
57
  on_initial_response_event(&block)
58
+ on_unknown_event(&block)
52
59
  end
53
60
 
54
61
  # @api private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
  require 'thread'
3
5
  require 'set'