aws-sdk-core 3.104.1 → 3.107.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: 70a6905bf06dee70851564691ecbfd4df7e750c087d302c2c32c711c6d628c2e
4
- data.tar.gz: 7a895028e693d8ec2b65930b212e2e83ff3edccce7f3cd594df31208d00e9796
3
+ metadata.gz: 6d1947f118cb9fb3ae23c3e5fb51454c34d3c12bd619fc4cd2d4ecb60f0a4b31
4
+ data.tar.gz: c0eec064c19eb08e1ae8d641fd9bcfcba4fc3c6676294209268a5b66578ef4bf
5
5
  SHA512:
6
- metadata.gz: 8a3c29b11ac10b61679545cb7c133b272f25f7717d8cbb935e85272ad588c77b8db61483e24f6d9624676704fc04db8c4c280e6d89f6399bd38816d3184a4172
7
- data.tar.gz: 673a1eb3b3a33e181426f5585117834c9c69ee4226adcae4b5c9c05e9d8e59d8311d26befcadc0d6acba21de01d762557862ac88bc5124a67e763000e1abd40d
6
+ metadata.gz: d20011f32bb555def30a1911330b722c7ed016f4d8a8d397460cb2cc9b0f069214d5984076966ad9dad18e1eb180b139ea35bacc69fc030bebde64c883df29cf
7
+ data.tar.gz: ff3975dc97b11ca149576348128938bf93751d5e13ad86558d3dc78d06696ced46e4d7f56f4b33246bd9820600d296f8205b7eb7456c9583f271ffdedf9ba363
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.104.1
1
+ 3.107.0
@@ -18,9 +18,9 @@ require_relative 'aws-sdk-core/ecs_credentials'
18
18
  require_relative 'aws-sdk-core/instance_profile_credentials'
19
19
  require_relative 'aws-sdk-core/shared_credentials'
20
20
  require_relative 'aws-sdk-core/process_credentials'
21
+ require_relative 'aws-sdk-core/sso_credentials'
21
22
 
22
23
  # client modules
23
-
24
24
  require_relative 'aws-sdk-core/client_stubs'
25
25
  require_relative 'aws-sdk-core/async_client_stubs'
26
26
  require_relative 'aws-sdk-core/eager_loader'
@@ -86,10 +86,12 @@ require_relative 'aws-sdk-core/client_side_monitoring/publisher'
86
86
  require_relative 'aws-sdk-core/arn'
87
87
  require_relative 'aws-sdk-core/arn_parser'
88
88
 
89
- # aws-sdk-sts is vendored to support Aws::AssumeRoleCredentials
90
-
89
+ # aws-sdk-sts is included to support Aws::AssumeRoleCredentials
91
90
  require 'aws-sdk-sts'
92
91
 
92
+ # aws-sdk-sso is included to support Aws::SSOCredentials
93
+ require 'aws-sdk-sso'
94
+
93
95
  module Aws
94
96
 
95
97
  CORE_GEM_VERSION = File.read(File.expand_path('../../VERSION', __FILE__)).strip
