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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfdbbed3a219f8690462fbca974111e863bbb4b3a3677648cf77dec94af963e9
4
- data.tar.gz: 285b62f651038d1bf38e9fc156ec48d78b6aedd21f869455cfdb942aad7d817c
3
+ metadata.gz: 42108655e1496a1ce6df9db9b19ea1733e1c2d3710b70d8a27bb6c8b562fb307
4
+ data.tar.gz: 2b759d809937dc65075c1e193ce71972de3ce592ac7d6d01d782e1eb401e6b1e
5
5
  SHA512:
6
- metadata.gz: aaed81549dabc75fd9415706924178884c1a9b2d3cc0c8325be4540c28301dd45d6d376ba6fc75bba28f705764af6916b984818d5c2df0d360884db429578b31
7
- data.tar.gz: 20bc2cf996bcc241fefe8beba3bb6e30d7f5678e764c23c16a05f00e91c47be098290d85b3fe48a87bdb1edf27b35ab5e632545a210e2c81b801aed682e01641
6
+ metadata.gz: d0342f210f9a406650291b5cc4a27315d39c142d042609362bc16b3ef20eafa2915243a7f72dcd3a84a81bcdc0e1209f76b440cddf3acd88dc62ce66cc6f67fb
7
+ data.tar.gz: e3090d0ea9210596cb6eaa93b95ad43fb8784de81b249ebe8e8db33fb97763e281192f593a0f07bf224fa820ec5d0ea5f225368d9e396982f10a9c3e8a528f91
@@ -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:
@@ -66,6 +68,6 @@ require_relative 'aws-sdk-s3/event_streams'
66
68
  # @service
67
69
  module Aws::S3
68
70
 
69
- GEM_VERSION = '1.68.1'
71
+ GEM_VERSION = '1.69.0'
70
72
 
71
73
  end
@@ -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
  # 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
  # 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
  # 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 'thread'
2
4
 
3
5
  module Aws
@@ -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
  # 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
  # WARNING ABOUT GENERATED CODE
2
4
  #
3
5
  # This file is generated. See the contributing guide for more information:
@@ -11668,7 +11670,7 @@ module Aws::S3
11668
11670
  params: params,
11669
11671
  config: config)
11670
11672
  context[:gem_name] = 'aws-sdk-s3'
11671
- context[:gem_version] = '1.68.1'
11673
+ context[:gem_version] = '1.69.0'
11672
11674
  Seahorse::Client::Request.new(handlers, context)
11673
11675
  end
11674
11676
 
@@ -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,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # utility classes
2
4
  require 'aws-sdk-s3/bucket_region_cache'
3
5
  require 'aws-sdk-s3/encryption'
6
+ require 'aws-sdk-s3/encryption_v2'
4
7
  require 'aws-sdk-s3/file_part'
5
8
  require 'aws-sdk-s3/file_uploader'
6
9
  require 'aws-sdk-s3/file_downloader'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  class MultipartUpload
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  class Object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  class ObjectSummary
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Aws::S3::Types::ListObjectVersionsOutput
2
4
 
3
5
  # TODO : Remove this customization once the resource code
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aws-sdk-s3/encryption/client'
2
4
  require 'aws-sdk-s3/encryption/decrypt_handler'
3
5
  require 'aws-sdk-s3/encryption/default_cipher_provider'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Aws
@@ -30,6 +32,7 @@ module Aws
30
32
 
31
33
  def call(context)
32
34
  attach_http_event_listeners(context)
35
+ apply_cse_user_agent(context)
33
36
  @handler.call(context)
34
37
  end
35
38
 
@@ -173,6 +176,14 @@ module Aws
173
176
  context.http_response.headers['x-amz-meta-x-amz-tag-len']
174
177
  end
175
178
 
179
+ def apply_cse_user_agent(context)
180
+ if context.config.user_agent_suffix.nil?
181
+ context.config.user_agent_suffix = 'CSE_V1'
182
+ elsif !context.config.user_agent_suffix.include? 'CSE_V1'
183
+ context.config.user_agent_suffix += ' CSE_V1'
184
+ end
185
+ end
186
+
176
187
  end
177
188
  end
178
189
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Encryption
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Aws
@@ -10,6 +12,7 @@ module Aws
10
12
  envelope, cipher = context[:encryption][:cipher_provider].encryption_cipher
