aws-sdk-core 3.125.5 → 3.130.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,340 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Plugins
5
+ # @api private
6
+ class ChecksumAlgorithm < Seahorse::Client::Plugin
7
+ CHUNK_SIZE = 1 * 1024 * 1024 # one MB
8
+
9
+ # determine the set of supported client side checksum algorithms
10
+ # CRC32c requires aws-crt (optional sdk dependency) for support
11
+ CLIENT_ALGORITHMS = begin
12
+ supported = %w[SHA256 SHA1 CRC32]
13
+ begin
14
+ require 'aws-crt'
15
+ supported << 'CRC32C'
16
+ rescue LoadError
17
+ end
18
+ supported
19
+ end.freeze
20
+
21
+ # priority order of checksum algorithms to validate responses against
22
+ # Remove any algorithms not supported by client (ie, depending on CRT availability)
23
+ CHECKSUM_ALGORITHM_PRIORITIES = %w[CRC32C SHA1 CRC32 SHA256] & CLIENT_ALGORITHMS
24
+
25
+ # byte size of checksums, used in computing the trailer length
26
+ CHECKSUM_SIZE = {
27
+ 'CRC32' => 16,
28
+ 'CRC32C' => 16,
29
+ 'SHA1' => 36,
30
+ 'SHA256' => 52
31
+ }
32
+
33
+ # Interface for computing digests on request/response bodies
34
+ # which may be files, strings or IO like objects
35
+ # Applies only to digest functions that produce 32 bit integer checksums
36
+ # (eg CRC32)
37
+ class Digest32
38
+
39
+ attr_reader :value
40
+
41
+ # @param [Object] digest_fn
42
+ def initialize(digest_fn)
43
+ @digest_fn = digest_fn
44
+ @value = 0
45
+ end
46
+
47
+ def update(chunk)
48
+ @value = @digest_fn.call(chunk, @value)
49
+ end
50
+
51
+ def base64digest
52
+ Base64.encode64([@value].pack('N')).chomp
53
+ end
54
+ end
55
+
56
+ def add_handlers(handlers, _config)
57
+ handlers.add(OptionHandler, step: :initialize)
58
+ # priority set low to ensure checksum is computed AFTER the request is
59
+ # built but before it is signed
60
+ handlers.add(ChecksumHandler, priority: 15, step: :build)
61
+ end
62
+
63
+ private
64
+
65
+ def self.request_algorithm_selection(context)
66
+ return unless context.operation.http_checksum
67
+
68
+ input_member = context.operation.http_checksum['requestAlgorithmMember']
69
+ context.params[input_member.to_sym]&.upcase if input_member
70
+ end
71
+
72
+ def self.request_validation_mode(context)
73
+ return unless context.operation.http_checksum
74
+
75
+ input_member = context.operation.http_checksum['requestValidationModeMember']
76
+ context.params[input_member.to_sym] if input_member
77
+ end
78
+
79
+ def self.operation_response_algorithms(context)
80
+ return unless context.operation.http_checksum
81
+
82
+ context.operation.http_checksum['responseAlgorithms']
83
+ end
84
+
85
+
86
+ # @api private
87
+ class OptionHandler < Seahorse::Client::Handler
88
+ def call(context)
89
+ context[:http_checksum] ||= {}
90
+
91
+ # validate request configuration
92
+ if (request_input = ChecksumAlgorithm.request_algorithm_selection(context))
93
+ unless CLIENT_ALGORITHMS.include? request_input
94
+ if (request_input == 'CRC32C')
95
+ raise ArgumentError, "CRC32C requires crt support - install the aws-crt gem for support."
96
+ else
97
+ raise ArgumentError, "#{request_input} is not a supported checksum algorithm."
98
+ end
99
+ end
100
+ end
101
+
102
+ # validate response configuration
103
+ if (ChecksumAlgorithm.request_validation_mode(context))
104
+ # Compute an ordered list as the union between priority supported and the
105
+ # operation's modeled response algorithms.
106
+ validation_list = CHECKSUM_ALGORITHM_PRIORITIES &
107
+ ChecksumAlgorithm.operation_response_algorithms(context)
108
+ context[:http_checksum][:validation_list] = validation_list
109
+ end
110
+
111
+ @handler.call(context)
112
+ end
113
+ end
114
+
115
+ # @api private
116
+ class ChecksumHandler < Seahorse::Client::Handler
117
+
118
+ def call(context)
119
+ if should_calculate_request_checksum?(context)
120
+ request_algorithm_input = ChecksumAlgorithm.request_algorithm_selection(context)
121
+ context[:checksum_algorithms] = request_algorithm_input
122
+
123
+ request_checksum_property = {
124
+ 'algorithm' => request_algorithm_input,
125
+ 'in' => checksum_request_in(context),
126
+ 'name' => "x-amz-checksum-#{request_algorithm_input.downcase}"
127
+ }
128
+
129
+ calculate_request_checksum(context, request_checksum_property)
130
+ end
131
+
132
+ if should_verify_response_checksum?(context)
133
+ add_verify_response_checksum_handlers(context)
134
+ end
135
+
136
+ @handler.call(context)
137
+ end
138
+
139
+ private
140
+
141
+ def should_calculate_request_checksum?(context)
142
+ context.operation.http_checksum &&
143
+ ChecksumAlgorithm.request_algorithm_selection(context)
144
+ end
145
+
146
+ def should_verify_response_checksum?(context)
147
+ context[:http_checksum][:validation_list] && !context[:http_checksum][:validation_list].empty?
148
+ end
149
+
150
+ def calculate_request_checksum(context, checksum_properties)
151
+ case checksum_properties['in']
152
+ when 'header'
153
+ header_name = checksum_properties['name']
154
+ body = context.http_request.body_contents
155
+ if body
156
+ context.http_request.headers[header_name] ||=
157
+ ChecksumAlgorithm.calculate_checksum(checksum_properties['algorithm'], body)
158
+ end
159
+ when 'trailer'
160
+ apply_request_trailer_checksum(context, checksum_properties)
161
+ end
162
+ end
163
+
164
+ def apply_request_trailer_checksum(context, checksum_properties)
165
+ location_name = checksum_properties['name']
166
+
167
+ # set required headers
168
+ headers = context.http_request.headers
169
+ headers['Content-Encoding'] = 'aws-chunked'
170
+ headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
171
+ headers['X-Amz-Trailer'] = location_name
172
+
173
+ # We currently always compute the size in the modified body wrapper - allowing us
174
+ # to set the Content-Length header (set by content_length plugin).
175
+ # This means we cannot use Transfer-Encoding=chunked
176
+
177
+ if !context.http_request.body.respond_to?(:size)
178
+ raise Aws::Errors::ChecksumError, 'Could not determine length of the body'
179
+ end
180
+ headers['X-Amz-Decoded-Content-Length'] = context.http_request.body.size
181
+
182
+ context.http_request.body = AwsChunkedTrailerDigestIO.new(
183
+ context.http_request.body,
184
+ checksum_properties['algorithm'],
185
+ location_name
186
+ )
187
+ end
188
+
189
+ # Add events to the http_response to verify the checksum as its read
190
+ # This prevents the body from being read multiple times
191
+ # verification is done only once a successful response has completed
192
+ def add_verify_response_checksum_handlers(context)
193
+ http_response = context.http_response
194
+ checksum_context = { }
195
+ http_response.on_headers do |_status, headers|
196
+ header_name, algorithm = response_header_to_verify(headers, context[:http_checksum][:validation_list])
197
+ if header_name
198
+ expected = headers[header_name]
199
+
200
+ unless context[:http_checksum][:skip_on_suffix] && /-[\d]+$/.match(expected)
201
+ checksum_context[:algorithm] = algorithm
202
+ checksum_context[:header_name] = header_name
203
+ checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
204
+ checksum_context[:expected] = expected
205
+ end
206
+ end
207
+ end
208
+
209
+ http_response.on_data do |chunk|
210
+ checksum_context[:digest].update(chunk) if checksum_context[:digest]
211
+ end
212
+
213
+ http_response.on_success do
214
+ if checksum_context[:digest] &&
215
+ (computed = checksum_context[:digest].base64digest)
216
+
217
+ if computed != checksum_context[:expected]
218
+ raise Aws::Errors::ChecksumError,
219
+ "Checksum validation failed on #{checksum_context[:header_name]} "\
220
+ "computed: #{computed}, expected: #{checksum_context[:expected]}"
221
+ end
222
+
223
+ context[:http_checksum][:validated] = checksum_context[:algorithm]
224
+ end
225
+ end
226
+ end
227
+
228
+ # returns nil if no headers to verify
229
+ def response_header_to_verify(headers, validation_list)
230
+ validation_list.each do |algorithm|
231
+ header_name = "x-amz-checksum-#{algorithm}"
232
+ return [header_name, algorithm] if headers[header_name]
233
+ end
234
+ nil
235
+ end
236
+
237
+ # determine where (header vs trailer) a request checksum should be added
238
+ def checksum_request_in(context)
239
+ if context.operation['authtype'].eql?('v4-unsigned-body')
240
+ 'trailer'
241
+ else
242
+ 'header'
243
+ end
244
+ end
245
+
246
+ end
247
+
248
+ def self.calculate_checksum(algorithm, body)
249
+ digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
250
+ if body.respond_to?(:read)
251
+ ChecksumAlgorithm.update_in_chunks(digest, body)
252
+ else
253
+ digest.update(body)
254
+ end
255
+ digest.base64digest
256
+ end
257
+
258
+ def self.digest_for_algorithm(algorithm)
259
+ case algorithm
260
+ when 'CRC32'
261
+ Digest32.new(Zlib.method(:crc32))
262
+ when 'CRC32C'
263
+ # this will only be used if input algorithm is CRC32C AND client supports it (crt available)
264
+ Digest32.new(Aws::Crt::Checksums.method(:crc32c))
265
+ when 'SHA1'
266
+ Digest::SHA1.new
267
+ when 'SHA256'
268
+ Digest::SHA256.new
269
+ end
270
+ end
271
+
272
+ # The trailer size (in bytes) is the overhead + the trailer name +
273
+ # the length of the base64 encoded checksum
274
+ def self.trailer_length(algorithm, location_name)
275
+ CHECKSUM_SIZE[algorithm] + location_name.size
276
+ end
277
+
278
+ def self.update_in_chunks(digest, io)
279
+ loop do
280
+ chunk = io.read(CHUNK_SIZE)
281
+ break unless chunk
282
+ digest.update(chunk)
283
+ end
284
+ io.rewind
285
+ end
286
+
287
+ # Wrapper for request body that implements application-layer
288
+ # chunking with Digest computed on chunks + added as a trailer
289
+ class AwsChunkedTrailerDigestIO
290
+ CHUNK_SIZE = 16384
291
+
292
+ def initialize(io, algorithm, location_name)
293
+ @io = io
294
+ @location_name = location_name
295
+ @algorithm = algorithm
296
+ @digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
297
+ @trailer_io = nil
298
+ end
299
+
300
+ # the size of the application layer aws-chunked + trailer body
301
+ def size
302
+ # compute the number of chunks
303
+ # a full chunk has 4 + 4 bytes overhead, a partial chunk is len.to_s(16).size + 4
304
+ orig_body_size = @io.size
305
+ n_full_chunks = orig_body_size / CHUNK_SIZE
306
+ partial_bytes = orig_body_size % CHUNK_SIZE
307
+ chunked_body_size = n_full_chunks * (CHUNK_SIZE + 8)
308
+ chunked_body_size += partial_bytes.to_s(16).size + partial_bytes + 4 unless partial_bytes.zero?
309
+ trailer_size = ChecksumAlgorithm.trailer_length(@algorithm, @location_name)
310
+ chunked_body_size + trailer_size
311
+ end
312
+
313
+ def rewind
314
+ @io.rewind
315
+ end
316
+
317
+ def read(length, buf)
318
+ # account for possible leftover bytes at the end, if we have trailer bytes, send them
319
+ if @trailer_io
320
+ return @trailer_io.read(length, buf)
321
+ end
322
+
323
+ chunk = @io.read(length)
324
+ if chunk
325
+ @digest.update(chunk)
326
+ application_chunked = "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
327
+ return StringIO.new(application_chunked).read(application_chunked.size, buf)
328
+ else
329
+ trailers = {}
330
+ trailers[@location_name] = @digest.base64digest
331
+ trailers = trailers.map { |k,v| "#{k}:#{v}"}.join("\r\n")
332
+ @trailer_io = StringIO.new("0\r\n#{trailers}\r\n\r\n")
333
+ chunk = @trailer_io.read(length, buf)
334
+ end
335
+ chunk
336
+ end
337
+ end
338
+ end
339
+ end
340
+ end
@@ -11,7 +11,8 @@ module Aws
11
11
  CHUNK_SIZE = 1 * 1024 * 1024 # one MB
