aws-sdk-s3 1.147.0 → 1.149.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a53a99ccca2522053de21bfdf31e17a700464dcc70688283d438b987b1e8098d
4
- data.tar.gz: 2edaadc220c24d5d3493841421b9760c2202e7b14aa78e58eb6bb33554f46650
3
+ metadata.gz: d4d91f16763c42e349f2e6d50ff4f37926096c5148ae5f78b953685e4d2f171e
4
+ data.tar.gz: 2e72de55c5c10a86437e89200db3b357bb89f083ca5b1c044c20ed90143b66b4
5
5
  SHA512:
6
- metadata.gz: 822936b8f7a5f6b51baa737b7628ef9e6c584bafca53d648c99684cb6db92b3a6fea98a91ddcce1b2479e7050cccb59045f062cc73f9d889911013684ba7b3df
7
- data.tar.gz: 13107a5c2aa6fb081e943340433a72dabad53ee6800e841eff965662c135aac1307664ea855def95c610421886314148067972e6dd78f1f0dc9510671ccfa331
6
+ metadata.gz: '078c6651b2bc5d4c4cf9abb678303f3dc41250eb24ee66fcbbb22d9c96064dc8dbade173862964021948234fff6e9d38b4a9eb255949891fc047a0b06ac785f6'
7
+ data.tar.gz: d17a3204313a0977ee8f108c057fefbcbca80eb48e54e146274be01b9f2d9d4c33502cf2474c49fffe560d4a134d8e985a0f8db7a3f83ff533b898e725236473
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  Unreleased Changes
2
2
  ------------------
3
3
 
4
+ 1.149.0 (2024-04-30)
5
+ ------------------
6
+
7
+ * Feature - Support S3 Access Grants authentication. Access Grants can be enabled with the `access_grants` option, and custom options can be passed into the `access_grants_credentials_provider` option. This feature requires `aws-sdk-s3control` to be installed.
8
+
9
+ * Feature - Add RBS signatures for customizations of S3.
10
+
11
+ 1.148.0 (2024-04-25)
12
+ ------------------
13
+
14
+ * Feature - Code Generated Changes, see `./build_tools` or `aws-sdk-core`'s CHANGELOG.md for details.
15
+
4
16
  1.147.0 (2024-04-16)
5
17
  ------------------
6
18
 
@@ -33,7 +45,6 @@ Unreleased Changes
33
45
 