11
13
  apply_encryption_envelope(context, envelope, cipher)
12
14
  apply_encryption_cipher(context, cipher)
15
+ apply_cse_user_agent(context)
13
16
  @handler.call(context)
14
17
  end
15
18
 
@@ -44,6 +47,14 @@ module Aws
44
47
  end
45
48
  end
46
49
 
50
+ def apply_cse_user_agent(context)
51
+ if context.config.user_agent_suffix.nil?
52
+ context.config.user_agent_suffix = 'CSE_V1'
53
+ elsif !context.config.user_agent_suffix.include? 'CSE_V1'
54
+ context.config.user_agent_suffix += ' CSE_V1'
55
+ end
56
+ end
57
+
47
58
  end
48
59
  end
49
60
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Encryption
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Encryption
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Encryption
@@ -8,7 +10,8 @@ module Aws
8
10
  # @param [IO#write] io An IO-like object that responds to `#write`.
9
11
  def initialize(cipher, io)
10
12
  @cipher = cipher.clone
11
- @io = io
13
+ # Ensure that IO is reset between retries
14
+ @io = io.tap { |io| io.truncate(0) if io.respond_to?(:truncate) }
12
15
  end
13
16
 
14
17
  # @return [#write]
@@ -23,6 +26,10 @@ module Aws
23
26
  @io.write(@cipher.final)
24
27
  end
25
28
 
29
+ def size
30
+ @io.size
31
+ end
32
+
26
33
  end
27
34
  end
28
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringio'
2
4
  require 'tempfile'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Encryption
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Aws
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
 
3
5
  module Aws