12
12
 
13
13
  def call(context)
14
- if context.operation.http_checksum_required
14
+ if checksum_required?(context) &&
15
+ !context[:checksum_algorithms] # skip in favor of flexible checksum
15
16
  body = context.http_request.body
16
17
  context.http_request.headers['Content-Md5'] ||= md5(body)
17
18
  end
@@ -20,6 +21,12 @@ module Aws
20
21
 
21
22
  private
22
23
 
24
+ def checksum_required?(context)
25
+ context.operation.http_checksum_required ||
26
+ (context.operation.http_checksum &&
27
+ context.operation.http_checksum['requestChecksumRequired'])
28
+ end
29
+
23
30
  # @param [File, Tempfile, IO#read, String] value
24
31
  # @return [String<MD5>]
25
32
  def md5(value)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Plugins
5
+ # @api private
6
+ class RecursionDetection < Seahorse::Client::Plugin
7
+
8
+ # @api private
9
+ class Handler < Seahorse::Client::Handler
10
+ def call(context)
11
+
12
+ unless context.http_request.headers.key?('x-amz-trace-id')
13
+ if ENV['AWS_LAMBDA_FUNCTION_NAME'] &&
14
+ (trace_id = ENV['_X_AMZ_TRACE_ID'])
15
+ context.http_request.headers['x-amz-trace-id'] = trace_id
16
+ end
17
+ end
18
+ @handler.call(context)
19
+ end
20
+ end
21
+
22
+ # should be at the end of build so that
23
+ # modeled traits / service customizations apply first
24
+ handler(Handler, step: :build, order: 99)
25
+ end
26
+ end
27
+ end
@@ -10,7 +10,7 @@ module Aws
10
10
  def call(context)
