aws-sdk-core 3.190.2 → 3.240.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +650 -0
- data/VERSION +1 -1
- data/lib/aws-defaults.rb +4 -1
- data/lib/aws-sdk-core/arn.rb +1 -3
- data/lib/aws-sdk-core/assume_role_credentials.rb +21 -13
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +16 -9
- data/lib/aws-sdk-core/binary/decode_handler.rb +3 -9
- data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
- data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
- data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
- data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
- data/lib/aws-sdk-core/cbor/decoder.rb +308 -0
- data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
- data/lib/aws-sdk-core/cbor.rb +53 -0
- data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
- data/lib/aws-sdk-core/client_stubs.rb +39 -58
- data/lib/aws-sdk-core/credential_provider.rb +5 -1
- data/lib/aws-sdk-core/credential_provider_chain.rb +101 -25
- data/lib/aws-sdk-core/credentials.rb +19 -6
- data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
- data/lib/aws-sdk-core/ecs_credentials.rb +16 -14
- data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
- data/lib/aws-sdk-core/endpoints/matchers.rb +8 -10
- data/lib/aws-sdk-core/endpoints.rb +101 -21
- data/lib/aws-sdk-core/error_handler.rb +46 -0
- data/lib/aws-sdk-core/errors.rb +16 -4
- data/lib/aws-sdk-core/event_emitter.rb +1 -17
- data/lib/aws-sdk-core/instance_profile_credentials.rb +148 -157
- data/lib/aws-sdk-core/json/builder.rb +8 -1
- data/lib/aws-sdk-core/json/error_handler.rb +29 -13
- data/lib/aws-sdk-core/json/handler.rb +6 -6
- data/lib/aws-sdk-core/json/json_engine.rb +3 -1
- data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
- data/lib/aws-sdk-core/json/parser.rb +6 -1
- data/lib/aws-sdk-core/json.rb +43 -14
- data/lib/aws-sdk-core/log/param_filter.rb +2 -2
- data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
- data/lib/aws-sdk-core/log.rb +10 -0
- data/lib/aws-sdk-core/login_credentials.rb +229 -0
- data/lib/aws-sdk-core/lru_cache.rb +75 -0
- data/lib/aws-sdk-core/pageable_response.rb +1 -1
- data/lib/aws-sdk-core/param_validator.rb +7 -2
- data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +347 -170
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -1
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +78 -56
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
- data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
- data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -8
- data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
- data/lib/aws-sdk-core/plugins/logging.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
- data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
- data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
- data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
- data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -25
- data/lib/aws-sdk-core/plugins/request_compression.rb +11 -2
- data/lib/aws-sdk-core/plugins/retry_errors.rb +12 -3
- data/lib/aws-sdk-core/plugins/sign.rb +42 -26
- data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
- data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
- data/lib/aws-sdk-core/plugins/stub_responses.rb +59 -9
- data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
- data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
- data/lib/aws-sdk-core/plugins/user_agent.rb +103 -26
- data/lib/aws-sdk-core/plugins.rb +39 -0
- data/lib/aws-sdk-core/process_credentials.rb +48 -29
- data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
- data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
- data/lib/aws-sdk-core/query/handler.rb +4 -4
- data/lib/aws-sdk-core/query/param_builder.rb +2 -2
- data/lib/aws-sdk-core/query.rb +2 -1
- data/lib/aws-sdk-core/refreshing_credentials.rb +8 -11
- data/lib/aws-sdk-core/resources.rb +8 -0
- data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
- data/lib/aws-sdk-core/rest/handler.rb +3 -4
- data/lib/aws-sdk-core/rest/request/body.rb +32 -5
- data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
- data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +23 -11
- data/lib/aws-sdk-core/rest/response/body.rb +15 -1
- data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
- data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
- data/lib/aws-sdk-core/rest.rb +1 -0
- data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
- data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
- data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
- data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
- data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
- data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
- data/lib/aws-sdk-core/rpc_v2.rb +69 -0
- data/lib/aws-sdk-core/shared_config.rb +108 -22
- data/lib/aws-sdk-core/shared_credentials.rb +1 -7
- data/lib/aws-sdk-core/sso_credentials.rb +5 -2
- data/lib/aws-sdk-core/static_token_provider.rb +1 -2
- data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
- data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
- data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
- data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
- data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
- data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
- data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
- data/lib/aws-sdk-core/stubbing.rb +22 -0
- data/lib/aws-sdk-core/telemetry/base.rb +177 -0
- data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
- data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
- data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
- data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
- data/lib/aws-sdk-core/telemetry.rb +78 -0
- data/lib/aws-sdk-core/token.rb +3 -3
- data/lib/aws-sdk-core/token_provider.rb +4 -0
- data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
- data/lib/aws-sdk-core/util.rb +41 -1
- data/lib/aws-sdk-core/waiters/poller.rb +10 -5
- data/lib/aws-sdk-core/xml/builder.rb +17 -9
- data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
- data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
- data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
- data/lib/aws-sdk-core/xml/parser.rb +2 -6
- data/lib/aws-sdk-core.rb +86 -107
- data/lib/aws-sdk-signin/client.rb +604 -0
- data/lib/aws-sdk-signin/client_api.rb +119 -0
- data/lib/aws-sdk-signin/customizations.rb +1 -0
- data/lib/aws-sdk-signin/endpoint_parameters.rb +69 -0
- data/lib/aws-sdk-signin/endpoint_provider.rb +59 -0
- data/lib/aws-sdk-signin/endpoints.rb +20 -0
- data/lib/aws-sdk-signin/errors.rb +122 -0
- data/lib/aws-sdk-signin/plugins/endpoints.rb +77 -0
- data/lib/aws-sdk-signin/resource.rb +26 -0
- data/lib/aws-sdk-signin/types.rb +299 -0
- data/lib/aws-sdk-signin.rb +63 -0
- data/lib/aws-sdk-sso/client.rb +189 -96
- data/lib/aws-sdk-sso/client_api.rb +7 -0
- data/lib/aws-sdk-sso/endpoint_parameters.rb +13 -10
- data/lib/aws-sdk-sso/endpoint_provider.rb +16 -20
- data/lib/aws-sdk-sso/endpoints.rb +2 -54
- data/lib/aws-sdk-sso/plugins/endpoints.rb +20 -20
- data/lib/aws-sdk-sso/types.rb +1 -0
- data/lib/aws-sdk-sso.rb +15 -11
- data/lib/aws-sdk-ssooidc/client.rb +293 -122
- data/lib/aws-sdk-ssooidc/client_api.rb +38 -0
- data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +13 -10
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +14 -18
- data/lib/aws-sdk-ssooidc/endpoints.rb +2 -54
- data/lib/aws-sdk-ssooidc/errors.rb +31 -0
- data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +20 -20
- data/lib/aws-sdk-ssooidc/types.rb +142 -29
- data/lib/aws-sdk-ssooidc.rb +15 -11
- data/lib/aws-sdk-sts/client.rb +529 -156
- data/lib/aws-sdk-sts/client_api.rb +108 -8
- data/lib/aws-sdk-sts/customizations.rb +5 -2
- data/lib/aws-sdk-sts/endpoint_parameters.rb +15 -14
- data/lib/aws-sdk-sts/endpoint_provider.rb +50 -55
- data/lib/aws-sdk-sts/endpoints.rb +2 -118
- data/lib/aws-sdk-sts/errors.rb +79 -0
- data/lib/aws-sdk-sts/plugins/endpoints.rb +20 -28
- data/lib/aws-sdk-sts/presigner.rb +2 -6
- data/lib/aws-sdk-sts/types.rb +344 -32
- data/lib/aws-sdk-sts.rb +15 -11
- data/lib/seahorse/client/async_base.rb +4 -5
- data/lib/seahorse/client/async_response.rb +19 -0
- data/lib/seahorse/client/base.rb +18 -21
- data/lib/seahorse/client/h2/connection.rb +18 -28
- data/lib/seahorse/client/h2/handler.rb +19 -3
- data/lib/seahorse/client/handler.rb +1 -1
- data/lib/seahorse/client/http/response.rb +1 -1
- data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
- data/lib/seahorse/client/net_http/handler.rb +21 -9
- data/lib/seahorse/client/networking_error.rb +1 -1
- data/lib/seahorse/client/plugin.rb +9 -0
- data/lib/seahorse/client/plugins/endpoint.rb +0 -1
- data/lib/seahorse/client/plugins/h2.rb +4 -4
- data/lib/seahorse/client/plugins/net_http.rb +57 -16
- data/lib/seahorse/client/request_context.rb +9 -2
- data/lib/seahorse/client/response.rb +2 -0
- data/lib/seahorse/model/shapes.rb +2 -2
- data/lib/seahorse/util.rb +2 -1
- data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
- data/sig/aws-sdk-core/client_stubs.rbs +10 -0
- data/sig/aws-sdk-core/errors.rbs +22 -0
- data/sig/aws-sdk-core/resources/collection.rbs +21 -0
- data/sig/aws-sdk-core/structure.rbs +4 -0
- data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
- data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
- data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
- data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
- data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
- data/sig/aws-sdk-core.rbs +7 -0
- data/sig/seahorse/client/async_base.rbs +18 -0
- data/sig/seahorse/client/base.rbs +25 -0
- data/sig/seahorse/client/handler_builder.rbs +16 -0
- data/sig/seahorse/client/response.rbs +61 -0
- metadata +117 -23
- /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
|
@@ -17,6 +17,8 @@ module Aws
|
|
|
17
17
|
|
|
18
18
|
# @param [String<JSON>] json
|
|
19
19
|
def parse(json, target = nil)
|
|
20
|
+
json = '{}' if json.empty?
|
|
21
|
+
|
|
20
22
|
parse_ref(@rules, Json.load(json), target)
|
|
21
23
|
end
|
|
22
24
|
|
|
@@ -69,6 +71,8 @@ module Aws
|
|
|
69
71
|
def map(ref, values, target = nil)
|
|
70
72
|
target = {} if target.nil?
|
|
71
73
|
values.each do |key, value|
|
|
74
|
+
next if value.nil?
|
|
75
|
+
|
|
72
76
|
target[key] = parse_ref(ref.shape.value, value)
|
|
73
77
|
end
|
|
74
78
|
target
|
|
@@ -85,6 +89,7 @@ module Aws
|
|
|
85
89
|
when TimestampShape then time(value)
|
|
86
90
|
when BlobShape then Base64.decode64(value)
|
|
87
91
|
when BooleanShape then value.to_s == 'true'
|
|
92
|
+
when FloatShape then Util.deserialize_number(value)
|
|
88
93
|
else value
|
|
89
94
|
end
|
|
90
95
|
end
|
|
@@ -93,7 +98,7 @@ module Aws
|
|
|
93
98
|
# @param [String, Integer] value
|
|
94
99
|
# @return [Time]
|
|
95
100
|
def time(value)
|
|
96
|
-
value.is_a?(Numeric) ? Time.at(value) :
|
|
101
|
+
value.is_a?(Numeric) ? Time.at(value) : Aws::Util.deserialize_time(value)
|
|
97
102
|
end
|
|
98
103
|
|
|
99
104
|
def flattened_list?(shape)
|
data/lib/aws-sdk-core/json.rb
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'json'
|
|
4
3
|
require_relative 'json/builder'
|
|
5
4
|
require_relative 'json/error_handler'
|
|
6
5
|
require_relative 'json/handler'
|
|
7
6
|
require_relative 'json/parser'
|
|
8
|
-
require_relative 'json/json_engine'
|
|
9
|
-
require_relative 'json/oj_engine'
|
|
10
7
|
|
|
11
8
|
module Aws
|
|
12
9
|
# @api private
|
|
@@ -21,29 +18,61 @@ module Aws
|
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
class << self
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
# @param [Symbol,Class] engine
|
|
22
|
+
# Must be one of the following values:
|
|
23
|
+
#
|
|
24
|
+
# * :oj
|
|
25
|
+
# * :json
|
|
26
|
+
#
|
|
27
|
+
def engine=(engine)
|
|
28
|
+
@engine = Class === engine ? engine : load_engine(engine)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Class] Returns the default engine.
|
|
32
|
+
# One of:
|
|
33
|
+
#
|
|
34
|
+
# * {OjEngine}
|
|
35
|
+
# * {JsonEngine}
|
|
36
|
+
#
|
|
37
|
+
def engine
|
|
38
|
+
set_default_engine unless @engine
|
|
39
|
+
@engine
|
|
26
40
|
end
|
|
27
41
|
|
|
28
|
-
def
|
|
29
|
-
load(
|
|
42
|
+
def load(json)
|
|
43
|
+
@engine.load(json)
|
|
30
44
|
end
|
|
31
45
|
|
|
32
46
|
def dump(value)
|
|
33
|
-
|
|
47
|
+
@engine.dump(value)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_default_engine
|
|
51
|
+
[:oj, :json].each do |name|
|
|
52
|
+
@engine ||= try_load_engine(name)
|
|
53
|
+
end
|
|
54
|
+
unless @engine
|
|
55
|
+
raise 'Unable to find a compatible json library. ' \
|
|
56
|
+
'Ensure that you have installed or added to your Gemfile one of ' \
|
|
57
|
+
'oj or json'
|
|
58
|
+
end
|
|
34
59
|
end
|
|
35
60
|
|
|
36
61
|
private
|
|
37
62
|
|
|
38
|
-
def
|
|
39
|
-
require
|
|
40
|
-
|
|
63
|
+
def load_engine(name)
|
|
64
|
+
require "aws-sdk-core/json/#{name}_engine"
|
|
65
|
+
const_name = name[0].upcase + name[1..-1] + 'Engine'
|
|
66
|
+
const_get(const_name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def try_load_engine(name)
|
|
70
|
+
load_engine(name)
|
|
41
71
|
rescue LoadError
|
|
42
|
-
|
|
72
|
+
false
|
|
43
73
|
end
|
|
44
74
|
end
|
|
45
75
|
|
|
46
|
-
|
|
47
|
-
ENGINE = select_engine
|
|
76
|
+
set_default_engine
|
|
48
77
|
end
|
|
49
78
|
end
|
|
@@ -55,14 +55,14 @@ module Aws
|
|
|
55
55
|
filtered[key] = if @enabled && filters.include?(key)
|
|
56
56
|
'[FILTERED]'
|
|
57
57
|
else
|
|
58
|
-
filter(value,
|
|
58
|
+
filter(value, value.class)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
filtered
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def filter_array(values, type)
|
|
65
|
-
values.map { |value| filter(value,
|
|
65
|
+
values.map { |value| filter(value, value.class) }
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
end
|
|
@@ -51,13 +51,17 @@ module Aws
|
|
|
51
51
|
when String then summarize_string(value)
|
|
52
52
|
when Hash then '{' + summarize_hash(value) + '}'
|
|
53
53
|
when Array then summarize_array(value)
|
|
54
|
-
when File then summarize_file(value
|
|
55
|
-
when Pathname then
|
|
54
|
+
when File then summarize_file(value)
|
|
55
|
+
when Pathname then summarize_filepath(value)
|
|
56
56
|
else value.inspect
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def summarize_file(
|
|
60
|
+
def summarize_file(file)
|
|
61
|
+
"#<File:#{file.path} (#{file.size} bytes)>"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def summarize_filepath(path)
|
|
61
65
|
"#<File:#{path} (#{File.size(path)} bytes)>"
|
|
62
66
|
end
|
|
63
67
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
# setup autoloading for Log module
|
|
5
|
+
module Log
|
|
6
|
+
autoload :Formatter, 'aws-sdk-core/log/formatter'
|
|
7
|
+
autoload :ParamFilter, 'aws-sdk-core/log/param_filter'
|
|
8
|
+
autoload :ParamFormatter, 'aws-sdk-core/log/param_formatter'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
# An auto-refreshing credential provider that retrieves credentials from
|
|
5
|
+
# a cached login token. This class does NOT implement the AWS Sign-In
|
|
6
|
+
# login flow - tokens must be generated separately by running `aws login`
|
|
7
|
+
# from the AWS CLI/AWS Tools for PowerShell with the correct profile.
|
|
8
|
+
# The {LoginCredentials} will auto-refresh the AWS credentials from AWS Sign-In.
|
|
9
|
+
#
|
|
10
|
+
# # You must first run aws login --profile your-login-profile
|
|
11
|
+
# login_credentials = Aws::LoginCredentials.new(login_session: 'my_login_session')
|
|
12
|
+
# ec2 = Aws::EC2::Client.new(credentials: login_credentials)
|
|
13
|
+
#
|
|
14
|
+
# If you omit the `:client` option, a new {Aws::Signin::Client} object will
|
|
15
|
+
# be constructed with additional options that were provided.
|
|
16
|
+
class LoginCredentials
|
|
17
|
+
include CredentialProvider
|
|
18
|
+
include RefreshingCredentials
|
|
19
|
+
|
|
20
|
+
# @option options [required, String] :login_session An opaque string
|
|
21
|
+
# used to determine the cache file location. This value can be found
|
|
22
|
+
# in the AWS config file which is set by the AWS CLI/AWS Tools for
|
|
23
|
+
# PowerShell automatically.
|
|
24
|
+
#
|
|
25
|
+
# @option options [Signin::Client] :client Optional `Signin::Client`.
|
|
26
|
+
# If not provided, a client will be constructed.
|
|
27
|
+
def initialize(options = {})
|
|
28
|
+
raise ArgumentError, 'Missing login_session' unless options[:login_session]
|
|
29
|
+
|
|
30
|
+
@login_session = options.delete(:login_session)
|
|
31
|
+
@client = options[:client]
|
|
32
|
+
unless @client
|
|
33
|
+
client_opts = options.reject { |key, _| CLIENT_EXCLUDE_OPTIONS.include?(key) }
|
|
34
|
+
@client = Signin::Client.new(client_opts.merge(credentials: nil))
|
|
35
|
+
end
|
|
36
|
+
@metrics = ['CREDENTIALS_LOGIN']
|
|
37
|
+
@async_refresh = true
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Signin::Client]
|
|
42
|
+
attr_reader :client
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def refresh
|
|
47
|
+
# First reload the token from disk to ensure it hasn't been refreshed externally
|
|
48
|
+
token_json = read_cached_token
|
|
49
|
+
update_creds(token_json['accessToken'])
|
|
50
|
+
return if @credentials && @expiration && !near_expiration?(sync_expiration_length)
|
|
51
|
+
|
|
52
|
+
# Using OpenSSL 3.6.0 may result in errors like "certificate verify failed (unable to get certificate CRL)."
|
|
53
|
+
# A recommended workaround is to use OpenSSL version < 3.6.0 or requiring the openssl gem with a version of at
|
|
54
|
+
# least 3.2.2. GitHub issue: https://github.com/openssl/openssl/issues/28752.
|
|
55
|
+
if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('3.6.') &&
|
|
56
|
+
(!Gem.loaded_specs['openssl'] || Gem.loaded_specs['openssl'].version < Gem::Version.new('3.2.2'))
|
|
57
|
+
warn 'WARNING: OpenSSL 3.6.x may cause certificate verify errors - use OpenSSL < 3.6.0 or openssl gem >= 3.2.2'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Attempt to refresh the token
|
|
61
|
+
attempt_refresh(token_json)
|
|
62
|
+
|
|
63
|
+
# Raise if token is hard expired
|
|
64
|
+
return unless !@expiration || @expiration < Time.now
|
|
65
|
+
|
|
66
|
+
raise Errors::InvalidLoginToken,
|
|
67
|
+
'Login token is invalid and failed to refresh. Please reauthenticate.'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def read_cached_token
|
|
71
|
+
cached_token = JSON.load_file(login_cache_file)
|
|
72
|
+
validate_cached_token(cached_token)
|
|
73
|
+
cached_token
|
|
74
|
+
rescue Errno::ENOENT, Aws::Json::ParseError
|
|
75
|
+
raise Errors::InvalidLoginToken,
|
|
76
|
+
"Failed to load a Login token for login session #{@login_session}. Please reauthenticate."
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def login_cache_file
|
|
80
|
+
directory = ENV['AWS_LOGIN_CACHE_DIRECTORY'] || File.join(Dir.home, '.aws', 'login', 'cache')
|
|
81
|
+
login_session_sha = OpenSSL::Digest::SHA256.hexdigest(@login_session.strip.encode('utf-8'))
|
|
82
|
+
File.join(directory, "#{login_session_sha}.json")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def validate_cached_token(cached_token)
|
|
86
|
+
required_cached_token_fields = %w[accessToken clientId refreshToken dpopKey]
|
|
87
|
+
missing_fields = required_cached_token_fields.reject { |field| cached_token[field] }
|
|
88
|
+
unless missing_fields.empty?
|
|
89
|
+
raise ArgumentError, "Cached login token is missing required field(s): #{missing_fields}. " \
|
|
90
|
+
'Please reauthenticate.'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
access_token = cached_token['accessToken']
|
|
94
|
+
required_access_token_fields = %w[accessKeyId secretAccessKey sessionToken accountId expiresAt]
|
|
95
|
+
missing_fields = required_access_token_fields.reject { |field| access_token[field] }
|
|
96
|
+
|
|
97
|
+
return if missing_fields.empty?
|
|
98
|
+
|
|
99
|
+
raise ArgumentError, "Access token in cached login token is missing required field(s): #{missing_fields}. " \
|
|
100
|
+
'Please reauthenticate.'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def update_creds(access_token)
|
|
104
|
+
@credentials = Credentials.new(
|
|
105
|
+
access_token['accessKeyId'],
|
|
106
|
+
access_token['secretAccessKey'],
|
|
107
|
+
access_token['sessionToken'],
|
|
108
|
+
account_id: access_token['accountId']
|
|
109
|
+
)
|
|
110
|
+
@expiration = Time.parse(access_token['expiresAt'])
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def attempt_refresh(token_json)
|
|
114
|
+
resp = make_request(token_json)
|
|
115
|
+
parse_resp(resp.token_output, token_json)
|
|
116
|
+
update_creds(token_json['accessToken'])
|
|
117
|
+
update_token_cache(token_json)
|
|
118
|
+
rescue Signin::Errors::AccessDeniedException => e
|
|
119
|
+
case e.error
|
|
120
|
+
when 'TOKEN_EXPIRED'
|
|
121
|
+
warn 'Your session has expired. Please reauthenticate.'
|
|
122
|
+
when 'USER_CREDENTIALS_CHANGED'
|
|
123
|
+
warn 'Unable to refresh credentials because of a change in your password. ' \
|
|
124
|
+
'Please reauthenticate with your new password.'
|
|
125
|
+
when 'INSUFFICIENT_PERMISSIONS'
|
|
126
|
+
warn 'Unable to refresh credentials due to insufficient permissions. ' \
|
|
127
|
+
'You may be missing permission for the `CreateOAuth2Token` action.'
|
|
128
|
+
end
|
|
129
|
+
rescue StandardError => e
|
|
130
|
+
warn("Failed to refresh Login token for LoginCredentials: #{e.message}")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def make_request(token_json)
|
|
134
|
+
options = {
|
|
135
|
+
token_input: {
|
|
136
|
+
client_id: token_json['clientId'],
|
|
137
|
+
grant_type: 'refresh_token',
|
|
138
|
+
refresh_token: token_json['refreshToken']
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
req = @client.build_request(:create_o_auth_2_token, options)
|
|
142
|
+
endpoint_params = Aws::Signin::EndpointParameters.create(req.context.config)
|
|
143
|
+
endpoint = req.context.config.endpoint_provider.resolve_endpoint(endpoint_params)
|
|
144
|
+
endpoint = URI.join(endpoint.url, @client.config.api.operation(:create_o_auth_2_token).http_request_uri).to_s
|
|
145
|
+
req.context.http_request.headers['DPoP'] = dpop_proof(token_json['dpopKey'], endpoint)
|
|
146
|
+
req.send_request
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def dpop_proof(dpop_key, endpoint)
|
|
150
|
+
# Load private key from cached token file
|
|
151
|
+
private_key = OpenSSL::PKey.read(dpop_key)
|
|
152
|
+
public_key = private_key.public_key.to_octet_string(:uncompressed)
|
|
153
|
+
|
|
154
|
+
# Construct header and payload
|
|
155
|
+
header = build_header(public_key[1, 32], public_key[33, 32])
|
|
156
|
+
payload = build_payload(endpoint)
|
|
157
|
+
|
|
158
|
+
# Base64URL encode header and payload, sign message using private key, and create header
|
|
159
|
+
message = build_message(header, payload)
|
|
160
|
+
signature = private_key.sign(OpenSSL::Digest.new('SHA256'), message)
|
|
161
|
+
jws_signature = der_to_jws(signature)
|
|
162
|
+
"#{message}.#{Base64.urlsafe_encode64(jws_signature, padding: false)}"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def build_header(x_bytes, y_bytes)
|
|
166
|
+
{
|
|
167
|
+
'alg' => 'ES256', # signing algorithm
|
|
168
|
+
'jwk' => {
|
|
169
|
+
'crv' => 'P-256', # curve name
|
|
170
|
+
'kty' => 'EC', # key type
|
|
171
|
+
'x' => Base64.urlsafe_encode64(x_bytes, padding: false), # public x coordinate
|
|
172
|
+
'y' => Base64.urlsafe_encode64(y_bytes, padding: false) # public y coordinate
|
|
173
|
+
},
|
|
174
|
+
'typ' => 'dpop+jwt' # hardcoded
|
|
175
|
+
}
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def build_payload(htu)
|
|
179
|
+
{
|
|
180
|
+
'jti' => SecureRandom.uuid, # unique identifier (UUID4)
|
|
181
|
+
'htm' => @client.config.api.operation(:create_o_auth_2_token).http_method, # POST
|
|
182
|
+
'htu' => htu, # endpoint of the CreateOAuth2Token operation, with path
|
|
183
|
+
'iat' => Time.now.utc.to_i # UTC timestamp, specified number of seconds from 1970-01-01T00:00:00Z UTC
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def build_message(header, payload)
|
|
188
|
+
encoded_header = Base64.urlsafe_encode64(JSON.dump(header), padding: false)
|
|
189
|
+
encoded_payload = Base64.urlsafe_encode64(JSON.dump(payload), padding: false)
|
|
190
|
+
"#{encoded_header}.#{encoded_payload}"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Converts DER-encoded ASN.1 signature to JWS
|
|
194
|
+
def der_to_jws(der_signature)
|
|
195
|
+
asn1 = OpenSSL::ASN1.decode(der_signature)
|
|
196
|
+
r = asn1.value[0].value
|
|
197
|
+
s = asn1.value[1].value
|
|
198
|
+
|
|
199
|
+
r_hex = r.to_s(16).rjust(64, '0')
|
|
200
|
+
s_hex = s.to_s(16).rjust(64, '0')
|
|
201
|
+
|
|
202
|
+
[r_hex + s_hex].pack('H*')
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def parse_resp(resp, token_json)
|
|
206
|
+
access_token = token_json['accessToken']
|
|
207
|
+
access_token.merge!(
|
|
208
|
+
'accessKeyId' => resp.access_token.access_key_id,
|
|
209
|
+
'secretAccessKey' => resp.access_token.secret_access_key,
|
|
210
|
+
'sessionToken' => resp.access_token.session_token,
|
|
211
|
+
'expiresAt' => (Time.now.utc + resp.expires_in).to_datetime.rfc3339
|
|
212
|
+
)
|
|
213
|
+
token_json['refreshToken'] = resp.refresh_token
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def update_token_cache(token_json)
|
|
217
|
+
cached_token = token_json.dup
|
|
218
|
+
# File.write is not atomic so use temp file and move
|
|
219
|
+
temp_file = Tempfile.new('temp_file')
|
|
220
|
+
begin
|
|
221
|
+
temp_file.write(Json.dump(cached_token))
|
|
222
|
+
temp_file.close
|
|
223
|
+
FileUtils.mv(temp_file.path, login_cache_file)
|
|
224
|
+
ensure
|
|
225
|
+
temp_file.unlink if File.exist?(temp_file.path) # Ensure temp file is cleaned up
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
# @api private
|
|
5
|
+
# A simple thread safe LRU cache
|
|
6
|
+
class LRUCache
|
|
7
|
+
# @param [Hash] options
|
|
8
|
+
# @option options [Integer] :max_entries (100) Maximum number of entries
|
|
9
|
+
# @option options [Integer] :expiration (nil) Expiration time in seconds
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
@max_entries = options[:max_entries] || 100
|
|
12
|
+
@expiration = options[:expiration]
|
|
13
|
+
@entries = {}
|
|
14
|
+
@mutex = Mutex.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param [String] key
|
|
18
|
+
# @return [Object]
|
|
19
|
+
def [](key)
|
|
20
|
+
@mutex.synchronize do
|
|
21
|
+
value = @entries[key]
|
|
22
|
+
if value
|
|
23
|
+
@entries.delete(key)
|
|
24
|
+
@entries[key] = value unless value.expired?
|
|
25
|
+
end
|
|
26
|
+
@entries[key]&.value
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param [String] key
|
|
31
|
+
# @param [Object] value
|
|
32
|
+
def []=(key, value)
|
|
33
|
+
@mutex.synchronize do
|
|
34
|
+
@entries.shift unless @entries.size < @max_entries
|
|
35
|
+
# delete old value if exists
|
|
36
|
+
@entries.delete(key)
|
|
37
|
+
@entries[key] = Entry.new(value: value, expiration: @expiration)
|
|
38
|
+
@entries[key].value
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param [String] key
|
|
43
|
+
# @return [Boolean]
|
|
44
|
+
def key?(key)
|
|
45
|
+
@mutex.synchronize do
|
|
46
|
+
@entries.delete(key) if @entries.key?(key) && @entries[key].expired?
|
|
47
|
+
@entries.key?(key)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def clear
|
|
52
|
+
@mutex.synchronize do
|
|
53
|
+
@entries.clear
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @api private
|
|
58
|
+
class Entry
|
|
59
|
+
def initialize(options = {})
|
|
60
|
+
@value = options[:value]
|
|
61
|
+
@expiration = options[:expiration]
|
|
62
|
+
@created_time = Time.now
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @return [Object]
|
|
66
|
+
attr_reader :value
|
|
67
|
+
|
|
68
|
+
def expired?
|
|
69
|
+
return false unless @expiration
|
|
70
|
+
|
|
71
|
+
Time.now - @created_time > @expiration
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -201,7 +201,7 @@ module Aws
|
|
|
201
201
|
def next_response(params)
|
|
202
202
|
params = next_page_params(params)
|
|
203
203
|
request = context.client.build_request(context.operation_name, params)
|
|
204
|
-
Aws::Plugins::UserAgent.
|
|
204
|
+
Aws::Plugins::UserAgent.metric('PAGINATOR') do
|
|
205
205
|
request.send_request
|
|
206
206
|
end
|
|
207
207
|
end
|
|
@@ -71,9 +71,10 @@ module Aws
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
if @validate_required && shape.union
|
|
74
|
-
|
|
74
|
+
set_values = values.to_h.length
|
|
75
|
+
if set_values > 1
|
|
75
76
|
errors << "multiple values provided to union at #{context} - must contain exactly one of the supported types: #{shape.member_names.join(', ')}"
|
|
76
|
-
elsif
|
|
77
|
+
elsif set_values == 0
|
|
77
78
|
errors << "No values provided to union at #{context} - must contain exactly one of the supported types: #{shape.member_names.join(', ')}"
|
|
78
79
|
end
|
|
79
80
|
end
|
|
@@ -106,6 +107,8 @@ module Aws
|
|
|
106
107
|
# validate members
|
|
107
108
|
member_ref = ref.shape.member
|
|
108
109
|
values.each.with_index do |value, index|
|
|
110
|
+
next unless value
|
|
111
|
+
|
|
109
112
|
shape(member_ref, value, errors, context + "[#{index}]")
|
|
110
113
|
end
|
|
111
114
|
end
|
|
@@ -121,6 +124,8 @@ module Aws
|
|
|
121
124
|
|
|
122
125
|
values.each do |key, value|
|
|
123
126
|
shape(key_ref, key, errors, "#{context} #{key.inspect} key")
|
|
127
|
+
next unless value
|
|
128
|
+
|
|
124
129
|
shape(value_ref, value, errors, context + "[#{key.inspect}]")
|
|
125
130
|
end
|
|
126
131
|
end
|
|
@@ -4,6 +4,8 @@ module Aws
|
|
|
4
4
|
# @api private
|
|
5
5
|
module Plugins
|
|
6
6
|
# @api private
|
|
7
|
+
# Deprecated - does not look at new traits like `auth` and `unsignedPayload`
|
|
8
|
+
# Necessary to exist after endpoints 2.0 for old service clients + new core
|
|
7
9
|
class BearerAuthorization < Seahorse::Client::Plugin
|
|
8
10
|
|
|
9
11
|
option(:token_provider,
|