34
46
  * Issue - Include original part errors in message when aborting multipart upload fails (#2990).
35
47
 
36
-
37
48
  1.143.0 (2024-01-26)
38
49
  ------------------
39
50
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.147.0
1
+ 1.149.0
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module Aws
6
+ module S3
7
+ # @api private
8
+ class AccessGrantsCredentials
9
+ include CredentialProvider
10
+ include RefreshingCredentials
11
+
12
+ def initialize(options = {})
13
+ @client = options[:client]
14
+ @get_data_access_params = {}
15
+ options.each_pair do |key, value|
16
+ if self.class.get_data_access_options.include?(key)
17
+ @get_data_access_params[key] = value
18
+ end
19
+ end
20
+ @async_refresh = true
21
+ super
22
+ end
23
+
24
+ # @return [S3Control::Client]
25
+ attr_reader :client
26
+
27
+ # @return [String]
28
+ attr_reader :matched_grant_target
29
+
30
+ private
31
+
32
+ def refresh
33
+ c = @client.get_data_access(@get_data_access_params)
34
+ credentials = c.credentials
35
+ @matched_grant_target = c.matched_grant_target
36
+ @credentials = Credentials.new(
37
+ credentials.access_key_id,
38
+ credentials.secret_access_key,
39
+ credentials.session_token
40
+ )
41
+ @expiration = credentials.expiration
42
+ end
43
+
44
+ class << self
45
+
46
+ # @api private
47
+ def get_data_access_options
48
+ @gdao ||= begin
49
+ input = Aws::S3Control::Client.api.operation(:get_data_access).input
50
+ Set.new(input.shape.member_names)
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,241 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ # @api private
6
+ def self.access_grants_credentials_cache
7
+ @access_grants_credentials_cache ||= LRUCache.new(max_entries: 100)
8
+ end
9
+
10
+ # @api private
11
+ def self.access_grants_account_id_cache
12
+ @access_grants_account_id_cache ||= LRUCache.new(
13
+ max_entries: 100,
14
+ expiration: 60 * 10
15
+ )
16
+ end
17
+
18
+ # Returns Credentials class for S3 Access Grants. Accepts GetDataAccess
19
+ # params and other configuration as options. See
20
+ # {Aws::S3Control::Client#get_data_access} for details.
21
+ class AccessGrantsCredentialsProvider
22
+ # @param [Hash] options
23
+ # @option options [Hash] :s3_control_client_options The S3 Control
24
+ # client options used to create regional S3 Control clients to
25
+ # create the session. Region will be set to the region of the
26
+ # bucket.
27
+ # @option options [Aws::STS::Client] :sts_client The STS client used for
28
+ # fetching the Account ID for the credentials if credentials do not
29
+ # include an Account ID.
30
+ # @option options [Aws::S3::Client] :s3_client The S3 client used for
31
+ # fetching the location of the bucket so that a regional S3 Control
32
+ # client can be created. Defaults to the S3 client from the access
33
+ # grants plugin.
34
+ # @option options [String] :privilege ('Default') The privilege to use
35
+ # when requesting credentials. (see: {Aws::S3Control::Client#get_data_access})
36
+ # @option options [Boolean] :fallback (false) When true, if access is
37
+ # denied, the provider will fall back to the configured credentials.
38
+ # @option options [Boolean] :caching (true) When true, credentials and
39
+ # bucket account ids will be cached.
40
+ # @option options [Callable] :before_refresh Proc called before
41
+ # credentials are refreshed.
42
+ def initialize(options = {})
43
+ @s3_control_options = options.delete(:s3_control_client_options) || {}
44
+ @s3_client = options.delete(:s3_client)
45
+ @sts_client = options.delete(:sts_client)
46
+ @fallback = options.delete(:fallback) || false
47
+ @caching = options.delete(:caching) != false
48
+ @s3_control_clients = {}
49
+ @bucket_region_cache = Aws::S3.bucket_region_cache
50
+ return unless @caching
51
+
52
+ @credentials_cache = Aws::S3.access_grants_credentials_cache
53
+ @account_id_cache = Aws::S3.access_grants_account_id_cache
54
+ end
55
+
56
+ def access_grants_credentials_for(options = {})
57
+ target = target_prefix(
58
+ options[:bucket],
59
+ options[:key],
60
+ options[:prefix]
61
+ )
62
+ credentials = s3_client.config.credentials.credentials # resolves
63
+
64
+ if @caching
65
+ cached_credentials_for(target, options[:permission], credentials)
66
+ else
67
+ new_credentials_for(target, options[:permission], credentials)
68
+ end
69
+ rescue Aws::S3Control::Errors::AccessDenied
70
+ raise unless @fallback
71
+
72
+ warn 'Access denied for S3 Access Grants. Falling back to ' \
73
+ 'configured credentials.'
74
+ s3_client.config.credentials
75
+ end
76
+
77
+ attr_accessor :s3_client
78
+
79
+ private
80
+
81
+ def s3_control_client(bucket_region)
82
+ @s3_control_clients[bucket_region] ||= begin
83
+ credentials = s3_client.config.credentials
84
+ config = { credentials: credentials }.merge(@s3_control_options)
85
+ Aws::S3Control::Client.new(config.merge(
86
+ region: bucket_region,
87
+ use_fips_endpoint: s3_client.config.use_fips_endpoint,
88
+ use_dualstack_endpoint: s3_client.config.use_dualstack_endpoint
89
+ ))
90
+ end
91
+ end
92
+
93
+ def cached_credentials_for(target, permission, credentials)
94
+ cached_creds = broad_search_credentials_cache_prefix(target, permission, credentials)
95
+ return cached_creds if cached_creds
96
+
97
+ if %w[READ WRITE].include?(permission)
98
+ cached_creds = broad_search_credentials_cache_prefix(target, 'READWRITE', credentials)
99
+ return cached_creds if cached_creds
100
+ end
101
+
102
+ cached_creds = broad_search_credentials_cache_characters(target, permission, credentials)
103
+ return cached_creds if cached_creds
104
+
105
+ if %w[READ WRITE].include?(permission)
106
+ cached_creds = broad_search_credentials_cache_characters(target, 'READWRITE', credentials)
107
+ return cached_creds if cached_creds
108
+ end
109
+
110
+ creds = new_credentials_for(target, permission, credentials)
111
+ if creds.matched_grant_target.end_with?('*')
112
+ # remove /* from the end of the target
113
+ key = credentials_cache_key(creds.matched_grant_target[0...-2], permission, credentials)
114
+ @credentials_cache[key] = creds
115
+ end
116
+
117
+ creds
118
+ end
119
+
120
+ def broad_search_credentials_cache_prefix(target, permission, credentials)
121
+ prefix = target
122
+ while prefix != 's3:'
123
+ key = credentials_cache_key(prefix, permission, credentials)
124
+ return @credentials_cache[key] if @credentials_cache.key?(key)
125
+
126
+ prefix = prefix.split('/', -1)[0..-2].join('/')
127
+ end
128
+ nil
129
+ end
130
+
131
+ def broad_search_credentials_cache_characters(target, permission, credentials)
132
+ prefix = target
133
+ while prefix != 's3://'
134
+ key = credentials_cache_key("#{prefix}*", permission, credentials)
135
+ return @credentials_cache[key] if @credentials_cache.key?(key)
136
+
137
+ prefix = prefix[0..-2]
138
+ end
139
+ nil
140
+ end
141
+
142
+ def new_credentials_for(target, permission, credentials)
143
+ bucket_region = bucket_region_for_access_grants(target)
144
+ client = s3_control_client(bucket_region)
145
+
146
+ AccessGrantsCredentials.new(
147
+ target: target,
148
+ account_id: account_id_for_access_grants(target, credentials),
149
+ permission: permission,
150
+ client: client
151
+ )
152
+ end
153
+
154
+ def account_id_for_access_grants(target, credentials)
155
+ if @caching
156
+ cached_account_id_for(target, credentials)
157
+ else
158
+ new_account_id_for(target, credentials)
159
+ end
160
+ end
161
+
162
+ def cached_account_id_for(target, credentials)
163
+ bucket = bucket_name_from(target)
164
+
165
+ if @account_id_cache.key?(bucket)
166
+ @account_id_cache[bucket]
167
+ else
168
+ @account_id_cache[bucket] = new_account_id_for(target, credentials)
169
+ end
170
+ end
171
+
172
+ # returns the account id associated with the access grants instance
173
+ def new_account_id_for(target, credentials)
174
+ bucket_region = bucket_region_for_access_grants(target)
175
+ s3_control_client = s3_control_client(bucket_region)
176
+ resp = s3_control_client.get_access_grants_instance_for_prefix(
177
+ s3_prefix: target,
178
+ account_id: account_id_for_credentials(bucket_region, credentials)
179
+ )
180
+ ARNParser.parse(resp.access_grants_instance_arn).account_id
181
+ end
182
+
183
+ def bucket_region_for_access_grants(target)
184
+ bucket = bucket_name_from(target)
185
+ # regardless of caching option, bucket region cache is always shared
186
+ cached_bucket_region_for(bucket)
187
+ end
188
+
189
+ def cached_bucket_region_for(bucket)
190
+ if @bucket_region_cache.key?(bucket)
191
+ @bucket_region_cache[bucket]
192
+ else
193
+ @bucket_region_cache[bucket] = new_bucket_region_for(bucket)
194
+ end
195
+ end
196
+
197
+ def new_bucket_region_for(bucket)
198
+ @s3_client.head_bucket(bucket: bucket).bucket_region
199
+ rescue Aws::S3::Errors::Http301Error => e
200
+ e.data.region
201
+ end
202
+
203
+ # returns the account id for the configured credentials
204
+ def account_id_for_credentials(region, credentials)
205
+ # use resolved credentials to check for account id
206
+ if credentials.respond_to?(:account_id) && credentials.account_id &&
207
+ !credentials.account_id.empty?
208
+ credentials.account_id
209
+ else
210
+ @sts_client ||= Aws::STS::Client.new(
211
+ credentials: s3_client.config.credentials,
212
+ region: region,
213
+ use_fips_endpoint: s3_client.config.use_fips_endpoint,
214
+ use_dualstack_endpoint: s3_client.config.use_dualstack_endpoint
215
+ )
216
+ @sts_client.get_caller_identity.account
217
+ end
218
+ end
219
+
220
+ def target_prefix(bucket, key, prefix)
221
+ if key && !key.empty?
222
+ "s3://#{bucket}/#{key}"
223
+ elsif prefix && !prefix.empty?
224
+ "s3://#{bucket}/#{prefix}"
225
+ else
226
+ "s3://#{bucket}/*"
227
+ end
228
+ end
229
+
230
+ def credentials_cache_key(target, permission, credentials)
231
+ "#{credentials.access_key_id}-#{credentials.secret_access_key}" \
232
+ "-#{permission}-#{target}"
233
+ end
234
+
235
+ # extracts bucket name from target prefix
236
+ def bucket_name_from(target)
237
+ URI(target).host
238
+ end
239
+ end
240
+ end
241
+ end
@@ -15,7 +15,7 @@ module Aws
15
15
  # Registers a block as a callback. This listener is called when a
16
16
  # new bucket/region pair is added to the cache.
17
17
  #
18
- # S3::BUCKET_REGIONS.bucket_added do |bucket_name, region_name|
18
+ # Aws::S3.bucket_region_cache.bucket_added do |bucket_name, region_name|
19
19
  # # ...
20
20
  # end
21
21
  #
@@ -59,6 +59,14 @@ module Aws
59
59
  end
60
60
  end
61
61
 
62
+ # @param [String] key
63
+ # @return [Boolean]
64
+ def key?(key)
65
+ @mutex.synchronize do
66
+ @regions.key?(key)
67
+ end
68
+ end
69
+
62
70
  # @api private
63
71
  def clear
64
72
  @mutex.synchronize { @regions = {} }
@@ -73,9 +81,5 @@ module Aws
73
81
  alias to_h to_hash
74
82
 
75
83
  end
76
-
77
- # @api private
78
- BUCKET_REGIONS = BucketRegionCache.new
79
-
80
84
  end
81
85
  end
@@ -22,6 +22,7 @@ require 'aws-sdk-core/plugins/endpoint_pattern.rb'
22
22
  require 'aws-sdk-core/plugins/response_paging.rb'
23
23
  require 'aws-sdk-core/plugins/stub_responses.rb'
24
24
  require 'aws-sdk-core/plugins/idempotency_token.rb'
25
+ require 'aws-sdk-core/plugins/invocation_id.rb'
25
26
  require 'aws-sdk-core/plugins/jsonvalue_converter.rb'
26
27
  require 'aws-sdk-core/plugins/client_metrics_plugin.rb'
27
28
  require 'aws-sdk-core/plugins/client_metrics_send_plugin.rb'
@@ -34,6 +35,7 @@ require 'aws-sdk-core/plugins/recursion_detection.rb'
34
35
  require 'aws-sdk-core/plugins/sign.rb'
35
36
  require 'aws-sdk-core/plugins/protocols/rest_xml.rb'
36
37
  require 'aws-sdk-s3/plugins/accelerate.rb'
38
+ require 'aws-sdk-s3/plugins/access_grants.rb'
37
39
  require 'aws-sdk-s3/plugins/arn.rb'
38
40
  require 'aws-sdk-s3/plugins/bucket_dns.rb'
39
41
  require 'aws-sdk-s3/plugins/bucket_name_restrictions.rb'
@@ -92,6 +94,7 @@ module Aws::S3
92
94
  add_plugin(Aws::Plugins::ResponsePaging)
93
95
  add_plugin(Aws::Plugins::StubResponses)
94
96
  add_plugin(Aws::Plugins::IdempotencyToken)
97
+ add_plugin(Aws::Plugins::InvocationId)
95
98
  add_plugin(Aws::Plugins::JsonvalueConverter)
96
99
  add_plugin(Aws::Plugins::ClientMetricsPlugin)
97
100
  add_plugin(Aws::Plugins::ClientMetricsSendPlugin)
@@ -104,6 +107,7 @@ module Aws::S3
104
107
  add_plugin(Aws::Plugins::Sign)
105
108
  add_plugin(Aws::Plugins::Protocols::RestXml)
106
109
  add_plugin(Aws::S3::Plugins::Accelerate)
110
+ add_plugin(Aws::S3::Plugins::AccessGrants)
107
111
  add_plugin(Aws::S3::Plugins::ARN)
108
112
  add_plugin(Aws::S3::Plugins::BucketDns)
109
113
  add_plugin(Aws::S3::Plugins::BucketNameRestrictions)
@@ -184,6 +188,16 @@ module Aws::S3
184
188
  # * `~/.aws/credentials`
185
189
  # * `~/.aws/config`
186
190
  #
191
+ # @option options [Boolean] :access_grants (false)
192
+ # When `true`, the S3 client will use the S3 Access Grants feature to
193
+ # authenticate requests. Bucket credentials will be fetched from S3
194
+ # Control using the `get_data_access` API.
195
+ #
196
+ # @option options [Aws::S3::AccessGrantsCredentialsProvider] :access_grants_credentials_provider
197
+ # When `access_grants` is `true`, this option can be used to provide
198
+ # additional options to the credentials provider, including a privilege
199
+ # setting, caching, and fallback behavior.
200
+ #
187
201
  # @option options [String] :access_key_id
188
202
  #
189
203
  # @option options [Boolean] :active_endpoint_cache (false)
@@ -246,10 +260,17 @@ module Aws::S3
246
260
  # @option options [Boolean] :disable_s3_express_session_auth
247
261
  # Parameter to indicate whether S3Express session auth should be disabled
248
262
  #
249
- # @option options [String] :endpoint
250
- # The client endpoint is normally constructed from the `:region`
251
- # option. You should only configure an `:endpoint` when connecting
252
- # to test or custom endpoints. This should be a valid HTTP(S) URI.
263
+ # @option options [String, URI::HTTPS, URI::HTTP] :endpoint
264
+ # Normally you should not configure the `:endpoint` option
265
+ # directly. This is normally constructed from the `:region`
266
+ # option. Configuring `:endpoint` is normally reserved for
267
+ # connecting to test or custom endpoints. The endpoint should
268
+ # be a URI formatted like:
269
+ #
270
+ # 'http://example.com'
271
+ # 'https://example.com'
272
+ # 'http://example.com:123'
273
+ #
253
274
  #
254
275
  # @option options [Integer] :endpoint_cache_max_entries (1000)
255
276
  # Used for the maximum size limit of the LRU cache storing endpoints data
@@ -432,50 +453,65 @@ module Aws::S3
432
453
  # @option options [Aws::S3::EndpointProvider] :endpoint_provider
433
454
  # The endpoint provider used to resolve endpoints. Any object that responds to `#resolve_endpoint(parameters)` where `parameters` is a Struct similar to `Aws::S3::EndpointParameters`
434
455
  #
435
- # @option options [URI::HTTP,String] :http_proxy A proxy to send
436
- # requests through. Formatted like 'http://proxy.com:123'.
437
- #
438
- # @option options [Float] :http_open_timeout (15) The number of
439
- # seconds to wait when opening a HTTP session before raising a
440
- # `Timeout::Error`.
441
- #
442
- # @option options [Float] :http_read_timeout (60) The default
443
- # number of seconds to wait for response data. This value can
444
- # safely be set per-request on the session.
445
- #
446
- # @option options [Float] :http_idle_timeout (5) The number of
447
- # seconds a connection is allowed to sit idle before it is
448
- # considered stale. Stale connections are closed and removed
449
- # from the pool before making a request.
450
- #
451
- # @option options [Float] :http_continue_timeout (1) The number of
452
- # seconds to wait for a 100-continue response before sending the
453
- # request body. This option has no effect unless the request has
454
- # "Expect" header set to "100-continue". Defaults to `nil` which
455
- # disables this behaviour. This value can safely be set per
456
- # request on the session.
457
- #
458
- # @option options [Float] :ssl_timeout (nil) Sets the SSL timeout
459
- # in seconds.
460
- #
461
- # @option options [Boolean] :http_wire_trace (false) When `true`,
462
- # HTTP debug output will be sent to the `:logger`.
456
+ # @option options [Float] :http_continue_timeout (1)
457
+ # The number of seconds to wait for a 100-continue response before sending the
458
+ # request body. This option has no effect unless the request has "Expect"
459
+ # header set to "100-continue". Defaults to `nil` which disables this
460
+ # behaviour. This value can safely be set per request on the session.
461
+ #
462
+ # @option options [Float] :http_idle_timeout (5)
463
+ # The number of seconds a connection is allowed to sit idle before it
464
+ # is considered stale. Stale connections are closed and removed from the
465
+ # pool before making a request.
466
+ #
467
+ # @option options [Float] :http_open_timeout (15)
468
+ # The default number of seconds to wait for response data.
469
+ # This value can safely be set per-request on the session.
470
+ #
471
+ # @option options [URI::HTTP,String] :http_proxy
472
+ # A proxy to send requests through. Formatted like 'http://proxy.com:123'.
473
+ #
474
+ # @option options [Float] :http_read_timeout (60)
475
+ # The default number of seconds to wait for response data.
476
+ # This value can safely be set per-request on the session.
477
+ #
478
+ # @option options [Boolean] :http_wire_trace (false)
479
+ # When `true`, HTTP debug output will be sent to the `:logger`.
480
+ #
481
+ # @option options [Proc] :on_chunk_received
482
+ # When a Proc object is provided, it will be used as callback when each chunk
483
+ # of the response body is received. It provides three arguments: the chunk,
484
+ # the number of bytes received, and the total number of
485
+ # bytes in the response (or nil if the server did not send a `content-length`).
486
+ #
487
+ # @option options [Proc] :on_chunk_sent
488
+ # When a Proc object is provided, it will be used as callback when each chunk
489
+ # of the request body is sent. It provides three arguments: the chunk,
490
+ # the number of bytes read from the body, and the total number of
491
+ # bytes in the body.
492
+ #
493
+ # @option options [Boolean] :raise_response_errors (true)
494
+ # When `true`, response errors are raised.
495
+ #
496
+ # @option options [String] :ssl_ca_bundle
497
+ # Full path to the SSL certificate authority bundle file that should be used when
498
+ # verifying peer certificates. If you do not pass `:ssl_ca_bundle` or
499
+ # `:ssl_ca_directory` the the system default will be used if available.
500
+ #
501
+ # @option options [String] :ssl_ca_directory
502
+ # Full path of the directory that contains the unbundled SSL certificate
503
+ # authority files for verifying peer certificates. If you do
504
+ # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the system
505
+ # default will be used if available.
463
506
  #
464
- # @option options [Boolean] :ssl_verify_peer (true) When `true`,
465
- # SSL peer certificates are verified when establishing a
466
- # connection.
507
+ # @option options [String] :ssl_ca_store
508
+ # Sets the X509::Store to verify peer certificate.
467
509
  #
468
- # @option options [String] :ssl_ca_bundle Full path to the SSL
469
- # certificate authority bundle file that should be used when
470
- # verifying peer certificates. If you do not pass
471
- # `:ssl_ca_bundle` or `:ssl_ca_directory` the the system default
472
- # will be used if available.
510
+ # @option options [Float] :ssl_timeout
511
+ # Sets the SSL timeout in seconds
473
512
  #
474
- # @option options [String] :ssl_ca_directory Full path of the
475
- # directory that contains the unbundled SSL certificate
476
- # authority files for verifying peer certificates. If you do
477
- # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the
478
- # system default will be used if available.
513
+ # @option options [Boolean] :ssl_verify_peer (true)
514
+ # When `true`, SSL peer certificates are verified when establishing a connection.
479
515
  #
480
516
  def initialize(*args)
481
517
  super
@@ -17206,22 +17242,22 @@ module Aws::S3
17206
17242
  #
17207
17243
  # @example EventStream Operation Example
17208
17244
  #
17209
- # You can process event once it arrives immediately, or wait until
17210
- # full response complete and iterate through eventstream enumerator.
17245
+ # You can process the event once it arrives immediately, or wait until the
17246
+ # full response is complete and iterate through the eventstream enumerator.
17211
17247
  #
17212
17248
  # To interact with event immediately, you need to register #select_object_content
17213
- # with callbacks, callbacks can be register for specifc events or for all events,
17214
- # callback for errors in the event stream is also available for register.
17249
+ # with callbacks. Callbacks can be registered for specific events or for all
17250
+ # events, including error events.
17215
17251
  #
17216
- # Callbacks can be passed in by `:event_stream_handler` option or within block
17217
- # statement attached to #select_object_content call directly. Hybrid pattern of both
17218
- # is also supported.
17252
+ # Callbacks can be passed into the `:event_stream_handler` option or within a
17253
+ # block statement attached to the #select_object_content call directly. Hybrid
17254
+ # pattern of both is also supported.
17219
17255
  #
17220
- # `:event_stream_handler` option takes in either Proc object or
17256
+ # `:event_stream_handler` option takes in either a Proc object or
17221
17257
  # Aws::S3::EventStreams::SelectObjectContentEventStream object.
17222
17258
  #
17223
- # Usage pattern a): callbacks with a block attached to #select_object_content
17224
- # Example for registering callbacks for all event types and error event
17259
+ # Usage pattern a): Callbacks with a block attached to #select_object_content
17260
+ # Example for registering callbacks for all event types and an error event
17225
17261
  #
17226
17262
  # client.select_object_content( # params input# ) do |stream|
17227
17263
  # stream.on_error_event do |event|
@@ -17241,9 +17277,9 @@ module Aws::S3
17241
17277
  #
17242
17278
  # end
17243
17279
  #
17244
- # Usage pattern b): pass in `:event_stream_handler` for #select_object_content
17280
+ # Usage pattern b): Pass in `:event_stream_handler` for #select_object_content
17245
17281
  #
17246
- # 1) create a Aws::S3::EventStreams::SelectObjectContentEventStream object
17282
+ # 1) Create a Aws::S3::EventStreams::SelectObjectContentEventStream object
17247
17283
  # Example for registering callbacks with specific events
17248
17284
  #
17249
17285
  # handler = Aws::S3::EventStreams::SelectObjectContentEventStream.new
@@ -17265,7 +17301,7 @@ module Aws::S3
17265
17301
  #
17266
17302
  # client.select_object_content( # params input #, event_stream_handler: handler)
17267
17303
  #
17268
- # 2) use a Ruby Proc object
17304
+ # 2) Use a Ruby Proc object
17269
17305
  # Example for registering callbacks with specific events
17270
17306
  #
17271
17307
  # handler = Proc.new do |stream|
@@ -17288,7 +17324,7 @@ module Aws::S3
17288
17324
  #
17289
17325
  # client.select_object_content( # params input #, event_stream_handler: handler)
17290
17326
  #
17291
- # Usage pattern c): hybird pattern of a) and b)
17327
+ # Usage pattern c): Hybrid pattern of a) and b)
17292
17328
  #
17293
17329
  # handler = Aws::S3::EventStreams::SelectObjectContentEventStream.new
17294
17330
  # handler.on_records_event do |event|
@@ -17318,8 +17354,7 @@ module Aws::S3
17318
17354
  # end
17319
17355
  # end
17320
17356
  #
17321
- # Besides above usage patterns for process events when they arrive immediately, you can also
17322
- # iterate through events after response complete.
17357
+ # You can also iterate through events after the response complete.
17323
17358
  #
17324
17359
  # Events are available at resp.payload # => Enumerator
17325
17360
  # For parameter input example, please refer to following request syntax
@@ -18792,7 +18827,7 @@ module Aws::S3
18792
18827
  params: params,
18793
18828
  config: config)