@@ -0,0 +1,378 @@
1
+ require 'forwardable'
2
+
3
+ module Aws
4
+ module S3
5
+
6
+ # Provides an encryption client that encrypts and decrypts data client-side,
7
+ # storing the encrypted data in Amazon S3. The EncryptionV2::Client
8
+ # provides improved security over the Encryption::Client by using more
9
+ # modern and secure algorithms. The EncryptionV2::Client maintains
10
+ # backwards compatibility: Using the EncryptionV2::Client you can decrypt
11
+ # objects encrypted with the Encryption::Client. However, objects you
12
+ # encrypt using the EncryptionV2::Client cannot be decrypted using the
13
+ # Encryption::Client.
14
+ #
15
+ # This client uses a process called "envelope encryption". Your private
16
+ # encryption keys and your data's plain-text are **never** sent to
17
+ # Amazon S3. **If you lose you encryption keys, you will not be able to
18
+ # decrypt your data.**
19
+ #
20
+ # ## Envelope Encryption Overview
21
+ #
22
+ # The goal of envelope encryption is to combine the performance of
23
+ # fast symmetric encryption while maintaining the secure key management
24
+ # that asymmetric keys provide.
25
+ #
26
+ # A one-time-use symmetric key (envelope key) is generated client-side.
27
+ # This is used to encrypt the data client-side. This key is then
28
+ # encrypted by your master key and stored alongside your data in Amazon
29
+ # S3.
30
+ #
31
+ # When accessing your encrypted data with the encryption client,
32
+ # the encrypted envelope key is retrieved and decrypted client-side
33
+ # with your master key. The envelope key is then used to decrypt the
34
+ # data client-side.
35
+ #
36
+ # One of the benefits of envelope encryption is that if your master key
37
+ # is compromised, you have the option of just re-encrypting the stored
38
+ # envelope symmetric keys, instead of re-encrypting all of the
39
+ # data in your account.
40
+ #
41
+ # ## Basic Usage
42
+ #
43
+ # The encryption client requires an {Aws::S3::Client}. If you do not
44
+ # provide a `:client`, then a client will be constructed for you.
45
+ #
46
+ # require 'openssl'
47
+ # key = OpenSSL::PKey::RSA.new(1024)
48
+ #
49
+ # # encryption client
50
+ # s3 = Aws::S3::EncryptionV2::Client.new(encryption_key: key)
51
+ #
52
+ # # round-trip an object, encrypted/decrypted locally
53
+ # s3.put_object(bucket:'aws-sdk', key:'secret', body:'handshake')
54
+ # s3.get_object(bucket:'aws-sdk', key:'secret').body.read
55
+ # #=> 'handshake'
56
+ #
57
+ # # reading encrypted object without the encryption client
58
+ # # results in the getting the cipher text
59
+ # Aws::S3::Client.new.get_object(bucket:'aws-sdk', key:'secret').body.read
60
+ # #=> "... cipher text ..."
61
+ #
62
+ # ## Keys
63
+ #
64
+ # For client-side encryption to work, you must provide one of the following:
65
+ #
66
+ # * An encryption key
67
+ # * A {KeyProvider}
68
+ # * A KMS encryption key id
69
+ #
70
+ # ### An Encryption Key
71
+ #
72
+ # You can pass a single encryption key. This is used as a master key
73
+ # encrypting and decrypting all object keys.
74
+ #
75
+ # key = OpenSSL::Cipher.new("AES-256-ECB").random_key # symmetric key
76
+ # key = OpenSSL::PKey::RSA.new(1024) # asymmetric key pair
77
+ #
78
+ # s3 = Aws::S3::EncryptionV2::Client.new(encryption_key: key)
79
+ #
80
+ # ### Key Provider
81
+ #
82
+ # Alternatively, you can use a {KeyProvider}. A key provider makes
83
+ # it easy to work with multiple keys and simplifies key rotation.
84
+ #
85
+ # ### KMS Encryption Key Id
86
+ #
87
+ # If you pass the id to an AWS Key Management Service (KMS) key,
88
+ # then KMS will be used to generate, encrypt and decrypt object keys.
89
+ #
90
+ # # keep track of the kms key id
91
+ # kms = Aws::KMS::Client.new
92
+ # key_id = kms.create_key.key_metadata.key_id
93
+ #
94
+ # Aws::S3::EncryptionV2::Client.new(
95
+ # kms_key_id: key_id,
96
+ # kms_client: kms,
97
+ # )
98
+ #
99
+ # ## Custom Key Providers
100
+ #
101
+ # A {KeyProvider} is any object that responds to:
102
+ #
103
+ # * `#encryption_materials`
104
+ # * `#key_for(materials_description)`
105
+ #
106
+ # Here is a trivial implementation of an in-memory key provider.
107
+ # This is provided as a demonstration of the key provider interface,
108
+ # and should not be used in production:
109
+ #
110
+ # class KeyProvider
111
+ #
112
+ # def initialize(default_key_name, keys)
113
+ # @keys = keys
114
+ # @encryption_materials = Aws::S3::EncryptionV2::Materials.new(
115
+ # key: @keys[default_key_name],
116
+ # description: JSON.dump(key: default_key_name),
117
+ # )
118
+ # end
119
+ #
120
+ # attr_reader :encryption_materials
121
+ #
122
+ # def key_for(matdesc)
123
+ # key_name = JSON.load(matdesc)['key']
124
+ # if key = @keys[key_name]
125
+ # key
126
+ # else
127
+ # raise "encryption key not found for: #{matdesc.inspect}"
128
+ # end
129
+ # end
130
+ # end
131
+ #
132
+ # Given the above key provider, you can create an encryption client that
133
+ # chooses the key to use based on the materials description stored with
134
+ # the encrypted object. This makes it possible to use multiple keys
135
+ # and simplifies key rotation.
136
+ #
137
+ # # uses "new-key" for encrypting objects, uses either for decrypting
138
+ # keys = KeyProvider.new('new-key', {
139
+ # "old-key" => Base64.decode64("kM5UVbhE/4rtMZJfsadYEdm2vaKFsmV2f5+URSeUCV4="),
140
+ # "new-key" => Base64.decode64("w1WLio3agRWRTSJK/Ouh8NHoqRQ6fn5WbSXDTHjXMSo="),
141
+ # }),
142
+ #
143
+ # # chooses the key based on the materials description stored
144
+ # # with the encrypted object
145
+ # s3 = Aws::S3::EncryptionV2::Client.new(key_provider: keys)
146
+ #
147
+ # ## Materials Description
148
+ #
149
+ # A materials description is JSON document string that is stored
150
+ # in the metadata (or instruction file) of an encrypted object.
151
+ # The {DefaultKeyProvider} uses the empty JSON document `"{}"`.
152
+ #
153
+ # When building a key provider, you are free to store whatever
154
+ # information you need to identify the master key that was used
155
+ # to encrypt the object.
156
+ #
157
+ # ## Envelope Location
158
+ #
159
+ # By default, the encryption client store the encryption envelope
160
+ # with the object, as metadata. You can choose to have the envelope
161
+ # stored in a separate "instruction file". An instruction file
162
+ # is an object, with the key of the encrypted object, suffixed with
163
+ # `".instruction"`.
164
+ #
165
+ # Specify the `:envelope_location` option as `:instruction_file` to
166
+ # use an instruction file for storing the envelope.
167
+ #
168
+ # # default behavior
169
+ # s3 = Aws::S3::EncryptionV2::Client.new(
170
+ # key_provider: ...,
171
+ # envelope_location: :metadata,
172
+ # )
173
+ #
174
+ # # store envelope in a separate object
175
+ # s3 = Aws::S3::EncryptionV2::Client.new(
176
+ # key_provider: ...,
177
+ # envelope_location: :instruction_file,
178
+ # instruction_file_suffix: '.instruction' # default
179
+ # )
180
+ #
181
+ # When using an instruction file, multiple requests are made when
182
+ # putting and getting the object. **This may cause issues if you are
183
+ # issuing concurrent PUT and GET requests to an encrypted object.**
184
+ #
185
+ module EncryptionV2
186
+ class Client
187
+
188
+ extend Deprecations
189
+ extend Forwardable
190
+ def_delegators :@client, :config, :delete_object, :head_object, :build_request
191
+
192
+ # Creates a new encryption client. You must provide one of the following
193
+ # options:
194
+ #
195
+ # * `:encryption_key`
196
+ # * `:kms_key_id`
197
+ # * `:key_provider`
198
+ #
199
+ # You may also pass any other options accepted by `Client#initialize`.
200
+ #
201
+ # @option options [S3::Client] :client A basic S3 client that is used
202
+ # to make api calls. If a `:client` is not provided, a new {S3::Client}
203
+ # will be constructed.
204
+ #
205
+ # @option options [OpenSSL::PKey::RSA, String] :encryption_key The master
206
+ # key to use for encrypting/decrypting all objects.
207
+ #
208
+ # @option options [String] :kms_key_id When you provide a `:kms_key_id`,
209
+ # then AWS Key Management Service (KMS) will be used to manage the
210
+ # object encryption keys. By default a {KMS::Client} will be
211
+ # constructed for KMS API calls. Alternatively, you can provide
212
+ # your own via `:kms_client`.
213
+ #
214
+ # @option options [#key_for] :key_provider Any object that responds
215
+ # to `#key_for`. This method should accept a materials description
216
+ # JSON document string and return return an encryption key.
217
+ #
218
+ # @option options [Symbol] :envelope_location (:metadata) Where to
219
+ # store the envelope encryption keys. By default, the envelope is
220
+ # stored with the encrypted object. If you pass `:instruction_file`,
221
+ # then the envelope is stored in a separate object in Amazon S3.
222
+ #
223
+ # @option options [String] :instruction_file_suffix ('.instruction')
224
+ # When `:envelope_location` is `:instruction_file` then the
225
+ # instruction file uses the object key with this suffix appended.
226
+ #
227
+ # @option options [KMS::Client] :kms_client A default {KMS::Client}
228
+ # is constructed when using KMS to manage encryption keys.
229
+ #
230
+ def initialize(options = {})
231
+ @client = extract_client(options)
232
+ @cipher_provider = cipher_provider(options)
233
+ @envelope_location = extract_location(options)
234
+ @instruction_file_suffix = extract_suffix(options)
235
+ end
236
+
237
+ # @return [S3::Client]
238
+ attr_reader :client
239
+
240
+ # @return [KeyProvider, nil] Returns `nil` if you are using
241
+ # AWS Key Management Service (KMS).
242
+ attr_reader :key_provider
243
+
244
+ # @return [Symbol<:metadata, :instruction_file>]
245
+ attr_reader :envelope_location
246
+
247
+ # @return [String] When {#envelope_location} is `:instruction_file`,
248
+ # the envelope is stored in the object with the object key suffixed
249
+ # by this string.
250
+ attr_reader :instruction_file_suffix
251
+
252
+ # Uploads an object to Amazon S3, encrypting data client-side.
253
+ # See {S3::Client#put_object} for documentation on accepted
254
+ # request parameters.
255
+ # @option (see S3::Client#put_object)
256
+ # @return (see S3::Client#put_object)
257
+ # @see S3::Client#put_object
258
+ def put_object(params = {})
259
+ req = @client.build_request(:put_object, params)
260
+ req.handlers.add(EncryptHandler, priority: 95)
261
+ req.context[:encryption] = {
262
+ cipher_provider: @cipher_provider,
263
+ envelope_location: @envelope_location,
264
+ instruction_file_suffix: @instruction_file_suffix,
265
+ }
266
+ req.send_request
267
+ end
268
+
269
+ # Gets an object from Amazon S3, decrypting data locally.
270
+ # See {S3::Client#get_object} for documentation on accepted
271
+ # request parameters.
272
+ # @option params [String] :instruction_file_suffix The suffix
273
+ # used to find the instruction file containing the encryption
274
+ # envelope. You should not set this option when the envelope
275
+ # is stored in the object metadata. Defaults to
276
+ # {#instruction_file_suffix}.
277
+ # @option params [String] :instruction_file_suffix
278
+ # @option (see S3::Client#get_object)
279
+ # @return (see S3::Client#get_object)
280
+ # @see S3::Client#get_object
281
+ # @note The `:range` request parameter is not yet supported.
282
+ def get_object(params = {}, &block)
283
+ if params[:range]
284
+ raise NotImplementedError, '#get_object with :range not supported'
285
+ end
286
+ envelope_location, instruction_file_suffix = envelope_options(params)
287
+ req = @client.build_request(:get_object, params)
288
+ req.handlers.add(DecryptHandler)
289
+ req.context[:encryption] = {
290
+ cipher_provider: @cipher_provider,
291
+ envelope_location: envelope_location,
292
+ instruction_file_suffix: instruction_file_suffix,
293
+ }
294
+ req.send_request(target: block)
295
+ end
296
+
297
+ private
298
+
299
+ def extract_client(options)
300
+ options[:client] || begin
301
+ options = options.dup
302
+ options.delete(:kms_key_id)
303
+ options.delete(:kms_client)
304
+ options.delete(:key_provider)
305
+ options.delete(:encryption_key)
306
+ options.delete(:envelope_location)
307
+ options.delete(:instruction_file_suffix)
308
+ S3::Client.new(options)
309
+ end
310
+ end
311
+
312
+ def kms_client(options)
313
+ options[:kms_client] || begin
314
+ KMS::Client.new(
315
+ region: @client.config.region,
316
+ credentials: @client.config.credentials,
317
+ )
318
+ end
319
+ end
320
+
321
+ def cipher_provider(options)
322
+ if options[:kms_key_id]
323
+ KmsCipherProvider.new(
324
+ kms_key_id: options[:kms_key_id],
325
+ kms_client: kms_client(options),
326
+ )
327
+ else
328
+ @key_provider = extract_key_provider(options)
329
+ DefaultCipherProvider.new(key_provider: @key_provider)
330
+ end
331
+ end
332
+
333
+ def extract_key_provider(options)
334
+ if options[:key_provider]
335
+ options[:key_provider]
336
+ elsif options[:encryption_key]
337
+ DefaultKeyProvider.new(options)
338
+ else
339
+ msg = 'you must pass a :kms_key_id, :key_provider, or :encryption_key'
340
+ raise ArgumentError, msg
341
+ end
342
+ end
343
+
344
+ def envelope_options(params)
345
+ location = params.delete(:envelope_location) || @envelope_location
346
+ suffix = params.delete(:instruction_file_suffix)
347
+ if suffix
348
+ [:instruction_file, suffix]
349
+ else
350
+ [location, @instruction_file_suffix]
351
+ end
352
+ end
353
+
354
+ def extract_location(options)
355
+ location = options[:envelope_location] || :metadata
356
+ if [:metadata, :instruction_file].include?(location)
357
+ location
358
+ else
359
+ msg = ':envelope_location must be :metadata or :instruction_file '\
360
+ "got #{location.inspect}"
361
+ raise ArgumentError, msg
362
+ end
363
+ end
364
+
365
+ def extract_suffix(options)
366
+ suffix = options[:instruction_file_suffix] || '.instruction'
367
+ if suffix.is_a? String
368
+ suffix
369
+ else
370
+ msg = ':instruction_file_suffix must be a String'
371
+ raise ArgumentError, msg
372
+ end
373
+ end
374
+
375
+ end
376
+ end
377
+ end
378
+ end