11
11
  context[:original_params] = context.params
12
12
  resp = @handler.call(context)
13
- resp.extend(PageableResponse)
13
+ PageableResponse.apply(resp)
14
14
  resp.pager = context.operation[:pager] || Aws::Pager::NullPager.new
15
15
  resp
16
16
  end
@@ -82,7 +82,7 @@ module Aws
82
82
  end
83
83
 
84
84
  def checksum?
85
- CHECKSUM_ERRORS.include?(@name) || @error.is_a?(Errors::ChecksumError)
85
+ CHECKSUM_ERRORS.include?(@name)
86
86
  end
87
87
 
88
88
  def networking?
@@ -98,6 +98,7 @@ module Aws
98
98
  req.headers.delete('Authorization')
99
99
  req.headers.delete('X-Amz-Security-Token')
100
100
  req.headers.delete('X-Amz-Date')
101
+ req.headers.delete('x-Amz-Region-Set')
101
102
 
102
103
  if context.config.respond_to?(:clock_skew) &&
103
104
  context.config.clock_skew &&
@@ -134,7 +135,7 @@ module Aws
134
135
  def apply_authtype(context)
135
136
  if context.operation['authtype'].eql?('v4-unsigned-body') &&
136
137
  context.http_request.endpoint.scheme.eql?('https')