18794
18829
  context[:gem_name] = 'aws-sdk-s3'
18795
- context[:gem_version] = '1.147.0'
18830
+ context[:gem_version] = '1.149.0'
18796
18831
  Seahorse::Client::Request.new(handlers, context)
18797
18832
  end
18798
18833
 
@@ -3,8 +3,8 @@
3
3
  module Aws
4
4
  module S3
5
5
  module Errors
6
- # Hijack PermanentRedirect dynamic error to also include endpoint
7
- # and bucket.
6
+ # Hijack PermanentRedirect dynamic error to include the bucket, region,
7
+ # and endpoint.
8
8
  class PermanentRedirect < ServiceError
9
9
  # @param [Seahorse::Client::RequestContext] context
10
10
  # @param [String] message
@@ -22,6 +22,19 @@ module Aws
22
22
  super(context, message, data)
23
23
  end
24
24
  end
25
+
26
+ # Hijack PermanentRedirect (HeadBucket case - no body) dynamic error to
27
+ # include the region.
28
+ class Http301Error < ServiceError
29
+ # @param [Seahorse::Client::RequestContext] context
30
+ # @param [String] message
31
+ # @param [Aws::S3::Types::PermanentRedirect] _data
32
+ def initialize(context, message, _data = Aws::EmptyStructure.new)
33
+ data = Aws::S3::Types::PermanentRedirect.new(message: message)
34
+ data.region = context.http_response.headers['x-amz-bucket-region']
35
+ super(context, message, data)
36
+ end
37
+ end
25
38
  end
