aws-sdk-s3 1.48.0 → 1.183.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 (134) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1352 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-sdk-s3/access_grants_credentials.rb +57 -0
  6. data/lib/aws-sdk-s3/access_grants_credentials_provider.rb +250 -0
  7. data/lib/aws-sdk-s3/bucket.rb +1005 -106
  8. data/lib/aws-sdk-s3/bucket_acl.rb +65 -18
  9. data/lib/aws-sdk-s3/bucket_cors.rb +80 -18
  10. data/lib/aws-sdk-s3/bucket_lifecycle.rb +71 -20
  11. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +126 -21
  12. data/lib/aws-sdk-s3/bucket_logging.rb +68 -16
  13. data/lib/aws-sdk-s3/bucket_notification.rb +52 -20
  14. data/lib/aws-sdk-s3/bucket_policy.rb +108 -17
  15. data/lib/aws-sdk-s3/bucket_region_cache.rb +11 -5
  16. data/lib/aws-sdk-s3/bucket_request_payment.rb +60 -15
  17. data/lib/aws-sdk-s3/bucket_tagging.rb +71 -18
  18. data/lib/aws-sdk-s3/bucket_versioning.rb +133 -17
  19. data/lib/aws-sdk-s3/bucket_website.rb +78 -21
  20. data/lib/aws-sdk-s3/client.rb +14517 -941
  21. data/lib/aws-sdk-s3/client_api.rb +1296 -197
  22. data/lib/aws-sdk-s3/customizations/bucket.rb +56 -37
  23. data/lib/aws-sdk-s3/customizations/errors.rb +40 -0
  24. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  25. data/lib/aws-sdk-s3/customizations/object.rb +288 -68
  26. data/lib/aws-sdk-s3/customizations/object_summary.rb +10 -0
  27. data/lib/aws-sdk-s3/customizations/object_version.rb +13 -0
  28. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
  29. data/lib/aws-sdk-s3/customizations/types/permanent_redirect.rb +26 -0
  30. data/lib/aws-sdk-s3/customizations.rb +27 -28
  31. data/lib/aws-sdk-s3/encryption/client.rb +28 -7
  32. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +71 -29
  33. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
  34. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
  35. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
  36. data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
  37. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
  38. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
  39. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
  40. data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
  41. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +46 -11
  42. data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
  43. data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
  44. data/lib/aws-sdk-s3/encryption.rb +4 -0
  45. data/lib/aws-sdk-s3/encryptionV2/client.rb +570 -0
  46. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +223 -0
  47. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
  48. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
  49. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +65 -0
  50. data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
  51. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
  52. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
  53. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
  54. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
  55. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +173 -0
  56. data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
  57. data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
  58. data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
  59. data/lib/aws-sdk-s3/endpoint_parameters.rb +181 -0
  60. data/lib/aws-sdk-s3/endpoint_provider.rb +716 -0
  61. data/lib/aws-sdk-s3/endpoints.rb +1434 -0
  62. data/lib/aws-sdk-s3/errors.rb +170 -1
  63. data/lib/aws-sdk-s3/event_streams.rb +8 -1
  64. data/lib/aws-sdk-s3/express_credentials.rb +55 -0
  65. data/lib/aws-sdk-s3/express_credentials_provider.rb +59 -0
  66. data/lib/aws-sdk-s3/file_downloader.rb +161 -46
  67. data/lib/aws-sdk-s3/file_part.rb +11 -6
  68. data/lib/aws-sdk-s3/file_uploader.rb +39 -18
  69. data/lib/aws-sdk-s3/legacy_signer.rb +17 -25
  70. data/lib/aws-sdk-s3/multipart_file_uploader.rb +104 -27
  71. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +61 -21
  72. data/lib/aws-sdk-s3/multipart_upload.rb +342 -32
  73. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  74. data/lib/aws-sdk-s3/multipart_upload_part.rb +384 -46
  75. data/lib/aws-sdk-s3/object.rb +2600 -231
  76. data/lib/aws-sdk-s3/object_acl.rb +103 -25
  77. data/lib/aws-sdk-s3/object_copier.rb +9 -5
  78. data/lib/aws-sdk-s3/object_multipart_copier.rb +48 -22
  79. data/lib/aws-sdk-s3/object_summary.rb +2174 -204
  80. data/lib/aws-sdk-s3/object_version.rb +539 -80
  81. data/lib/aws-sdk-s3/plugins/accelerate.rb +17 -64
  82. data/lib/aws-sdk-s3/plugins/access_grants.rb +178 -0
  83. data/lib/aws-sdk-s3/plugins/arn.rb +70 -0
  84. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +7 -43
  85. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +20 -3
  86. data/lib/aws-sdk-s3/plugins/checksum_algorithm.rb +31 -0
  87. data/lib/aws-sdk-s3/plugins/dualstack.rb +7 -50
  88. data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
  89. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +5 -4
  90. data/lib/aws-sdk-s3/plugins/express_session_auth.rb +88 -0
  91. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  92. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +62 -17
  93. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +44 -0
  94. data/lib/aws-sdk-s3/plugins/location_constraint.rb +5 -1
  95. data/lib/aws-sdk-s3/plugins/md5s.rb +14 -70
  96. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  97. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  98. data/lib/aws-sdk-s3/plugins/s3_signer.rb +63 -94
  99. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
  100. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +139 -0
  101. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
  102. data/lib/aws-sdk-s3/presigned_post.rb +160 -99
  103. data/lib/aws-sdk-s3/presigner.rb +141 -62
  104. data/lib/aws-sdk-s3/resource.rb +156 -17
  105. data/lib/aws-sdk-s3/types.rb +13021 -4106
  106. data/lib/aws-sdk-s3/waiters.rb +67 -1
  107. data/lib/aws-sdk-s3.rb +46 -32
  108. data/sig/bucket.rbs +222 -0
  109. data/sig/bucket_acl.rbs +78 -0
  110. data/sig/bucket_cors.rbs +69 -0
  111. data/sig/bucket_lifecycle.rbs +88 -0
  112. data/sig/bucket_lifecycle_configuration.rbs +115 -0
  113. data/sig/bucket_logging.rbs +76 -0
  114. data/sig/bucket_notification.rbs +114 -0
  115. data/sig/bucket_policy.rbs +59 -0
  116. data/sig/bucket_request_payment.rbs +54 -0
  117. data/sig/bucket_tagging.rbs +65 -0
  118. data/sig/bucket_versioning.rbs +77 -0
  119. data/sig/bucket_website.rbs +93 -0
  120. data/sig/client.rbs +2472 -0
  121. data/sig/customizations/bucket.rbs +19 -0
  122. data/sig/customizations/object.rbs +38 -0
  123. data/sig/customizations/object_summary.rbs +35 -0
  124. data/sig/errors.rbs +42 -0
  125. data/sig/multipart_upload.rbs +120 -0
  126. data/sig/multipart_upload_part.rbs +109 -0
  127. data/sig/object.rbs +459 -0
  128. data/sig/object_acl.rbs +86 -0
  129. data/sig/object_summary.rbs +345 -0
  130. data/sig/object_version.rbs +143 -0
  131. data/sig/resource.rbs +134 -0
  132. data/sig/types.rbs +2712 -0
  133. data/sig/waiters.rbs +95 -0
  134. metadata +74 -15
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+ require 'tempfile'
5
+
6
+ module Aws
7
+ module S3
8
+ module EncryptionV2
9
+
10
+ # Provides an IO wrapper encrypting a stream of data.
11
+ # @api private
12
+ class IOEncrypter
13
+
14
+ # @api private
15
+ ONE_MEGABYTE = 1024 * 1024
16
+
17
+ def initialize(cipher, io)
18
+ @encrypted = io.size <= ONE_MEGABYTE ?
19
+ encrypt_to_stringio(cipher, io.read) :
20
+ encrypt_to_tempfile(cipher, io)
21
+ @size = @encrypted.size
22
+ end
23
+
24
+ # @return [Integer]
25
+ attr_reader :size
26
+
27
+ def read(bytes = nil, output_buffer = nil)
28
+ if @encrypted.is_a?(Tempfile) && @encrypted.closed?
29
+ @encrypted.open
30
+ @encrypted.binmode
31
+ end
32
+ @encrypted.read(bytes, output_buffer)
33
+ end
34
+
35
+ def rewind
36
+ @encrypted.rewind
37
+ end
38
+
39
+ # @api private
40
+ def close
41
+ @encrypted.close if @encrypted.is_a?(Tempfile)
42
+ end
43
+
44
+ private
45
+
46
+ def encrypt_to_stringio(cipher, plain_text)
47
+ if plain_text.empty?
48
+ StringIO.new(cipher.final + cipher.auth_tag)
49
+ else
50
+ StringIO.new(cipher.update(plain_text) + cipher.final + cipher.auth_tag)
51
+ end
52
+ end
53
+
54
+ def encrypt_to_tempfile(cipher, io)
55
+ encrypted = Tempfile.new(self.object_id.to_s)
56
+ encrypted.binmode
57
+ while chunk = io.read(ONE_MEGABYTE, read_buffer ||= String.new)
58
+ if cipher.method(:update).arity == 1
59
+ encrypted.write(cipher.update(chunk))
60
+ else
61
+ encrypted.write(cipher.update(chunk, cipher_buffer ||= String.new))
62
+ end
63
+ end
64
+ encrypted.write(cipher.final)
65
+ encrypted.write(cipher.auth_tag)
66
+ encrypted.rewind
67
+ encrypted
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module EncryptionV2
6
+
7
+ # This module defines the interface required for a {Client#key_provider}.
8
+ # A key provider is any object that:
9
+ #
10
+ # * Responds to {#encryption_materials} with an {Materials} object.
11
+ #
12
+ # * Responds to {#key_for}, receiving a JSON document String,
13
+ # returning an encryption key. The returned encryption key
14
+ # must be one of:
15
+ #
16
+ # * `OpenSSL::PKey::RSA` - for asymmetric encryption
17
+ # * `String` - 32, 24, or 16 bytes long, for symmetric encryption
18
+ #
19
+ module KeyProvider
20
+
21
+ # @return [Materials]
22
+ def encryption_materials; end
23
+
24
+ # @param [String<JSON>] materials_description
25
+ # @return [OpenSSL::PKey::RSA, String] encryption_key
26
+ def key_for(materials_description); end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Aws
6
+ module S3
7
+ module EncryptionV2
8
+ # @api private
9
+ class KmsCipherProvider
10
+
11
+ def initialize(options = {})
12
+ @kms_key_id = validate_kms_key(options[:kms_key_id])
13
+ @kms_client = options[:kms_client]
14
+ @key_wrap_schema = validate_key_wrap(
15
+ options[:key_wrap_schema]
16
+ )
17
+ @content_encryption_schema = validate_cek(
18
+ options[:content_encryption_schema]
19
+ )
20
+ end
21
+
22
+ # @return [Array<Hash,Cipher>] Creates and returns a new encryption
23
+ # envelope and encryption cipher.
24
+ def encryption_cipher(options = {})
25
+ validate_key_for_encryption
26
+ encryption_context = build_encryption_context(@content_encryption_schema, options)
27
+ key_data = Aws::Plugins::UserAgent.metric('S3_CRYPTO_V2') do
28
+ @kms_client.generate_data_key(
29
+ key_id: @kms_key_id,
30
+ encryption_context: encryption_context,
31
+ key_spec: 'AES_256'
32
+ )
33
+ end
34
+ cipher = Utils.aes_encryption_cipher(:GCM)
35
+ cipher.key = key_data.plaintext
36
+ envelope = {
37
+ 'x-amz-key-v2' => encode64(key_data.ciphertext_blob),
38
+ 'x-amz-iv' => encode64(cipher.iv = cipher.random_iv),
39
+ 'x-amz-cek-alg' => @content_encryption_schema,
40
+ 'x-amz-tag-len' => (AES_GCM_TAG_LEN_BYTES * 8).to_s,
41
+ 'x-amz-wrap-alg' => @key_wrap_schema,
42
+ 'x-amz-matdesc' => Json.dump(encryption_context)
43
+ }
44
+ cipher.auth_data = '' # auth_data must be set after key and iv
45
+ [envelope, cipher]
46
+ end
47
+
48
+ # @return [Cipher] Given an encryption envelope, returns a
49
+ # decryption cipher.
50
+ def decryption_cipher(envelope, options = {})
51
+ encryption_context = Json.load(envelope['x-amz-matdesc'])
52
+ cek_alg = envelope['x-amz-cek-alg']
53
+
54
+ case envelope['x-amz-wrap-alg']
55
+ when 'kms'
56
+ unless options[:security_profile] == :v2_and_legacy
57
+ raise Errors::LegacyDecryptionError
58
+ end
59
+ when 'kms+context'
60
+ if cek_alg != encryption_context['aws:x-amz-cek-alg']
61
+ raise Errors::CEKAlgMismatchError
62
+ end
63
+
64
+ if encryption_context != build_encryption_context(cek_alg, options)
65
+ raise Errors::DecryptionError, 'Value of encryption context from'\
66
+ ' envelope does not match the provided encryption context'
67
+ end
68
+ when 'AES/GCM'
69
+ raise ArgumentError, 'Key mismatch - Client is configured' \
70
+ ' with a KMS key and the x-amz-wrap-alg is AES/GCM.'
71
+ when 'RSA-OAEP-SHA1'
72
+ raise ArgumentError, 'Key mismatch - Client is configured' \
73
+ ' with a KMS key and the x-amz-wrap-alg is RSA-OAEP-SHA1.'
74
+ else
75
+ raise ArgumentError, 'Unsupported wrap-alg: ' \
76
+ "#{envelope['x-amz-wrap-alg']}"
77
+ end
78
+
79
+ any_cmk_mode = false || options[:kms_allow_decrypt_with_any_cmk]
80
+ decrypt_options = {
81
+ ciphertext_blob: decode64(envelope['x-amz-key-v2']),
82
+ encryption_context: encryption_context
83
+ }
84
+ unless any_cmk_mode
85
+ decrypt_options[:key_id] = @kms_key_id
86
+ end
87
+
88
+ key = Aws::Plugins::UserAgent.metric('S3_CRYPTO_V2') do
89
+ @kms_client.decrypt(decrypt_options).plaintext
90
+ end
91
+ iv = decode64(envelope['x-amz-iv'])
92
+ block_mode =
93
+ case cek_alg
94
+ when 'AES/CBC/PKCS5Padding'
95
+ :CBC
96
+ when 'AES/CBC/PKCS7Padding'
97
+ :CBC
98
+ when 'AES/GCM/NoPadding'
99
+ :GCM
100
+ else
101
+ type = envelope['x-amz-cek-alg'].inspect
102
+ msg = "unsupported content encrypting key (cek) format: #{type}"
103
+ raise Errors::DecryptionError, msg
104
+ end
105
+ Utils.aes_decryption_cipher(block_mode, key, iv)
106
+ end
107
+
108
+ private
109
+
110
+ def validate_key_wrap(key_wrap_schema)
111
+ case key_wrap_schema
112
+ when :kms_context then 'kms+context'
113
+ else
114
+ raise ArgumentError, "Unsupported key_wrap_schema: #{key_wrap_schema}"
115
+ end
116
+ end
117
+
118
+ def validate_cek(content_encryption_schema)
119
+ case content_encryption_schema
120
+ when :aes_gcm_no_padding
121
+ "AES/GCM/NoPadding"
122
+ else
123
+ raise ArgumentError, "Unsupported content_encryption_schema: #{content_encryption_schema}"
124
+ end
125
+ end
126
+
127
+ def validate_kms_key(kms_key_id)
128
+ if kms_key_id.nil? || kms_key_id.length.zero?
129
+ raise ArgumentError, 'KMS CMK ID was not specified. ' \
130
+ 'Please specify a CMK ID, ' \
131
+ 'or set kms_key_id: :kms_allow_decrypt_with_any_cmk to use ' \
132
+ 'any valid CMK from the object.'
133
+ end
134
+
135
+ if kms_key_id.is_a?(Symbol) && kms_key_id != :kms_allow_decrypt_with_any_cmk
136
+ raise ArgumentError, 'kms_key_id must be a valid KMS CMK or be ' \
137
+ 'set to :kms_allow_decrypt_with_any_cmk'
138
+ end
139
+ kms_key_id
140
+ end
141
+
142
+ def build_encryption_context(cek_alg, options = {})
143
+ kms_context = (options[:kms_encryption_context] || {})
144
+ .each_with_object({}) { |(k, v), h| h[k.to_s] = v }
145
+ if kms_context.include? 'aws:x-amz-cek-alg'
146
+ raise ArgumentError, 'Conflict in reserved KMS Encryption Context ' \
147
+ 'key aws:x-amz-cek-alg. This value is reserved for the S3 ' \
148
+ 'Encryption Client and cannot be set by the user.'
149
+ end
150
+ {
151
+ 'aws:x-amz-cek-alg' => cek_alg
152
+ }.merge(kms_context)
153
+ end
154
+
155
+ def encode64(str)
156
+ Base64.encode64(str).split("\n") * ""
157
+ end
158
+
159
+ def decode64(str)
160
+ Base64.decode64(str)
161
+ end
162
+
163
+ def validate_key_for_encryption
164
+ if @kms_key_id == :kms_allow_decrypt_with_any_cmk
165
+ raise ArgumentError, 'Unable to encrypt/write objects with '\
166
+ 'kms_key_id = :kms_allow_decrypt_with_any_cmk. Provide ' \
167
+ 'a valid kms_key_id on client construction.'
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Aws
6
+ module S3
7
+ module EncryptionV2
8
+ class Materials
9
+
10
+ # @option options [required, OpenSSL::PKey::RSA, String] :key
11
+ # The master key to use for encrypting/decrypting all objects.
12
+ #
13
+ # @option options [String<JSON>] :description ('{}')
14
+ # The encryption materials description. This is must be
15
+ # a JSON document string.
16
+ #
17
+ def initialize(options = {})
18
+ @key = validate_key(options[:key])
19
+ @description = validate_desc(options[:description])
20
+ end
21
+
22
+ # @return [OpenSSL::PKey::RSA, String]
23
+ attr_reader :key
24
+
25
+ # @return [String<JSON>]
26
+ attr_reader :description
27
+
28
+ private
29
+
30
+ def validate_key(key)
31
+ case key
32
+ when OpenSSL::PKey::RSA then key
33
+ when String
34
+ if [32, 24, 16].include?(key.bytesize)
35
+ key
36
+ else
37
+ msg = 'invalid key, symmetric key required to be 16, 24, or '\
38
+ '32 bytes in length, saw length ' + key.bytesize.to_s
39
+ raise ArgumentError, msg
40
+ end
41
+ else
42
+ msg = 'invalid encryption key, expected an OpenSSL::PKey::RSA key '\
43
+ '(for asymmetric encryption) or a String (for symmetric '\
44
+ 'encryption).'
45
+ raise ArgumentError, msg
46
+ end
47
+ end
48
+
49
+ def validate_desc(description)
50
+ Json.load(description)
51
+ description
52
+ rescue Json::ParseError, EncodingError
53
+ msg = 'expected description to be a valid JSON document string'
54
+ raise ArgumentError, msg
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Aws
6
+ module S3
7
+ module EncryptionV2
8
+ # @api private
9
+ module Utils
10
+
11
+ class << self
12
+
13
+ def encrypt_aes_gcm(key, data, auth_data)
14
+ cipher = aes_encryption_cipher(:GCM, key)
15
+ cipher.iv = (iv = cipher.random_iv)
16
+ cipher.auth_data = auth_data
17
+
18
+ iv + cipher.update(data) + cipher.final + cipher.auth_tag
19
+ end
20
+
21
+ def encrypt_rsa(key, data, auth_data)
22
+ # Plaintext must be KeyLengthInBytes (1 Byte) + DataKey + AuthData
23
+ buf = [data.bytesize] + data.unpack('C*') + auth_data.unpack('C*')
24
+ key.public_encrypt(buf.pack('C*'), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
25
+ end
26
+
27
+ def decrypt(key, data)
28
+ begin
29
+ case key
30
+ when OpenSSL::PKey::RSA # asymmetric decryption
31
+ key.private_decrypt(data)
32
+ when String # symmetric Decryption
33
+ cipher = aes_cipher(:decrypt, :ECB, key, nil)
34
+ cipher.update(data) + cipher.final
35
+ end
36
+ rescue OpenSSL::Cipher::CipherError
37
+ msg = 'decryption failed, possible incorrect key'
38
+ raise Errors::DecryptionError, msg
39
+ end
40
+ end
41
+
42
+ def decrypt_aes_gcm(key, data, auth_data)
43
+ # data is iv (12B) + key + tag (16B)
44
+ buf = data.unpack('C*')
45
+ iv = buf[0,12].pack('C*') # iv will always be 12 bytes
46
+ tag = buf[-16, 16].pack('C*') # tag is 16 bytes
47
+ enc_key = buf[12, buf.size - (12+16)].pack('C*')
48
+ cipher = aes_cipher(:decrypt, :GCM, key, iv)
49
+ cipher.auth_tag = tag
50
+ cipher.auth_data = auth_data
51
+ cipher.update(enc_key) + cipher.final
52
+ end
53
+
54
+ # returns the decrypted data + auth_data
55
+ def decrypt_rsa(key, enc_data)
56
+ # Plaintext must be KeyLengthInBytes (1 Byte) + DataKey + AuthData
57
+ buf = key.private_decrypt(enc_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING).unpack('C*')
58
+ key_length = buf[0]
59
+ data = buf[1, key_length].pack('C*')
60
+ auth_data = buf[key_length+1, buf.length - key_length].pack('C*')
61
+ [data, auth_data]
62
+ end
63
+
64
+ # @param [String] block_mode "CBC" or "ECB"
65
+ # @param [OpenSSL::PKey::RSA, String, nil] key
66
+ # @param [String, nil] iv The initialization vector
67
+ def aes_encryption_cipher(block_mode, key = nil, iv = nil)
68
+ aes_cipher(:encrypt, block_mode, key, iv)
69
+ end
70
+
71
+ # @param [String] block_mode "CBC" or "ECB"
72
+ # @param [OpenSSL::PKey::RSA, String, nil] key
73
+ # @param [String, nil] iv The initialization vector
74
+ def aes_decryption_cipher(block_mode, key = nil, iv = nil)
75
+ aes_cipher(:decrypt, block_mode, key, iv)
76
+ end
77
+
78
+ # @param [String] mode "encrypt" or "decrypt"
79
+ # @param [String] block_mode "CBC" or "ECB"
80
+ # @param [OpenSSL::PKey::RSA, String, nil] key
81
+ # @param [String, nil] iv The initialization vector
82
+ def aes_cipher(mode, block_mode, key, iv)
83
+ cipher = key ?
84
+ OpenSSL::Cipher.new("aes-#{cipher_size(key)}-#{block_mode.downcase}") :
85
+ OpenSSL::Cipher.new("aes-256-#{block_mode.downcase}")
86
+ cipher.send(mode) # encrypt or decrypt
87
+ cipher.key = key if key
88
+ cipher.iv = iv if iv
89
+ cipher
90
+ end
91
+
92
+ # @param [String] key
93
+ # @return [Integer]
94
+ # @raise ArgumentError
95
+ def cipher_size(key)
96
+ key.bytesize * 8
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,23 @@
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
18
+ AES_GCM_TAG_LEN_BYTES = 16
19
+ EC_USER_AGENT = 'S3CryptoV2'
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ # WARNING ABOUT GENERATED CODE
4
+ #
5
+ # This file is generated. See the contributing guide for more information:
6
+ # https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
7
+ #
8
+ # WARNING ABOUT GENERATED CODE
9
+
10
+ module Aws::S3
11
+ # Endpoint parameters used to influence endpoints per request.
12
+ #
13
+ # @!attribute bucket
14
+ # The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.
15
+ #
16
+ # @return [String]
17
+ #
18
+ # @!attribute region
19
+ # The AWS region used to dispatch the request.
20
+ #
21
+ # @return [String]
22
+ #
23
+ # @!attribute use_fips
24
+ # When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.
25
+ #
26
+ # @return [Boolean]
27
+ #
28
+ # @!attribute use_dual_stack
29
+ # When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.
30
+ #
31
+ # @return [Boolean]
32
+ #
33
+ # @!attribute endpoint
34
+ # Override the endpoint used to send this request
35
+ #
36
+ # @return [String]
37
+ #
38
+ # @!attribute force_path_style
39
+ # When true, force a path-style endpoint to be used where the bucket name is part of the path.
40
+ #
41
+ # @return [Boolean]
42
+ #
43
+ # @!attribute accelerate
44
+ # When true, use S3 Accelerate. NOTE: Not all regions support S3 accelerate.
45
+ #
46
+ # @return [Boolean]
47
+ #
48
+ # @!attribute use_global_endpoint
49
+ # Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.
50
+ #
51
+ # @return [Boolean]
52
+ #
53
+ # @!attribute use_object_lambda_endpoint
54
+ # Internal parameter to use object lambda endpoint for an operation (eg: WriteGetObjectResponse)
55
+ #
56
+ # @return [Boolean]
57
+ #
58
+ # @!attribute key
59
+ # The S3 Key used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Key.
60
+ #
61
+ # @return [String]
62
+ #
63
+ # @!attribute prefix
64
+ # The S3 Prefix used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Prefix.
65
+ #
66
+ # @return [String]
67
+ #
68
+ # @!attribute copy_source
69
+ # The Copy Source used for Copy Object request. This is an optional parameter that will be set automatically for operations that are scoped to Copy Source.
70
+ #
71
+ # @return [String]
72
+ #
73
+ # @!attribute disable_access_points
74
+ # Internal parameter to disable Access Point Buckets
75
+ #
76
+ # @return [Boolean]
77
+ #
78
+ # @!attribute disable_multi_region_access_points
79
+ # Whether multi-region access points (MRAP) should be disabled.
80
+ #
81
+ # @return [Boolean]
82
+ #
83
+ # @!attribute use_arn_region
84
+ # When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN&#39;s region when constructing the endpoint instead of the client&#39;s configured region.
85
+ #
86
+ # @return [Boolean]
87
+ #
88
+ # @!attribute use_s3_express_control_endpoint
89
+ # Internal parameter to indicate whether S3Express operation should use control plane, (ex. CreateBucket)
90
+ #
91
+ # @return [Boolean]
92
+ #
93
+ # @!attribute disable_s3_express_session_auth
94
+ # Parameter to indicate whether S3Express session auth should be disabled
95
+ #
96
+ # @return [Boolean]
97
+ #
98
+ EndpointParameters = Struct.new(
99
+ :bucket,
100
+ :region,
101
+ :use_fips,
102
+ :use_dual_stack,
103
+ :endpoint,
104
+ :force_path_style,
105
+ :accelerate,
106
+ :use_global_endpoint,
107
+ :use_object_lambda_endpoint,
108
+ :key,
109
+ :prefix,
110
+ :copy_source,
111
+ :disable_access_points,
112
+ :disable_multi_region_access_points,
113
+ :use_arn_region,
114
+ :use_s3_express_control_endpoint,
115
+ :disable_s3_express_session_auth,
116
+ ) do
117
+ include Aws::Structure
118
+
119
+ # @api private
120
+ class << self
121
+ PARAM_MAP = {
122
+ 'Bucket' => :bucket,
123
+ 'Region' => :region,
124
+ 'UseFIPS' => :use_fips,
125
+ 'UseDualStack' => :use_dual_stack,
126
+ 'Endpoint' => :endpoint,
127
+ 'ForcePathStyle' => :force_path_style,
128
+ 'Accelerate' => :accelerate,
129
+ 'UseGlobalEndpoint' => :use_global_endpoint,
130
+ 'UseObjectLambdaEndpoint' => :use_object_lambda_endpoint,
131
+ 'Key' => :key,
132
+ 'Prefix' => :prefix,
133
+ 'CopySource' => :copy_source,
134
+ 'DisableAccessPoints' => :disable_access_points,
135
+ 'DisableMultiRegionAccessPoints' => :disable_multi_region_access_points,
136
+ 'UseArnRegion' => :use_arn_region,
137
+ 'UseS3ExpressControlEndpoint' => :use_s3_express_control_endpoint,
138
+ 'DisableS3ExpressSessionAuth' => :disable_s3_express_session_auth,
139
+ }.freeze
140
+ end
141
+
142
+ def initialize(options = {})
143
+ self[:bucket] = options[:bucket]
144
+ self[:region] = options[:region]
145
+ self[:use_fips] = options[:use_fips]
146
+ self[:use_fips] = false if self[:use_fips].nil?
147
+ self[:use_dual_stack] = options[:use_dual_stack]
148
+ self[:use_dual_stack] = false if self[:use_dual_stack].nil?
149
+ self[:endpoint] = options[:endpoint]
150
+ self[:force_path_style] = options[:force_path_style]
151
+ self[:force_path_style] = false if self[:force_path_style].nil?
152
+ self[:accelerate] = options[:accelerate]
153
+ self[:accelerate] = false if self[:accelerate].nil?
154
+ self[:use_global_endpoint] = options[:use_global_endpoint]
155
+ self[:use_global_endpoint] = false if self[:use_global_endpoint].nil?
156
+ self[:use_object_lambda_endpoint] = options[:use_object_lambda_endpoint]
157
+ self[:key] = options[:key]
158
+ self[:prefix] = options[:prefix]
159
+ self[:copy_source] = options[:copy_source]
160
+ self[:disable_access_points] = options[:disable_access_points]
161
+ self[:disable_multi_region_access_points] = options[:disable_multi_region_access_points]
162
+ self[:disable_multi_region_access_points] = false if self[:disable_multi_region_access_points].nil?
163
+ self[:use_arn_region] = options[:use_arn_region]
164
+ self[:use_s3_express_control_endpoint] = options[:use_s3_express_control_endpoint]
165
+ self[:disable_s3_express_session_auth] = options[:disable_s3_express_session_auth]
166
+ end
167
+
168
+ def self.create(config, options={})
169
+ new({
170
+ region: config.region,
171
+ use_fips: config.use_fips_endpoint,
172
+ endpoint: (config.endpoint.to_s unless config.regional_endpoint),
173
+ force_path_style: config.force_path_style,
174
+ use_global_endpoint: config.s3_us_east_1_regional_endpoint == 'legacy',
175
+ disable_multi_region_access_points: config.s3_disable_multiregion_access_points,
176
+ use_arn_region: config.s3_use_arn_region,
177
+ disable_s3_express_session_auth: config.disable_s3_express_session_auth,
178
+ }.merge(options))
179
+ end
180
+ end
181
+ end