@@ -22,11 +22,13 @@ module Aws
22
22
  [
23
23
  [:static_credentials, {}],
24
24
  [:static_profile_assume_role_web_identity_credentials, {}],
25
+ [:static_profile_sso_credentials, {}],
25
26
  [:static_profile_assume_role_credentials, {}],
26
27
  [:static_profile_credentials, {}],
27
28
  [:static_profile_process_credentials, {}],
28
29
  [:env_credentials, {}],
29
30
  [:assume_role_web_identity_credentials, {}],
31
+ [:sso_credentials, {}],
30
32
  [:assume_role_credentials, {}],
31
33
  [:shared_credentials, {}],
32
34
  [:process_credentials, {}],
@@ -57,6 +59,14 @@ module Aws
57
59
  end
58
60
  end
59
61
 
62
+ def static_profile_sso_credentials(options)
63
+ if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile
64
+ Aws.shared_config.sso_credentials_from_config(
65
+ profile: options[:config].profile
66
+ )
67
+ end
68
+ end
69
+
60
70
  def static_profile_assume_role_credentials(options)
61
71
  if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile
62
72
  assume_role_with_profile(options, options[:config].profile)
@@ -115,6 +125,15 @@ module Aws
115
125
  nil
116
126
  end
117
127
 
128
+ def sso_credentials(options)
129
+ profile_name = determine_profile_name(options)
130
+ if Aws.shared_config.config_enabled?
131
+ Aws.shared_config.sso_credentials_from_config(profile: profile_name)
132
+ end
133
+ rescue Errors::NoSuchProfileError
134
+ nil
135
+ end
136
+
118
137
  def assume_role_credentials(options)
119
138
  if Aws.shared_config.config_enabled?
120
139
  assume_role_with_profile(options, determine_profile_name(options))
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
3
  require 'time'
5
4
  require 'net/http'
6
5
 
@@ -81,8 +80,8 @@ module Aws
81
80
  # service is responding but is returning invalid JSON documents
82
81
  # in response to the GET profile credentials call.
83
82
  begin
84
- retry_errors([JSON::ParserError, StandardError], max_retries: 3) do
85
- c = JSON.parse(get_credentials.to_s)
83
+ retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
84
+ c = Aws::Json.load(get_credentials.to_s)
86
85
  @credentials = Credentials.new(
87
86
  c['AccessKeyId'],
88
87
  c['SecretAccessKey'],
@@ -90,7 +89,7 @@ module Aws
90
89
  )
91
90
  @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
92
91
  end
93
- rescue JSON::ParserError
92
+ rescue Aws::Json::ParseError
94
93
  raise Aws::Errors::MetadataParserError.new
95
94
  end
96
95
  end
@@ -207,6 +207,9 @@ module Aws
207
207
  # payload with either invalid version number or malformed contents
208
208
  class InvalidProcessCredentialsPayload < RuntimeError; end
209
209
 
210
+ # Raised when SSO Credentials are invalid
211
+ class InvalidSSOCredentials < RuntimeError; end
212
+
210
213
  # Raised when a client is constructed and region is not specified.
211
214
  class MissingRegionError < ArgumentError
212
215
  def initialize(*args)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
3
  require 'time'
5
4
  require 'net/http'
6
5
 
@@ -92,8 +91,8 @@ module Aws
92
91
  # service is responding but is returning invalid JSON documents
93
92
  # in response to the GET profile credentials call.
94
93
  begin
95
- retry_errors([JSON::ParserError, StandardError], max_retries: 3) do
96
- c = JSON.parse(get_credentials.to_s)
94
+ retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
95
+ c = Aws::Json.load(get_credentials.to_s)
97
96
  @credentials = Credentials.new(
98
97
  c['AccessKeyId'],
99
98
  c['SecretAccessKey'],
@@ -101,7 +100,7 @@ module Aws
101
100
  )
102
101
  @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
103
102
  end
104
- rescue JSON::ParserError
103
+ rescue Aws::Json::ParseError
105
104
  raise Aws::Errors::MetadataParserError
106
105
  end
107
106
  end
@@ -39,7 +39,7 @@ module Aws
39
39
  require 'oj'
40
40
  [
41
41
  Oj,
42
- [{ mode: :compat, symbol_keys: false }],
42
+ [{ mode: :compat, symbol_keys: false, empty_string: false }],
43
43
  [{ mode: :compat }],
44
44
  oj_parse_error
45
45
  ]
@@ -143,8 +143,22 @@ module Aws
143
143
  errors << expected_got(context, "true or false", value)
144
144
  end
145
145
  when BlobShape
146
- unless value.is_a?(String) || io_like?(value)
147
- errors << expected_got(context, "a String or IO object", value)
146
+ unless value.is_a?(String)
147
+ if streaming_input?(ref)
148
+ unless io_like?(value, _require_size = false)
149
+ errors << expected_got(
150
+ context,
151
+ "a String or IO like object that supports read and rewind",
152
+ value
153
+ )
154
+ end
155
+ elsif !io_like?(value, _require_size = true)
156
+ errors << expected_got(
157
+ context,
158
+ "a String or IO like object that supports read, rewind, and size",
159
+ value
160
+ )
161
+ end
148
162
  end
149
163
  else
150
164
  raise "unhandled shape type: #{ref.shape.class.name}"
@@ -167,8 +181,13 @@ module Aws
167
181
  end
168
182
  end
169
183
 
170
- def io_like?(value)
171
- value.respond_to?(:read) && value.respond_to?(:rewind)
184
+ def io_like?(value, require_size = true)
185
+ value.respond_to?(:read) && value.respond_to?(:rewind) &&
186
+ (!require_size || value.respond_to?(:size))
187
+ end
188
+
189
+ def streaming_input?(ref)
190
+ (ref["streaming"] || ref.shape["streaming"])
172
191
  end
173
192
 
174
193
  def error_messages(errors)
@@ -23,7 +23,7 @@ When provided, `x-api-key` header will be injected with the value provided.
23
23
  class OptionHandler < Seahorse::Client::Handler
24
24
  def call(context)
25
25
  if context.operation.require_apikey
26
- if context.params.is_a?(Hash)
26
+ if context.params.is_a?(Hash) && context.params[:api_key]
27
27
  api_key = context.params.delete(:api_key)
28
28
  end
29
29
  api_key = context.config.api_key if api_key.nil?
@@ -30,13 +30,28 @@ following classes:
30
30
  * `Aws::Credentials` - Used for configuring static, non-refreshing
31
31
  credentials.
32
32
 
33
+ * `Aws::SharedCredentials` - Used for loading static credentials from a
34
+ shared file, such as `~/.aws/config`.
35
+
36
+ * `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
37
+
38
+ * `Aws::AssumeRoleWebIdentityCredentials` - Used when you need to
39
+ assume a role after providing credentials via the web.
40
+
41
+ * `Aws::SSOCredentials` - Used for loading credentials from AWS SSO using an
42
+ access token generated from `aws login`.
43
+
44
+ * `Aws::ProcessCredentials` - Used for loading credentials from a
45
+ process that outputs to stdout.
46
+
33
47
  * `Aws::InstanceProfileCredentials` - Used for loading credentials
34
48
  from an EC2 IMDS on an EC2 instance.
35
49
 
36
- * `Aws::SharedCredentials` - Used for loading credentials from a
37
- shared file, such as `~/.aws/config`.
50
+ * `Aws::ECSCredentials` - Used for loading credentials from
51
+ instances running in ECS.
38
52
 
39
- * `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
53
+ * `Aws::CognitoIdentityCredentials` - Used for loading credentials
54
+ from the Cognito Identity service.
40
55
 
41
56
  When `:credentials` are not configured directly, the following
42
57
  locations will be searched for credentials:
@@ -46,10 +61,10 @@ locations will be searched for credentials:
46
61
  * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']
47
62
  * `~/.aws/credentials`
48
63
  * `~/.aws/config`
49
- * EC2 IMDS instance profile - When used by default, the timeouts are
50
- very aggressive. Construct and pass an instance of
51
- `Aws::InstanceProfileCredentails` to enable retries and extended
52
- timeouts.
64
+ * EC2/ECS IMDS instance profile - When used by default, the timeouts
65
+ are very aggressive. Construct and pass an instance of
66
+ `Aws::InstanceProfileCredentails` or `Aws::ECSCredentials` to
67
+ enable retries and extended timeouts.
53
68
  DOCS
54
69
  ) do |config|