26
39
  end
27
40
  end
@@ -18,9 +18,12 @@ require 'aws-sdk-s3/presigner'
18
18
 
19
19
  # s3 express session auth
20
20
  require 'aws-sdk-s3/express_credentials'
21
- require 'aws-sdk-s3/express_credentials_cache'
22
21
  require 'aws-sdk-s3/express_credentials_provider'
23
22
 
23
+ # s3 access grants auth
24
+ require 'aws-sdk-s3/access_grants_credentials'
25
+ require 'aws-sdk-s3/access_grants_credentials_provider'
26
+
24
27
  # customizations to generated classes
25
28
  require 'aws-sdk-s3/customizations/bucket'
26
29
  require 'aws-sdk-s3/customizations/errors'
@@ -2,30 +2,53 @@
2
2
 
3
3
  module Aws
4
4
  module S3
5
+ # @api private
6
+ def self.express_credentials_cache
7
+ @express_credentials_cache ||= LRUCache.new(max_entries: 100)
8
+ end
9
+
5
10
  # Returns Credentials class for S3 Express. Accepts CreateSession
6
11
  # params as options. See {Client#create_session} for details.
7
12
  class ExpressCredentialsProvider
8
13
  # @param [Hash] options
9
- # @option options [Client] :client The S3 client used to create the session.
14
+ # @option options [Client] :client The S3 client used to create the
15
+ # session.
10
16
  # @option options [String] :session_mode (see: {Client#create_session})