137
- context.http_request.headers['X-Amz-Content-Sha256'] = 'UNSIGNED-PAYLOAD'
138
+ context.http_request.headers['X-Amz-Content-Sha256'] ||= 'UNSIGNED-PAYLOAD'
138
139
  end
139
140
  context
140
141
  end
@@ -51,7 +51,11 @@ requests are made, and retries are disabled.
51
51
  stub = context.client.next_stub(context)
52
52
  resp = Seahorse::Client::Response.new(context: context)
53
53
  async_mode = context.client.is_a? Seahorse::Client::AsyncBase
54
- apply_stub(stub, resp, async_mode)
54
+ if Hash === stub && stub[:mutex]
55
+ stub[:mutex].synchronize { apply_stub(stub, resp, async_mode) }
56
+ else
57
+ apply_stub(stub, resp, async_mode)
58
+ end
55
59
 
56
60
  async_mode ? Seahorse::Client::AsyncResponse.new(
57
61
  context: context, stream: context[:input_event_stream_handler].event_emitter.stream, sync_queue: Queue.new) : resp
@@ -27,6 +27,7 @@ module Aws
27
27
  def initialize(process)
28
28
  @process = process
29
29
  @credentials = credentials_from_process(@process)
30
+ @async_refresh = false
30
31
 
