aws-sdk-s3 1.68.1 → 1.69.0

Sign up to get free protection for your applications and to get access to all the features.
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 +2 -0
  4. data/lib/aws-sdk-s3/bucket_acl.rb +2 -0
  5. data/lib/aws-sdk-s3/bucket_cors.rb +2 -0
  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 +2 -0
  16. data/lib/aws-sdk-s3/client.rb +3 -1
  17. data/lib/aws-sdk-s3/client_api.rb +2 -0
  18. data/lib/aws-sdk-s3/customizations.rb +3 -0
  19. data/lib/aws-sdk-s3/customizations/bucket.rb +2 -0
  20. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  21. data/lib/aws-sdk-s3/customizations/object.rb +2 -0
  22. data/lib/aws-sdk-s3/customizations/object_summary.rb +2 -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 +2 -0
  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 +2 -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 +2 -0
  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 +2 -0
  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 +2 -0
  68. data/lib/aws-sdk-s3/object_version.rb +2 -0
  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 +2 -0
  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 +2 -0
  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 +2 -0
  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 +2 -0
  88. data/lib/aws-sdk-s3/types.rb +2 -0
  89. data/lib/aws-sdk-s3/waiters.rb +2 -0
  90. metadata +16 -2
@@ -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:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
  require 'thread'
3
5
  require 'set'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
  require 'time'
3
5
  require 'openssl'