17
+ # @option options [Boolean] :caching (true) When true, credentials will
18
+ # be cached.
11
19
  # @option options [Callable] :before_refresh Proc called before
12
20
  # credentials are refreshed.
13
21
  def initialize(options = {})
14
22
  @client = options.delete(:client)
23
+ @caching = options.delete(:caching) != false
15
24
  @options = options
16
- @cache = EXPRESS_CREDENTIALS_CACHE
25
+ return unless @caching
26
+
27
+ @cache = Aws::S3.express_credentials_cache
17
28
  end
18
29
 
19
30
  def express_credentials_for(bucket)
20
- @cache[bucket] || new_credentials_for(bucket)
31
+ if @caching
32
+ cached_credentials_for(bucket)
33
+ else
34
+ new_credentials_for(bucket)
35
+ end
21
36
  end
22
37
 
23
38
  attr_accessor :client
24
39
 
25
40
  private
26
41
 
42
+ def cached_credentials_for(bucket)
43
+ if @cache.key?(bucket)
44
+ @cache[bucket]
45
+ else
46
+ @cache[bucket] = new_credentials_for(bucket)
47
+ end
48
+ end
49
+
27
50
  def new_credentials_for(bucket)
28
- @cache[bucket] = ExpressCredentials.new(
51
+ ExpressCredentials.new(
29
52
  bucket: bucket,
30
53
  client: @client,
31
54
  **@options
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ # @api private
7
+ class AccessGrants < Seahorse::Client::Plugin
8
+ @s3control =
9
+ begin
10
+ require 'aws-sdk-s3control'
11
+ true
12
+ rescue LoadError
13
+ false
14
+ end
15
+
16
+ option(
17
+ :access_grants,
18
+ default: false,
19
+ doc_type: 'Boolean',
20
+ docstring: <<-DOCS)
21
+ When `true`, the S3 client will use the S3 Access Grants feature to
22
+ authenticate requests. Bucket credentials will be fetched from S3
23
+ Control using the `get_data_access` API.
24
+ DOCS
25
+
26
+ option(:access_grants_credentials_provider,
27
+ doc_type: 'Aws::S3::AccessGrantsCredentialsProvider',
28
+ rbs_type: 'untyped',
29
+ docstring: <<-DOCS) do |_cfg|
30
+ When `access_grants` is `true`, this option can be used to provide
31
+ additional options to the credentials provider, including a privilege
32
+ setting, caching, and fallback behavior.
33
+ DOCS
34
+ Aws::S3::AccessGrantsCredentialsProvider.new
35
+ end
36
+
37
+ # @api private
38
+ class Handler < Seahorse::Client::Handler
39
+ PERMISSION_MAP = {
40
+ head_object: 'READ',
41
+ get_object: 'READ',
42
+ get_object_acl: 'READ',
43
+ list_multipart_uploads: 'READ',
44
+ list_objects_v2: 'READ',
45
+ list_object_versions: 'READ',
46
+ list_parts: 'READ',
47
+ put_object: 'WRITE',
48
+ put_object_acl: 'WRITE',
49
+ delete_object: 'WRITE',
50
+ abort_multipart_upload: 'WRITE',
51
+ create_multipart_upload: 'WRITE',
52
+ upload_part: 'WRITE',
53
+ complete_multipart_upload: 'WRITE'
54
+ }.freeze
55
+
56
+ def call(context)
57
+ if access_grants_operation?(context) &&
58
+ !s3_express_endpoint?(context)
59
+ params = context[:endpoint_params]
60
+ permission = PERMISSION_MAP[context.operation_name]
61
+
62
+ provider = context.config.access_grants_credentials_provider
63
+ credentials = provider.access_grants_credentials_for(
64
+ bucket: params[:bucket],
65
+ key: params[:key],
66
+ prefix: params[:prefix],
67
+ permission: permission
68
+ )
69
+ context[:sigv4_credentials] = credentials # Sign will use this
70
+ end
71
+
72
+ @handler.call(context)
73
+ end
74
+
75
+ private
76
+
77
+ def access_grants_operation?(context)
78
+ params = context[:endpoint_params]
79
+ params[:bucket] && PERMISSION_MAP[context.operation_name]
80
+ end
81
+
82
+ def s3_express_endpoint?(context)
83
+ context[:endpoint_properties]['backend'] == 'S3Express'
84
+ end
85
+ end
86
+
87
+ def add_handlers(handlers, config)
88
+ return unless AccessGrants.s3control? && config.access_grants
89
+
90
+ handlers.add(Handler)
91
+ end
92
+
93
+ def after_initialize(client)
94
+ return unless AccessGrants.s3control? && client.config.access_grants
95
+
96
+ provider = client.config.access_grants_credentials_provider
97
+ provider.s3_client = client unless provider.s3_client
98
+ end
99
+
100
+ class << self
101
+ def s3control?
102
+ @s3control
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -31,7 +31,7 @@ for different buckets.
31
31
  def call(context)
32
32
  if (props = context[:endpoint_properties])
33
33
  # S3 Express endpoint - turn off md5 and enable crc32 default
34
- if (backend = props['backend']) && backend == 'S3Express'
34
+ if props['backend'] == 'S3Express'
35
35
  if context.operation_name == :put_object || checksum_required?(context)
36
36
  context[:default_request_checksum_algorithm] = 'CRC32'
37
37
  end
@@ -4,6 +4,11 @@ require 'aws-sigv4'
4
4
 
5
5
  module Aws
6
6
  module S3
7
+ # @api private
8
+ def self.bucket_region_cache
9
+ @bucket_region_cache ||= BucketRegionCache.new
10
+ end
11
+
7
12
  module Plugins
8
13
  # This plugin used to have a V4 signer but it was removed in favor of
9
14
  # generic Sign plugin that uses endpoint auth scheme.
@@ -51,7 +56,7 @@ module Aws
51
56
  private
52
57
 
53
58
  def check_for_cached_region(context, bucket)
54
- cached_region = S3::BUCKET_REGIONS[bucket]
59
+ cached_region = Aws::S3.bucket_region_cache[bucket]
55
60
  if cached_region &&
56
61
  cached_region != context.config.region &&
57
62
  !S3Signer.custom_endpoint?(context)
@@ -97,7 +102,7 @@ module Aws
97
102
  end
98
103
 
99
104
  def update_bucket_cache(context, actual_region)
100
- S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
105
+ Aws::S3.bucket_region_cache[context.params[:bucket]] = actual_region
101
106
  end
102
107
 
103
108
  def fips_region?(resp)
@@ -200,6 +200,7 @@ module Aws
200
200
  req.handlers.remove(Aws::Plugins::Sign::Handler)
201
201
  req.handlers.remove(Seahorse::Client::Plugins::ContentLength::Handler)
202
202
  req.handlers.remove(Aws::Rest::ContentTypeHandler)
203
+ req.handlers.remove(Aws::Plugins::InvocationId::Handler)
203
204
 
204
205
  req.handle(step: :send) do |context|
205
206
  # if an endpoint was not provided, force secure or insecure
data/lib/aws-sdk-s3.rb CHANGED
@@ -73,6 +73,6 @@ require_relative 'aws-sdk-s3/event_streams'
73
73
  # @!group service
74
74
  module Aws::S3
75
75
 
76
- GEM_VERSION = '1.147.0'
76
+ GEM_VERSION = '1.149.0'
77
77
 
78
78
  end
data/sig/client.rbs CHANGED
@@ -14,6 +14,8 @@ module Aws
14
14
  def self.new: (
15
15
  ?credentials: untyped,
16
16
  ?region: String,
17
+ ?access_grants: bool,
18
+ ?access_grants_credentials_provider: untyped,
17
19
  ?access_key_id: String,
18
20
  ?active_endpoint_cache: bool,
19
21
  ?adaptive_retry_wait_to_fill: bool,
@@ -0,0 +1,19 @@
1
+ module Aws
2
+ module S3
3
+ class Bucket
4
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Bucket.html#clear!-instance_method
5
+ def clear!: () -> void
6
+
7
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Bucket.html#delete!-instance_method
8
+ def delete!: (?max_attempts: ::Integer, ?initial_wait: ::Float) -> void
9
+ | (?Hash[Symbol, untyped]) -> void
10
+
11
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Bucket.html#url-instance_method
12
+ def url: (?virtual_host: boolish, ?secure: boolish) -> String
13
+ | (?Hash[Symbol, untyped]) -> String
14
+
15
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Bucket.html#presigned_post-instance_method
16
+ def presigned_post: (Hash[Symbol, untyped]) -> untyped
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ module Aws
2
+ module S3
3
+ class Object
4
+ alias size content_length
5
+
6
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#copy_from-instance_method
7
+ def copy_from: (untyped source, ?Hash[Symbol, untyped] options) -> void
8
+ | ...
9
+
10
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#copy_to-instance_method
11
+ def copy_to: (untyped target, ?Hash[Symbol, untyped] options) -> void
12
+
13
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#move_to-instance_method
14
+ def move_to: (untyped target, ?Hash[Symbol, untyped] options) -> void
15
+
16
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
17
+ def presigned_post: (?Hash[Symbol, untyped]) -> untyped
18
+
19
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
20
+ def presigned_url: (Symbol | String method, ?Hash[Symbol, untyped] params) -> String
21
+
22
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_request-instance_method
23
+ def presigned_request: (Symbol | String method, ?Hash[Symbol, untyped] params) -> [String, Hash[String, String]]
24
+
25
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#public_url-instance_method
26
+ def public_url: (?Hash[Symbol, untyped] options) -> String
27
+
28
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#upload_stream-instance_method
29
+ def upload_stream: (?Hash[Symbol, untyped] options) { (IO write_stream) -> void } -> bool
30
+
31
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#upload_file-instance_method
32
+ def upload_file: (untyped source, ?Hash[Symbol, untyped] options) ?{ (untyped response) -> void } -> bool
33
+
34
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#download_file-instance_method
35
+ def download_file: (String destination, ?Hash[Symbol, untyped] options) -> bool
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ module Aws
2
+ module S3
3
+ class ObjectSummary
4
+ alias content_length size
5
+
6
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#copy_from-instance_method
7
+ def copy_from: (untyped source, ?Hash[Symbol, untyped] options) -> void
8
+ | ...
9
+
10
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#copy_to-instance_method
11
+ def copy_to: (untyped target, ?Hash[Symbol, untyped] options) -> void
12
+
13
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#move_to-instance_method
14
+ def move_to: (untyped target, ?Hash[Symbol, untyped] options) -> void
15
+
16
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#presigned_post-instance_method
17
+ def presigned_post: (Hash[Symbol, untyped]) -> untyped
18
+
19
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#presigned_url-instance_method
20
+ def presigned_url: (Symbol | String method, ?Hash[Symbol, untyped] params) -> String
21
+
22
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#public_url-instance_method
23
+ def public_url: (?Hash[Symbol, untyped] options) -> String
24
+
25
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#upload_file-instance_method
26
+ def upload_file: (untyped source, ?Hash[Symbol, untyped] options) ?{ (untyped response) -> void } -> bool
27
+
28
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#upload_stream-instance_method
29
+ def upload_stream: (?Hash[Symbol, untyped] options) { (IO write_stream) -> void } -> bool
30
+
31
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/ObjectSummary.html#download_file-instance_method
32
+ def download_file: (String destination, ?Hash[Symbol, untyped] options) -> bool
33
+ end
34
+ end
35
+ end
data/sig/resource.rbs CHANGED
@@ -14,6 +14,8 @@ module Aws
14
14
  ?client: Client,
15
15
  ?credentials: untyped,
16
16
  ?region: String,
17
+ ?access_grants: bool,
18
+ ?access_grants_credentials_provider: untyped,
17
19
  ?access_key_id: String,
18
20
  ?active_endpoint_cache: bool,
19
21
  ?adaptive_retry_wait_to_fill: bool,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-sdk-s3
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.147.0
4
+ version: 1.149.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-16 00:00:00.000000000 Z
11
+ date: 2024-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-kms
@@ -47,7 +47,7 @@ dependencies:
47
47
  version: '3'
48
48
  - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 3.192.0
50
+ version: 3.194.0
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
@@ -57,7 +57,7 @@ dependencies:
57
57
  version: '3'
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 3.192.0
60
+ version: 3.194.0
61
61
  description: Official AWS Ruby gem for Amazon Simple Storage Service (Amazon S3).
62
62
  This gem is part of the AWS SDK for Ruby.
63
63
  email:
@@ -70,6 +70,8 @@ files:
70
70
  - LICENSE.txt
71
71
  - VERSION
72
72
  - lib/aws-sdk-s3.rb
73
+ - lib/aws-sdk-s3/access_grants_credentials.rb
74
+ - lib/aws-sdk-s3/access_grants_credentials_provider.rb
73
75
  - lib/aws-sdk-s3/bucket.rb
74
76
  - lib/aws-sdk-s3/bucket_acl.rb
75
77
  - lib/aws-sdk-s3/bucket_cors.rb
@@ -127,7 +129,6 @@ files:
127
129
  - lib/aws-sdk-s3/errors.rb
128
130
  - lib/aws-sdk-s3/event_streams.rb
129
131
  - lib/aws-sdk-s3/express_credentials.rb
130
- - lib/aws-sdk-s3/express_credentials_cache.rb
131
132
  - lib/aws-sdk-s3/express_credentials_provider.rb
132
133
  - lib/aws-sdk-s3/file_downloader.rb
133
134
  - lib/aws-sdk-s3/file_part.rb
@@ -145,6 +146,7 @@ files:
145
146
  - lib/aws-sdk-s3/object_summary.rb
146
147
  - lib/aws-sdk-s3/object_version.rb
147
148
  - lib/aws-sdk-s3/plugins/accelerate.rb
149
+ - lib/aws-sdk-s3/plugins/access_grants.rb
148
150
  - lib/aws-sdk-s3/plugins/arn.rb
149
151
  - lib/aws-sdk-s3/plugins/bucket_dns.rb
150
152
  - lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb
@@ -182,6 +184,9 @@ files:
182
184
  - sig/bucket_versioning.rbs
183
185
  - sig/bucket_website.rbs
184
186
  - sig/client.rbs
187
+ - sig/customizations/bucket.rbs
188
+ - sig/customizations/object.rbs
189
+ - sig/customizations/object_summary.rbs
185
190
  - sig/errors.rbs
186
191
  - sig/multipart_upload.rbs
187
192
  - sig/multipart_upload_part.rbs
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aws
4
- module S3
5
- # @api private
6
- class ExpressCredentialsCache
7
- def initialize
8
- @credentials = {}
9
- @mutex = Mutex.new
10
- end
11
-
12
- def [](bucket_name)
13
- @mutex.synchronize { @credentials[bucket_name] }
14
- end
15
-
16
- def []=(bucket_name, credential_provider)
17
- @mutex.synchronize do
18
- @credentials[bucket_name] = credential_provider
19
- end
20
- end
21
-
22
- def clear
23
- @mutex.synchronize { @credentials = {} }
24
- end
25
- end
26
-
27
- # @api private
28
- EXPRESS_CREDENTIALS_CACHE = ExpressCredentialsCache.new
29
- end
30
- end