31
32
  super
32
33
  end
@@ -73,9 +74,9 @@ module Aws
73
74
  @credentials = credentials_from_process(@process)
74
75
  end
75
76
 
76
- def near_expiration?
77
+ def near_expiration?(expiration_length)
77
78
  # are we within 5 minutes of expiration?
78
- @expiration && (Time.now.to_i + 5 * 60) > @expiration.to_i
79
+ @expiration && (Time.now.to_i + expiration_length) > @expiration.to_i
79
80
  end
80
81
  end
81
82
  end
@@ -17,45 +17,74 @@ module Aws
17
17
  # @api private
18
18
  module RefreshingCredentials
19
19
 
20
+ SYNC_EXPIRATION_LENGTH = 300 # 5 minutes
21
+ ASYNC_EXPIRATION_LENGTH = 600 # 10 minutes
22
+
20
23
  def initialize(options = {})
21
24
  @mutex = Mutex.new
25
+ @before_refresh = options.delete(:before_refresh) if Hash === options
26
+
27
+ @before_refresh.call(self) if @before_refresh
22
28
  refresh
23
29
  end
24
30
 
25
31
  # @return [Credentials]
26
32
  def credentials
27
- refresh_if_near_expiration
33
+ refresh_if_near_expiration!
28
34
  @credentials
29
35
  end
30
36
 
31
37
  # @return [Time,nil]
32
38
  def expiration
33
- refresh_if_near_expiration
39
+ refresh_if_near_expiration!
34
40
  @expiration
35
41
  end
36
42
 
37
43
  # Refresh credentials.
38
44
  # @return [void]
39
45
  def refresh!
40
- @mutex.synchronize { refresh }
46
+ @mutex.synchronize do
47
+ @before_refresh.call(self) if @before_refresh
48
+
49
+ refresh
50
+ end
41
51
  end
42
52
 
43
53
  private
44
54
 
45
- # Refreshes instance metadata credentials if they are within
46
- # 5 minutes of expiration.
47
- def refresh_if_near_expiration
48
- if near_expiration?
55
+ # Refreshes credentials asynchronously and synchronously.
56
+ # If we are near to expiration, block while getting new credentials.
57
+ # Otherwise, if we're approaching expiration, use the existing credentials
58
+ # but attempt a refresh in the background.
59
+ def refresh_if_near_expiration!
60
+ # Note: This check is an optimization. Rather than acquire the mutex on every #refresh_if_near_expiration
61
+ # call, we check before doing so, and then we check within the mutex to avoid a race condition.
62
+ # See issue: https://github.com/aws/aws-sdk-ruby/issues/2641 for more info.
63
+ if near_expiration?(SYNC_EXPIRATION_LENGTH)
49
64
  @mutex.synchronize do
50
- refresh if near_expiration?
65
+ if near_expiration?(SYNC_EXPIRATION_LENGTH)
66
+ @before_refresh.call(self) if @before_refresh
67
+ refresh
68
+ end
69
+ end
70
+ elsif @async_refresh && near_expiration?(ASYNC_EXPIRATION_LENGTH)
71
+ unless @mutex.locked?
72
+ Thread.new do
73
+ @mutex.synchronize do
74
+ if near_expiration?(ASYNC_EXPIRATION_LENGTH)
75
+ @before_refresh.call(self) if @before_refresh
76
+ refresh
77
+ end
78
+ end
79
+ end
51
80
  end
52
81
  end
53
82
  end
54
83
 
55
- def near_expiration?
84
+ def near_expiration?(expiration_length)
56
85
  if @expiration