55
70
  CredentialProviderChain.new(config).resolve
@@ -42,8 +42,8 @@ module Aws
42
42
 
43
43
  if process_status.success?
44
44
  begin
45
- creds_json = JSON.parse(raw_out)
46
- rescue JSON::ParserError
45
+ creds_json = Aws::Json.load(raw_out)
46
+ rescue Aws::Json::ParseError
47
47
  raise Errors::InvalidProcessCredentialsPayload.new("Invalid JSON response")
48
48
  end
49
49
  payload_version = creds_json['Version']
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'time'
4
4
  require 'base64'
5
- require 'json'
6
5
 
7
6
  module Aws
8
7
  module Rest
@@ -68,7 +67,7 @@ module Aws
68
67
  end
69
68
 
70
69
  def extract_json_trait(value)
71
- JSON.parse(Base64.decode64(value))
70
+ Aws::Json.load(Base64.decode64(value))
72
71
  end
73
72
 
74
73
  end
@@ -3,6 +3,8 @@
3
3
  module Aws
4
4
  # @api private
5
5
  class SharedConfig
6
+ SSO_PROFILE_KEYS = %w[sso_start_url sso_region sso_account_id sso_role_name].freeze
7
+
6
8
  # @return [String]
7
9
  attr_reader :credentials_path
