aws-sdk-s3 1.48.0 → 1.169.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1270 -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 +959 -106
  8. data/lib/aws-sdk-s3/bucket_acl.rb +64 -18
  9. data/lib/aws-sdk-s3/bucket_cors.rb +79 -18
  10. data/lib/aws-sdk-s3/bucket_lifecycle.rb +66 -20
  11. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +106 -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 +107 -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 +13765 -1019
  21. data/lib/aws-sdk-s3/client_api.rb +1137 -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 +592 -0
  61. data/lib/aws-sdk-s3/endpoints.rb +1392 -0
  62. data/lib/aws-sdk-s3/errors.rb +126 -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 +176 -44
  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 +82 -23
  71. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +61 -21
  72. data/lib/aws-sdk-s3/multipart_upload.rb +265 -32
  73. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  74. data/lib/aws-sdk-s3/multipart_upload_part.rb +367 -45
  75. data/lib/aws-sdk-s3/object.rb +2475 -228
  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 +2075 -203
  80. data/lib/aws-sdk-s3/object_version.rb +492 -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/dualstack.rb +7 -50
  87. data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
  88. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +5 -4
  89. data/lib/aws-sdk-s3/plugins/express_session_auth.rb +97 -0
  90. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  91. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +60 -15
  92. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +44 -0
  93. data/lib/aws-sdk-s3/plugins/location_constraint.rb +5 -1
  94. data/lib/aws-sdk-s3/plugins/md5s.rb +35 -30
  95. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  96. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  97. data/lib/aws-sdk-s3/plugins/s3_signer.rb +63 -94
  98. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  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 +138 -59
  104. data/lib/aws-sdk-s3/resource.rb +155 -17
  105. data/lib/aws-sdk-s3/types.rb +12229 -4377
  106. data/lib/aws-sdk-s3/waiters.rb +67 -1
  107. data/lib/aws-sdk-s3.rb +46 -32
  108. data/sig/bucket.rbs +216 -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 +2406 -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 +34 -0
  125. data/sig/multipart_upload.rbs +111 -0
  126. data/sig/multipart_upload_part.rbs +105 -0
  127. data/sig/object.rbs +443 -0
  128. data/sig/object_acl.rbs +86 -0
  129. data/sig/object_summary.rbs +335 -0
  130. data/sig/object_version.rbs +137 -0
  131. data/sig/resource.rbs +132 -0
  132. data/sig/types.rbs +2596 -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