57
- # are we within 5 minutes of expiration?
58
- (Time.now.to_i + 5 * 60) > @expiration.to_i
86
+ # Are we within expiration?
87
+ (Time.now.to_i + expiration_length) > @expiration.to_i
59
88
  else
60
89
  true
61
90
  end
@@ -100,7 +100,7 @@ module Aws
100
100
  # or `nil` if no valid credentials were found.
101
101
  def credentials(opts = {})
102
102
  p = opts[:profile] || @profile_name
103
- validate_profile_exists(p) if credentials_present?
103
+ validate_profile_exists(p)
104
104
  if (credentials = credentials_from_shared(p, opts))
105
105
  credentials
106
106
  elsif (credentials = credentials_from_config(p, opts))
@@ -195,11 +195,6 @@ module Aws
195
195
  value
196
196
  end
197
197
 
198
- def credentials_present?
199
- (@parsed_credentials && !@parsed_credentials.empty?) ||
200
- (@parsed_config && !@parsed_config.empty?)
201
- end
202
-
203
198
  def assume_role_from_profile(cfg, profile, opts, chain_config)
204
199
  if cfg && prof_cfg = cfg[profile]
205
200
  opts[:source_profile] ||= prof_cfg['source_profile']
@@ -63,6 +63,11 @@ module Aws
63
63
  #
64
64
  # @option options [SSO::Client] :client Optional `SSO::Client`. If not
65
65
  # provided, a client will be constructed.
66
+ #
67
+ # @option options [Callable] before_refresh Proc called before
68
+ # credentials are refreshed. `before_refresh` is called
69
+ # with an instance of this object when
70
+ # AWS credentials are required and need to be refreshed.
66
71
  def initialize(options = {})
67
72
 
68
73
  missing_keys = SSO_REQUIRED_OPTS.select { |k| options[k].nil? }
@@ -81,6 +86,7 @@ module Aws
81
86
  options[:region] = @sso_region
82
87
  options[:credentials] = nil
83
88
  @client = options[:client] || Aws::SSO::Client.new(options)
89
+ @async_refresh = true
84
90
  super
85
91
  end
86
92
 
@@ -27,7 +27,9 @@ require 'aws-sdk-core/plugins/client_metrics_plugin.rb'
27
27
  require 'aws-sdk-core/plugins/client_metrics_send_plugin.rb'
28
28
  require 'aws-sdk-core/plugins/transfer_encoding.rb'
29
29
  require 'aws-sdk-core/plugins/http_checksum.rb'
30
+ require 'aws-sdk-core/plugins/checksum_algorithm.rb'
30
31
  require 'aws-sdk-core/plugins/defaults_mode.rb'
32
+ require 'aws-sdk-core/plugins/recursion_detection.rb'
31
33
  require 'aws-sdk-core/plugins/signature_v4.rb'
32
34
  require 'aws-sdk-core/plugins/protocols/rest_json.rb'
33
35
 
@@ -74,7 +76,9 @@ module Aws::SSO
74
76
  add_plugin(Aws::Plugins::ClientMetricsSendPlugin)
75
77
  add_plugin(Aws::Plugins::TransferEncoding)
76
78
  add_plugin(Aws::Plugins::HttpChecksum)
79
+ add_plugin(Aws::Plugins::ChecksumAlgorithm)
77
80
  add_plugin(Aws::Plugins::DefaultsMode)
81
+ add_plugin(Aws::Plugins::RecursionDetection)
78
82
  add_plugin(Aws::Plugins::SignatureV4)
79
83
  add_plugin(Aws::Plugins::Protocols::RestJson)
80
84
 
@@ -541,7 +545,7 @@ module Aws::SSO
541
545
  params: params,
542
546
  config: config)
543
547
  context[:gem_name] = 'aws-sdk-core'
544
- context[:gem_version] = '3.125.5'
548
+ context[:gem_version] = '3.130.0'
545
549
  Seahorse::Client::Request.new(handlers, context)
546
550
  end
547
551
 
data/lib/aws-sdk-sso.rb CHANGED
@@ -50,6 +50,6 @@ require_relative 'aws-sdk-sso/customizations'
50
50
  # @!group service
51
51
  module Aws::SSO
52
52
 
53
- GEM_VERSION = '3.125.5'
53
+ GEM_VERSION = '3.130.0'
54
54
 
55
55
  end