8
10
 
@@ -135,6 +137,18 @@ module Aws
135
137
  end
136
138
  end
137
139
 
140
+ # Attempts to load from shared config or shared credentials file.
141
+ # Will always attempt first to load from the shared credentials
142
+ # file, if present.
143
+ def sso_credentials_from_config(opts = {})
144
+ p = opts[:profile] || @profile_name
145
+ credentials = sso_credentials_from_profile(@parsed_credentials, p)
146
+ if @parsed_config
147
+ credentials ||= sso_credentials_from_profile(@parsed_config, p)
148
+ end
149
+ credentials
150
+ end
151
+
138
152
  # Add an accessor method (similar to attr_reader) to return a configuration value
139
153
  # Uses the get_config_value below to control where
140
154
  # values are loaded from
@@ -146,6 +160,7 @@ module Aws
146
160
 
147
161
  config_reader(
148
162
  :region,
163
+ :ca_bundle,
149
164
  :credential_process,
150
165
  :endpoint_discovery_enabled,
151
166
  :max_attempts,
@@ -237,6 +252,8 @@ module Aws
237
252
  provider.credentials if provider.credentials.set?
238
253
  elsif (provider = assume_role_process_credentials_from_config(profile))
239
254
  provider.credentials if provider.credentials.set?
255
+ elsif (provider = sso_credentials_from_config(profile: profile))
256
+ provider.credentials if provider.credentials.set?
240
257
  end
241
258
  end
242
259
 
@@ -273,6 +290,22 @@ module Aws
273
290
  end
274
291
  end
275
292
 
293
+ # If any of the sso_ profile values are present, attempt to construct
294
+ # SSOCredentials
295
+ def sso_credentials_from_profile(cfg, profile)
296
+ if @parsed_config &&
297
+ (prof_config = cfg[profile]) &&
298
+ !(prof_config.keys & SSO_PROFILE_KEYS).empty?
299
+
300
+ SSOCredentials.new(
301
+ sso_start_url: prof_config['sso_start_url'],
302
+ sso_region: prof_config['sso_region'],
303
+ sso_account_id: prof_config['sso_account_id'],
304
+ sso_role_name: prof_config['sso_role_name']
305
+ )
306
+ end
307
+ end
308
+
276
309
  def credentials_from_profile(prof_config)
277
310
  creds = Credentials.new(
278
311
  prof_config['aws_access_key_id'],
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ # An auto-refreshing credential provider that works by assuming a
5
+ # role via {Aws::SSO::Client#get_role_credentials} using a cached access
6
+ # token. This class does NOT implement the SSO login token flow - tokens
7
+ # must generated and refreshed separately by running `aws login` with the
8
+ # correct profile.
9
+ #
10
+ # For more background on AWS SSO see the official
11
+ # [what is SSO](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html]
12
+ # page.
13
+ #
14
+ # ## Refreshing Credentials from SSO
15
+ #
16
+ # The `SSOCredentials` will auto-refresh the AWS credentials from SSO. In
17
+ # addition to AWS credentials expiring after a given amount of time, the
18
+ # access token generated and cached from `aws login` will also expire.
19
+ # Once this token expires, it will not be usable to refresh AWS credentials,
20
+ # and another token will be needed. The SDK does not manage refreshing of
21
+ # the token value, but this can be done by running `aws login` with the
22
+ # correct profile.
23
+ class SSOCredentials
24
+
25
+ include CredentialProvider
26
+ include RefreshingCredentials
27
+
28
+ SSO_REQUIRED_OPTS = [:sso_account_id, :sso_region, :sso_role_name, :sso_start_url].freeze
29
+
30
+ SSO_LOGIN_GUIDANCE = 'The SSO session associated with this profile has '\
31
+ 'expired or is otherwise invalid. To refresh this SSO session run '\
32
+ 'aws sso login with the corresponding profile.'.freeze
33
+
34
+ # @option options [required, String] :sso_account_id The AWS account ID
35
+ # that temporary AWS credentials will be resolved for
36
+ #
37
+ # @option options [required, String] :sso_region The AWS region where the
38
+ # SSO directory for the given sso_start_url is hosted.
39
+ #
40
+ # @option options [required, String] :sso_role_name The corresponding
41
+ # IAM role in the AWS account that temporary AWS credentials
42
+ # will be resolved for.
43
+ #
44
+ # @option options [required, String] :sso_start_url The start URL is
45
+ # provided by the SSO service via the console and is the URL used to
46
+ # login to the SSO directory. This is also sometimes referred to as
47
+ # the "User Portal URL"
48
+
49
+ # @option options [SSO::Client] :client Optional `SSO::Client`. If not
50
+ # provided, a client will be constructed.
51
+ def initialize(options = {})
52
+
53
+ missing_keys = SSO_REQUIRED_OPTS.select { |k| options[k].nil? }
54
+ unless missing_keys.empty?
55
+ raise ArgumentError, "Missing required keys: #{missing_keys}"
56
+ end
57
+
58
+ @sso_start_url = options.delete(:sso_start_url)
59
+ @sso_region = options.delete(:sso_region)
60
+ @sso_role_name = options.delete(:sso_role_name)
61
+ @sso_account_id = options.delete(:sso_account_id)
62
+
63
+ # validate we can read the token file
64
+ read_cached_token
65
+
66
+ options[:region] = @sso_region
67
+ options[:credentials] = nil
68
+ @client = options[:client] || SSO::Client.new(options)
69
+ super
70
+ end
71
+
72
+ # @return [STS::Client]
73
+ attr_reader :client
74
+
75
+ private
76
+
77
+ def read_cached_token
78
+ cached_token = Json.load(File.read(sso_cache_file))
79
+ # validation
80
+ unless cached_token['accessToken'] && cached_token['expiresAt']
81
+ raise ArgumentError, 'Missing required field(s)'
82
+ end
83
+ expires_at = DateTime.parse(cached_token['expiresAt'])
84
+ if expires_at < DateTime.now
85
+ raise ArgumentError, 'Cached SSO Token is expired.'
86
+ end
87
+ cached_token
88
+ rescue Aws::Json::ParseError, ArgumentError
89
+ raise Errors::InvalidSSOCredentials, SSO_LOGIN_GUIDANCE
90
+ end
91
+
92
+ def refresh
93
+ cached_token = read_cached_token
94
+ c = @client.get_role_credentials(
95
+ account_id: @sso_account_id,
96
+ role_name: @sso_role_name,
97
+ access_token: cached_token['accessToken']
98
+ ).role_credentials
99
+
100
+ @credentials = Credentials.new(
101
+ c.access_key_id,
102
+ c.secret_access_key,
103
+ c.session_token
104
+ )
105
+ @expiration = c.expiration
106
+ end
107
+
108
+ def sso_cache_file
109
+ start_url_sha1 = OpenSSL::Digest::SHA1.hexdigest(@sso_start_url.encode('utf-8'))
110
+ File.join(Dir.home, '.aws', 'sso', 'cache', "#{start_url_sha1}.json")
111
+ rescue ArgumentError
112
+ # Dir.home raises ArgumentError when ENV['home'] is not set
113
+ raise ArgumentError, "Unable to load sso_cache_file: ENV['HOME'] is not set."
114
+ end
115
+ end
116
+ end