aws-sdk-core 3.131.3 → 3.176.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +330 -1
- data/VERSION +1 -1
- data/lib/aws-defaults/default_configuration.rb +4 -4
- data/lib/aws-sdk-core/arn.rb +13 -0
- data/lib/aws-sdk-core/binary/encode_handler.rb +12 -1
- data/lib/aws-sdk-core/credential_provider.rb +3 -0
- data/lib/aws-sdk-core/credential_provider_chain.rb +8 -5
- data/lib/aws-sdk-core/ecs_credentials.rb +111 -53
- data/lib/aws-sdk-core/endpoints/condition.rb +41 -0
- data/lib/aws-sdk-core/endpoints/endpoint.rb +17 -0
- data/lib/aws-sdk-core/endpoints/endpoint_rule.rb +75 -0
- data/lib/aws-sdk-core/endpoints/error_rule.rb +42 -0
- data/lib/aws-sdk-core/endpoints/function.rb +80 -0
- data/lib/aws-sdk-core/endpoints/matchers.rb +127 -0
- data/lib/aws-sdk-core/endpoints/reference.rb +31 -0
- data/lib/aws-sdk-core/endpoints/rule.rb +25 -0
- data/lib/aws-sdk-core/endpoints/rule_set.rb +52 -0
- data/lib/aws-sdk-core/endpoints/rules_provider.rb +37 -0
- data/lib/aws-sdk-core/endpoints/templater.rb +58 -0
- data/lib/aws-sdk-core/endpoints/tree_rule.rb +45 -0
- data/lib/aws-sdk-core/endpoints/url.rb +60 -0
- data/lib/aws-sdk-core/endpoints.rb +78 -0
- data/lib/aws-sdk-core/errors.rb +13 -0
- data/lib/aws-sdk-core/json/error_handler.rb +20 -1
- data/lib/aws-sdk-core/log/formatter.rb +6 -0
- data/lib/aws-sdk-core/pageable_response.rb +10 -1
- data/lib/aws-sdk-core/plugins/bearer_authorization.rb +67 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +1 -1
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +24 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +6 -2
- data/lib/aws-sdk-core/plugins/recursion_detection.rb +14 -3
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +5 -0
- data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +2 -1
- data/lib/aws-sdk-core/plugins/sign.rb +201 -0
- data/lib/aws-sdk-core/plugins/signature_v2.rb +1 -0
- data/lib/aws-sdk-core/plugins/signature_v4.rb +13 -7
- data/lib/aws-sdk-core/plugins/user_agent.rb +117 -14
- data/lib/aws-sdk-core/refreshing_credentials.rb +0 -6
- data/lib/aws-sdk-core/refreshing_token.rb +71 -0
- data/lib/aws-sdk-core/rest/request/headers.rb +2 -6
- data/lib/aws-sdk-core/shared_config.rb +78 -6
- data/lib/aws-sdk-core/sso_credentials.rb +80 -45
- data/lib/aws-sdk-core/sso_token_provider.rb +135 -0
- data/lib/aws-sdk-core/static_token_provider.rb +14 -0
- data/lib/aws-sdk-core/structure.rb +6 -4
- data/lib/aws-sdk-core/token.rb +31 -0
- data/lib/aws-sdk-core/token_provider.rb +15 -0
- data/lib/aws-sdk-core/token_provider_chain.rb +51 -0
- data/lib/aws-sdk-core/waiters/poller.rb +3 -1
- data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
- data/lib/aws-sdk-core.rb +14 -0
- data/lib/aws-sdk-sso/client.rb +56 -11
- data/lib/aws-sdk-sso/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-sso/endpoint_provider.rb +51 -0
- data/lib/aws-sdk-sso/endpoints.rb +72 -0
- data/lib/aws-sdk-sso/plugins/endpoints.rb +76 -0
- data/lib/aws-sdk-sso/types.rb +8 -43
- data/lib/aws-sdk-sso.rb +5 -1
- data/lib/aws-sdk-ssooidc/client.rb +611 -0
- data/lib/aws-sdk-ssooidc/client_api.rb +216 -0
- data/lib/aws-sdk-ssooidc/customizations.rb +1 -0
- data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +51 -0
- data/lib/aws-sdk-ssooidc/endpoints.rb +58 -0
- data/lib/aws-sdk-ssooidc/errors.rb +290 -0
- data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +74 -0
- data/lib/aws-sdk-ssooidc/resource.rb +26 -0
- data/lib/aws-sdk-ssooidc/types.rb +502 -0
- data/lib/aws-sdk-ssooidc.rb +59 -0
- data/lib/aws-sdk-sts/client.rb +263 -243
- data/lib/aws-sdk-sts/endpoint_parameters.rb +78 -0
- data/lib/aws-sdk-sts/endpoint_provider.rb +112 -0
- data/lib/aws-sdk-sts/endpoints.rb +136 -0
- data/lib/aws-sdk-sts/plugins/endpoints.rb +84 -0
- data/lib/aws-sdk-sts/presigner.rb +13 -15
- data/lib/aws-sdk-sts/types.rb +87 -195
- data/lib/aws-sdk-sts.rb +5 -1
- data/lib/seahorse/client/async_base.rb +0 -1
- data/lib/seahorse/client/configuration.rb +2 -2
- data/lib/seahorse/client/h2/connection.rb +12 -11
- data/lib/seahorse/client/plugins/request_callback.rb +9 -9
- data/lib/seahorse/util.rb +4 -0
- metadata +47 -6
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'aws-sigv4'
|
|
4
|
+
|
|
5
|
+
module Aws
|
|
6
|
+
module Plugins
|
|
7
|
+
# @api private
|
|
8
|
+
class Sign < Seahorse::Client::Plugin
|
|
9
|
+
# These once had defaults. But now they are used as overrides to
|
|
10
|
+
# new endpoint and auth resolution.
|
|
11
|
+
option(:sigv4_signer)
|
|
12
|
+
option(:sigv4_name)
|
|
13
|
+
option(:sigv4_region)
|
|
14
|
+
option(:unsigned_operations, default: [])
|
|
15
|
+
|
|
16
|
+
supported_auth_types = %w[sigv4 bearer none]
|
|
17
|
+
supported_auth_types += ['sigv4a'] if Aws::Sigv4::Signer.use_crt?
|
|
18
|
+
SUPPORTED_AUTH_TYPES = supported_auth_types.freeze
|
|
19
|
+
|
|
20
|
+
def add_handlers(handlers, cfg)
|
|
21
|
+
operations = cfg.api.operation_names - cfg.unsigned_operations
|
|
22
|
+
handlers.add(Handler, step: :sign, operations: operations)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
# Return a signer with the `sign(context)` method
|
|
27
|
+
def self.signer_for(auth_scheme, config, region_override = nil)
|
|
28
|
+
case auth_scheme['name']
|
|
29
|
+
when 'sigv4', 'sigv4a'
|
|
30
|
+
SignatureV4.new(auth_scheme, config, region_override)
|
|
31
|
+
when 'bearer'
|
|
32
|
+
Bearer.new
|
|
33
|
+
else
|
|
34
|
+
NullSigner.new
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Handler < Seahorse::Client::Handler
|
|
39
|
+
def call(context)
|
|
40
|
+
# Skip signing if using sigv2 signing from s3_signer in S3
|
|
41
|
+
unless v2_signing?(context.config)
|
|
42
|
+
signer = Sign.signer_for(
|
|
43
|
+
context[:auth_scheme],
|
|
44
|
+
context.config,
|
|
45
|
+
context[:sigv4_region]
|
|
46
|
+
)
|
|
47
|
+
signer.sign(context)
|
|
48
|
+
end
|
|
49
|
+
@handler.call(context)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def v2_signing?(config)
|
|
55
|
+
# 's3' is legacy signing, 'v4' is default
|
|
56
|
+
config.respond_to?(:signature_version) &&
|
|
57
|
+
config.signature_version == 's3'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @api private
|
|
62
|
+
class Bearer
|
|
63
|
+
def initialize
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def sign(context)
|
|
67
|
+
if context.http_request.endpoint.scheme != 'https'
|
|
68
|
+
raise ArgumentError,
|
|
69
|
+
'Unable to use bearer authorization on non https endpoint.'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
token_provider = context.config.token_provider
|
|
73
|
+
|
|
74
|
+
raise Errors::MissingBearerTokenError unless token_provider&.set?
|
|
75
|
+
|
|
76
|
+
context.http_request.headers['Authorization'] =
|
|
77
|
+
"Bearer #{token_provider.token.token}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def presign_url(*args)
|
|
81
|
+
raise ArgumentError, 'Bearer auth does not support presigned urls'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def sign_event(*args)
|
|
85
|
+
raise ArgumentError, 'Bearer auth does not support event signing'
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @api private
|
|
90
|
+
class SignatureV4
|
|
91
|
+
def initialize(auth_scheme, config, region_override = nil)
|
|
92
|
+
scheme_name = auth_scheme['name']
|
|
93
|
+
|
|
94
|
+
unless %w[sigv4 sigv4a].include?(scheme_name)
|
|
95
|
+
raise ArgumentError,
|
|
96
|
+
"Expected sigv4 or sigv4a auth scheme, got #{scheme_name}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
region = if scheme_name == 'sigv4a'
|
|
100
|
+
auth_scheme['signingRegionSet'].first
|
|
101
|
+
else
|
|
102
|
+
auth_scheme['signingRegion']
|
|
103
|
+
end
|
|
104
|
+
begin
|
|
105
|
+
@signer = Aws::Sigv4::Signer.new(
|
|
106
|
+
service: config.sigv4_name || auth_scheme['signingName'],
|
|
107
|
+
region: region_override || config.sigv4_region || region,
|
|
108
|
+
credentials_provider: config.credentials,
|
|
109
|
+
signing_algorithm: scheme_name.to_sym,
|
|
110
|
+
uri_escape_path: !!!auth_scheme['disableDoubleEncoding'],
|
|
111
|
+
normalize_path: !!!auth_scheme['disableNormalizePath'],
|
|
112
|
+
unsigned_headers: %w[content-length user-agent x-amzn-trace-id]
|
|
113
|
+
)
|
|
114
|
+
rescue Aws::Sigv4::Errors::MissingCredentialsError
|
|
115
|
+
raise Aws::Errors::MissingCredentialsError
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def sign(context)
|
|
120
|
+
req = context.http_request
|
|
121
|
+
|
|
122
|
+
apply_authtype(context, req)
|
|
123
|
+
reset_signature(req)
|
|
124
|
+
apply_clock_skew(context, req)
|
|
125
|
+
|
|
126
|
+
# compute the signature
|
|
127
|
+
begin
|
|
128
|
+
signature = @signer.sign_request(
|
|
129
|
+
http_method: req.http_method,
|
|
130
|
+
url: req.endpoint,
|
|
131
|
+
headers: req.headers,
|
|
132
|
+
body: req.body
|
|
133
|
+
)
|
|
134
|
+
rescue Aws::Sigv4::Errors::MissingCredentialsError
|
|
135
|
+
# Necessary for when credentials is explicitly set to nil
|
|
136
|
+
raise Aws::Errors::MissingCredentialsError
|
|
137
|
+
end
|
|
138
|
+
# apply signature headers
|
|
139
|
+
req.headers.update(signature.headers)
|
|
140
|
+
|
|
141
|
+
# add request metadata with signature components for debugging
|
|
142
|
+
context[:canonical_request] = signature.canonical_request
|
|
143
|
+
context[:string_to_sign] = signature.string_to_sign
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def presign_url(*args)
|
|
147
|
+
@signer.presign_url(*args)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def sign_event(*args)
|
|
151
|
+
@signer.sign_event(*args)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def apply_authtype(context, req)
|
|
157
|
+
if context.operation['authtype'].eql?('v4-unsigned-body') &&
|
|
158
|
+
req.endpoint.scheme.eql?('https')
|
|
159
|
+
req.headers['X-Amz-Content-Sha256'] ||= 'UNSIGNED-PAYLOAD'
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def reset_signature(req)
|
|
164
|
+
# in case this request is being re-signed
|
|
165
|
+
req.headers.delete('Authorization')
|
|
166
|
+
req.headers.delete('X-Amz-Security-Token')
|
|
167
|
+
req.headers.delete('X-Amz-Date')
|
|
168
|
+
req.headers.delete('x-Amz-Region-Set')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def apply_clock_skew(context, req)
|
|
172
|
+
if context.config.respond_to?(:clock_skew) &&
|
|
173
|
+
context.config.clock_skew &&
|
|
174
|
+
context.config.correct_clock_skew
|
|
175
|
+
|
|
176
|
+
endpoint = context.http_request.endpoint
|
|
177
|
+
skew = context.config.clock_skew.clock_correction(endpoint)
|
|
178
|
+
if skew.abs.positive?
|
|
179
|
+
req.headers['X-Amz-Date'] =
|
|
180
|
+
(Time.now.utc + skew).strftime('%Y%m%dT%H%M%SZ')
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# @api private
|
|
188
|
+
class NullSigner
|
|
189
|
+
|
|
190
|
+
def sign(context)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def presign_url(*args)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def sign_event(*args)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -5,8 +5,11 @@ require 'aws-sigv4'
|
|
|
5
5
|
module Aws
|
|
6
6
|
module Plugins
|
|
7
7
|
# @api private
|
|
8
|
+
# Necessary to exist after endpoints 2.0
|
|
8
9
|
class SignatureV4 < Seahorse::Client::Plugin
|
|
9
10
|
|
|
11
|
+
V4_AUTH = %w[v4 v4-unsigned-payload v4-unsigned-body]
|
|
12
|
+
|
|
10
13
|
option(:sigv4_signer) do |cfg|
|
|
11
14
|
SignatureV4.build_signer(cfg)
|
|
12
15
|
end
|
|
@@ -32,13 +35,16 @@ module Aws
|
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
option(:unsigned_operations) do |cfg|
|
|
35
|
-
cfg.api.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
if cfg.api.metadata['signatureVersion'] == 'v4'
|
|
39
|
+
# select operations where authtype is set and is not v4
|
|
40
|
+
cfg.api.operation_names.select do |o|
|
|
41
|
+
cfg.api.operation(o)['authtype'] && !V4_AUTH.include?(cfg.api.operation(o)['authtype'])
|
|
42
|
+
end
|
|
43
|
+
else # service is not v4 auth
|
|
44
|
+
# select all operations where authtype is not v4
|
|
45
|
+
# (includes operations with no explicit authtype)
|
|
46
|
+
cfg.api.operation_names.select do |o|
|
|
47
|
+
!V4_AUTH.include?(cfg.api.operation(o)['authtype'])
|
|
42
48
|
end
|
|
43
49
|
end
|
|
44
50
|
end
|
|
@@ -4,7 +4,31 @@ module Aws
|
|
|
4
4
|
module Plugins
|
|
5
5
|
# @api private
|
|
6
6
|
class UserAgent < Seahorse::Client::Plugin
|
|
7
|
+
# @api private
|
|
7
8
|
option(:user_agent_suffix)
|
|
9
|
+
# @api private
|
|
10
|
+
option(:user_agent_frameworks, default: [])
|
|
11
|
+
|
|
12
|
+
option(
|
|
13
|
+
:sdk_ua_app_id,
|
|
14
|
+
doc_type: 'String',
|
|
15
|
+
docstring: <<-DOCS) do |cfg|
|
|
16
|
+
A unique and opaque application ID that is appended to the
|
|
17
|
+
User-Agent header as app/<sdk_ua_app_id>. It should have a
|
|
18
|
+
maximum length of 50.
|
|
19
|
+
DOCS
|
|
20
|
+
app_id = ENV['AWS_SDK_UA_APP_ID']
|
|
21
|
+
app_id ||= Aws.shared_config.sdk_ua_app_id(profile: cfg.profile)
|
|
22
|
+
app_id
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.feature(feature, &block)
|
|
26
|
+
Thread.current[:aws_sdk_core_user_agent_feature] ||= []
|
|
27
|
+
Thread.current[:aws_sdk_core_user_agent_feature] << "ft/#{feature}"
|
|
28
|
+
block.call
|
|
29
|
+
ensure
|
|
30
|
+
Thread.current[:aws_sdk_core_user_agent_feature].pop
|
|
31
|
+
end
|
|
8
32
|
|
|
9
33
|
# @api private
|
|
10
34
|
class Handler < Seahorse::Client::Handler
|
|
@@ -14,33 +38,112 @@ module Aws
|
|
|
14
38
|
end
|
|
15
39
|
|
|
16
40
|
def set_user_agent(context)
|
|
17
|
-
|
|
41
|
+
context.http_request.headers['User-Agent'] = UserAgent.new(context).to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class UserAgent
|
|
45
|
+
def initialize(context)
|
|
46
|
+
@context = context
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def to_s
|
|
50
|
+
ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
|
|
51
|
+
ua += ' ua/2.0'
|
|
52
|
+
ua += " #{api_metadata}" if api_metadata
|
|
53
|
+
ua += " #{os_metadata}"
|
|
54
|
+
ua += " #{language_metadata}"
|
|
55
|
+
ua += " #{env_metadata}" if env_metadata
|
|
56
|
+
ua += " #{config_metadata}" if config_metadata
|
|
57
|
+
ua += " #{app_id}" if app_id
|
|
58
|
+
ua += " #{feature_metadata}" if feature_metadata
|
|
59
|
+
ua += " #{framework_metadata}" if framework_metadata
|
|
60
|
+
if @context.config.user_agent_suffix
|
|
61
|
+
ua += " #{@context.config.user_agent_suffix}"
|
|
62
|
+
end
|
|
63
|
+
ua.strip
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
18
67
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
68
|
+
# Used to be gem_name/gem_version
|
|
69
|
+
def api_metadata
|
|
70
|
+
service_id = @context.config.api.metadata['serviceId']
|
|
71
|
+
return unless service_id
|
|
72
|
+
|
|
73
|
+
service_id = service_id.gsub(' ', '_').downcase
|
|
74
|
+
gem_version = @context[:gem_version]
|
|
75
|
+
"api/#{service_id}##{gem_version}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Used to be RUBY_PLATFORM
|
|
79
|
+
def os_metadata
|
|
80
|
+
os =
|
|
81
|
+
case RbConfig::CONFIG['host_os']
|
|
82
|
+
when /mac|darwin/
|
|
83
|
+
'macos'
|
|
84
|
+
when /linux|cygwin/
|
|
85
|
+
'linux'
|
|
86
|
+
when /mingw|mswin/
|
|
87
|
+
'windows'
|
|
88
|
+
else
|
|
89
|
+
'other'
|
|
90
|
+
end
|
|
91
|
+
metadata = "os/#{os}"
|
|
92
|
+
local_version = Gem::Platform.local.version
|
|
93
|
+
metadata += "##{local_version}" if local_version
|
|
94
|
+
metadata += " md/#{RbConfig::CONFIG['host_cpu']}"
|
|
95
|
+
metadata
|
|
23
96
|
end
|
|
24
97
|
|
|
25
|
-
|
|
98
|
+
# Used to be RUBY_ENGINE/RUBY_VERSION
|
|
99
|
+
def language_metadata
|
|
100
|
+
"lang/#{RUBY_ENGINE}##{RUBY_ENGINE_VERSION} md/#{RUBY_VERSION}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def env_metadata
|
|
104
|
+
return unless (execution_env = ENV['AWS_EXECUTION_ENV'])
|
|
105
|
+
|
|
106
|
+
"exec-env/#{execution_env}"
|
|
107
|
+
end
|
|
26
108
|
|
|
27
|
-
|
|
28
|
-
|
|
109
|
+
def config_metadata
|
|
110
|
+
"cfg/retry-mode##{@context.config.retry_mode}"
|
|
29
111
|
end
|
|
30
112
|
|
|
31
|
-
|
|
32
|
-
|
|
113
|
+
def app_id
|
|
114
|
+
return unless (app_id = @context.config.sdk_ua_app_id)
|
|
115
|
+
|
|
116
|
+
# Sanitize and only allow these characters
|
|
117
|
+
app_id = app_id.gsub(/[^!#$%&'*+\-.^_`|~0-9A-Za-z]/, '-')
|
|
118
|
+
"app/#{app_id}"
|
|
33
119
|
end
|
|
34
120
|
|
|
35
|
-
|
|
36
|
-
|
|
121
|
+
def feature_metadata
|
|
122
|
+
return unless Thread.current[:aws_sdk_core_user_agent_feature]
|
|
123
|
+
|
|
124
|
+
Thread.current[:aws_sdk_core_user_agent_feature].join(' ')
|
|
37
125
|
end
|
|
38
126
|
|
|
39
|
-
|
|
127
|
+
def framework_metadata
|
|
128
|
+
if (frameworks_cfg = @context.config.user_agent_frameworks).empty?
|
|
129
|
+
return
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Frameworks may be aws-record, aws-sdk-rails, etc.
|
|
133
|
+
regex = /gems\/(?<name>#{frameworks_cfg.join('|')})-(?<version>\d+\.\d+\.\d+)/.freeze
|
|
134
|
+
frameworks = {}
|
|
135
|
+
Kernel.caller.each do |line|
|
|
136
|
+
match = line.match(regex)
|
|
137
|
+
next unless match
|
|
138
|
+
|
|
139
|
+
frameworks[match[:name]] = match[:version]
|
|
140
|
+
end
|
|
141
|
+
frameworks.map { |n, v| "lib/#{n}##{v}" }.join(' ')
|
|
142
|
+
end
|
|
40
143
|
end
|
|
41
144
|
end
|
|
42
145
|
|
|
43
|
-
handler(Handler)
|
|
146
|
+
handler(Handler, priority: 1)
|
|
44
147
|
end
|
|
45
148
|
end
|
|
46
149
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'thread'
|
|
4
|
+
|
|
5
|
+
module Aws
|
|
6
|
+
|
|
7
|
+
# Module/mixin used by token provider classes that can be refreshed. This
|
|
8
|
+
# provides basic refresh logic in a thread-safe manner. Classes mixing in
|
|
9
|
+
# this module are expected to implement a #refresh method that populates
|
|
10
|
+
# the following instance variable:
|
|
11
|
+
#
|
|
12
|
+
# * `@token` [Token] - {Aws::Token} object with the `expiration` and `token`
|
|
13
|
+
# fields set.
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
module RefreshingToken
|
|
17
|
+
|
|
18
|
+
def initialize(options = {})
|
|
19
|
+
@mutex = Mutex.new
|
|
20
|
+
@before_refresh = options.delete(:before_refresh) if Hash === options
|
|
21
|
+
|
|
22
|
+
@before_refresh.call(self) if @before_refresh
|
|
23
|
+
refresh
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [Token]
|
|
27
|
+
def token
|
|
28
|
+
refresh_if_near_expiration
|
|
29
|
+
@token
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [Time,nil]
|
|
33
|
+
def expiration
|
|
34
|
+
refresh_if_near_expiration
|
|
35
|
+
@expiration
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Refresh token.
|
|
39
|
+
# @return [void]
|
|
40
|
+
def refresh!
|
|
41
|
+
@mutex.synchronize do
|
|
42
|
+
@before_refresh.call(self) if @before_refresh
|
|
43
|
+
refresh
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Refreshes token if it is within
|
|
50
|
+
# 5 minutes of expiration.
|
|
51
|
+
def refresh_if_near_expiration
|
|
52
|
+
if near_expiration?
|
|
53
|
+
@mutex.synchronize do
|
|
54
|
+
if near_expiration?
|
|
55
|
+
@before_refresh.call(self) if @before_refresh
|
|
56
|
+
refresh
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def near_expiration?
|
|
63
|
+
if @token && @token.expiration
|
|
64
|
+
# are we within 5 minutes of expiration?
|
|
65
|
+
(Time.now.to_i + 5 * 60) > @token.expiration.to_i
|
|
66
|
+
else
|
|
67
|
+
true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -53,12 +53,8 @@ module Aws
|
|
|
53
53
|
return if !value || value.empty?
|
|
54
54
|
headers[ref.location_name] = value
|
|
55
55
|
.compact
|
|
56
|
-
.map { |s| escape_header_list_string(s.to_s) }
|
|
57
|
-
.join(
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def escape_header_list_string(s)
|
|
61
|
-
(s.include?('"') || s.include?(",")) ? "\"#{s.gsub('"', '\"')}\"" : s
|
|
56
|
+
.map { |s| Seahorse::Util.escape_header_list_string(s.to_s) }
|
|
57
|
+
.join(',')
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
def apply_header_map(headers, ref, values)
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
module Aws
|
|
4
4
|
# @api private
|
|
5
5
|
class SharedConfig
|
|
6
|
-
|
|
6
|
+
SSO_CREDENTIAL_PROFILE_KEYS = %w[sso_account_id sso_role_name].freeze
|
|
7
|
+
SSO_PROFILE_KEYS = %w[sso_session sso_start_url sso_region sso_account_id sso_role_name].freeze
|
|
8
|
+
SSO_TOKEN_PROFILE_KEYS = %w[sso_session].freeze
|
|
9
|
+
SSO_SESSION_KEYS = %w[sso_region sso_start_url].freeze
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
# @return [String]
|
|
9
13
|
attr_reader :credentials_path
|
|
@@ -51,10 +55,12 @@ module Aws
|
|
|
51
55
|
@config_enabled = options[:config_enabled]
|
|
52
56
|
@credentials_path = options[:credentials_path] ||
|
|
53
57
|
determine_credentials_path
|
|
58
|
+
@credentials_path = File.expand_path(@credentials_path) if @credentials_path
|
|
54
59
|
@parsed_credentials = {}
|
|
55
60
|
load_credentials_file if loadable?(@credentials_path)
|
|
56
61
|
if @config_enabled
|
|
57
62
|
@config_path = options[:config_path] || determine_config_path
|
|
63
|
+
@config_path = File.expand_path(@config_path) if @config_path
|
|
58
64
|
load_config_file if loadable?(@config_path)
|
|
59
65
|
end
|
|
60
66
|
end
|
|
@@ -149,6 +155,18 @@ module Aws
|
|
|
149
155
|
credentials
|
|
150
156
|
end
|
|
151
157
|
|
|
158
|
+
# Attempts to load from shared config or shared credentials file.
|
|
159
|
+
# Will always attempt first to load from the shared credentials
|
|
160
|
+
# file, if present.
|
|
161
|
+
def sso_token_from_config(opts = {})
|
|
162
|
+
p = opts[:profile] || @profile_name
|
|
163
|
+
token = sso_token_from_profile(@parsed_credentials, p)
|
|
164
|
+
if @parsed_config
|
|
165
|
+
token ||= sso_token_from_profile(@parsed_config, p)
|
|
166
|
+
end
|
|
167
|
+
token
|
|
168
|
+
end
|
|
169
|
+
|
|
152
170
|
# Add an accessor method (similar to attr_reader) to return a configuration value
|
|
153
171
|
# Uses the get_config_value below to control where
|
|
154
172
|
# values are loaded from
|
|
@@ -179,7 +197,8 @@ module Aws
|
|
|
179
197
|
:s3_use_arn_region,
|
|
180
198
|
:s3_us_east_1_regional_endpoint,
|
|
181
199
|
:s3_disable_multiregion_access_points,
|
|
182
|
-
:defaults_mode
|
|
200
|
+
:defaults_mode,
|
|
201
|
+
:sdk_ua_app_id
|
|
183
202
|
)
|
|
184
203
|
|
|
185
204
|
private
|
|
@@ -314,13 +333,66 @@ module Aws
|
|
|
314
333
|
def sso_credentials_from_profile(cfg, profile)
|
|
315
334
|
if @parsed_config &&
|
|
316
335
|
(prof_config = cfg[profile]) &&
|
|
317
|
-
!(prof_config.keys &
|
|
336
|
+
!(prof_config.keys & SSO_CREDENTIAL_PROFILE_KEYS).empty?
|
|
337
|
+
|
|
338
|
+
if sso_session_name = prof_config['sso_session']
|
|
339
|
+
sso_session = cfg["sso-session #{sso_session_name}"]
|
|
340
|
+
unless sso_session
|
|
341
|
+
raise ArgumentError,
|
|
342
|
+
"sso-session #{sso_session_name} must be defined in the config file. " \
|
|
343
|
+
"Referenced by profile #{profile}"
|
|
344
|
+
end
|
|
345
|
+
sso_region = sso_session['sso_region']
|
|
346
|
+
sso_start_url = sso_session['sso_start_url']
|
|
347
|
+
|
|
348
|
+
# validate sso_region and sso_start_url don't conflict if set on profile and session
|
|
349
|
+
if prof_config['sso_region'] && prof_config['sso_region'] != sso_region
|
|
350
|
+
raise ArgumentError,
|
|
351
|
+
"sso-session #{sso_session_name}'s sso_region (#{sso_region}) " \
|
|
352
|
+
"does not match the profile #{profile}'s sso_region (#{prof_config['sso_region']}'"
|
|
353
|
+
end
|
|
354
|
+
if prof_config['sso_start_url'] && prof_config['sso_start_url'] != sso_start_url
|
|
355
|
+
raise ArgumentError,
|
|
356
|
+
"sso-session #{sso_session_name}'s sso_start_url (#{sso_start_url}) " \
|
|
357
|
+
"does not match the profile #{profile}'s sso_start_url (#{prof_config['sso_start_url']}'"
|
|
358
|
+
end
|
|
359
|
+
else
|
|
360
|
+
sso_region = prof_config['sso_region']
|
|
361
|
+
sso_start_url = prof_config['sso_start_url']
|
|
362
|
+
end
|
|
318
363
|
|
|
319
364
|
SSOCredentials.new(
|
|
320
|
-
sso_start_url: prof_config['sso_start_url'],
|
|
321
|
-
sso_region: prof_config['sso_region'],
|
|
322
365
|
sso_account_id: prof_config['sso_account_id'],
|
|
323
|
-
sso_role_name: prof_config['sso_role_name']
|
|
366
|
+
sso_role_name: prof_config['sso_role_name'],
|
|
367
|
+
sso_session: prof_config['sso_session'],
|
|
368
|
+
sso_region: sso_region,
|
|
369
|
+
sso_start_url: prof_config['sso_start_url']
|
|
370
|
+
)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# If the required sso_ profile values are present, attempt to construct
|
|
375
|
+
# SSOTokenProvider
|
|
376
|
+
def sso_token_from_profile(cfg, profile)
|
|
377
|
+
if @parsed_config &&
|
|
378
|
+
(prof_config = cfg[profile]) &&
|
|
379
|
+
!(prof_config.keys & SSO_TOKEN_PROFILE_KEYS).empty?
|
|
380
|
+
|
|
381
|
+
sso_session_name = prof_config['sso_session']
|
|
382
|
+
sso_session = cfg["sso-session #{sso_session_name}"]
|
|
383
|
+
unless sso_session
|
|
384
|
+
raise ArgumentError,
|
|
385
|
+
"sso-session #{sso_session_name} must be defined in the config file." \
|
|
386
|
+
"Referenced by profile #{profile}"
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
unless sso_session['sso_region']
|
|
390
|
+
raise ArgumentError, "sso-session #{sso_session_name} missing required parameter: sso_region"
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
SSOTokenProvider.new(
|
|
394
|
+
sso_session: sso_session_name,
|
|
395
|
+
sso_region: sso_session['sso_region']
|
|
324
396
|
)
|
|
325
397
|
end
|
|
326
398
|
end
|