aws-sdk-core 3.122.0 → 3.180.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +505 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +153 -0
  5. data/lib/aws-defaults/defaults_mode_config_resolver.rb +107 -0
  6. data/lib/aws-defaults.rb +3 -0
  7. data/lib/aws-sdk-core/arn.rb +13 -0
  8. data/lib/aws-sdk-core/assume_role_credentials.rb +21 -7
  9. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +14 -10
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +12 -1
  11. data/lib/aws-sdk-core/client_stubs.rb +5 -1
  12. data/lib/aws-sdk-core/credential_provider.rb +3 -0
  13. data/lib/aws-sdk-core/credential_provider_chain.rb +8 -5
  14. data/lib/aws-sdk-core/ec2_metadata.rb +3 -2
  15. data/lib/aws-sdk-core/ecs_credentials.rb +121 -53
  16. data/lib/aws-sdk-core/endpoints/condition.rb +41 -0
  17. data/lib/aws-sdk-core/endpoints/endpoint.rb +17 -0
  18. data/lib/aws-sdk-core/endpoints/endpoint_rule.rb +75 -0
  19. data/lib/aws-sdk-core/endpoints/error_rule.rb +42 -0
  20. data/lib/aws-sdk-core/endpoints/function.rb +80 -0
  21. data/lib/aws-sdk-core/endpoints/matchers.rb +127 -0
  22. data/lib/aws-sdk-core/endpoints/reference.rb +31 -0
  23. data/lib/aws-sdk-core/endpoints/rule.rb +25 -0
  24. data/lib/aws-sdk-core/endpoints/rule_set.rb +52 -0
  25. data/lib/aws-sdk-core/endpoints/rules_provider.rb +37 -0
  26. data/lib/aws-sdk-core/endpoints/templater.rb +58 -0
  27. data/lib/aws-sdk-core/endpoints/tree_rule.rb +45 -0
  28. data/lib/aws-sdk-core/endpoints/url.rb +60 -0
  29. data/lib/aws-sdk-core/endpoints.rb +78 -0
  30. data/lib/aws-sdk-core/errors.rb +14 -1
  31. data/lib/aws-sdk-core/ini_parser.rb +1 -1
  32. data/lib/aws-sdk-core/instance_profile_credentials.rb +85 -14
  33. data/lib/aws-sdk-core/json/error_handler.rb +20 -1
  34. data/lib/aws-sdk-core/log/formatter.rb +6 -0
  35. data/lib/aws-sdk-core/pageable_response.rb +81 -32
  36. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +67 -0
  37. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +340 -0
  38. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +27 -1
  39. data/lib/aws-sdk-core/plugins/defaults_mode.rb +40 -0
  40. data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +6 -2
  41. data/lib/aws-sdk-core/plugins/http_checksum.rb +8 -1
  42. data/lib/aws-sdk-core/plugins/jsonvalue_converter.rb +34 -6
  43. data/lib/aws-sdk-core/plugins/recursion_detection.rb +38 -0
  44. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +111 -30
  45. data/lib/aws-sdk-core/plugins/request_compression.rb +217 -0
  46. data/lib/aws-sdk-core/plugins/response_paging.rb +1 -1
  47. data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +7 -4
  48. data/lib/aws-sdk-core/plugins/retry_errors.rb +21 -5
  49. data/lib/aws-sdk-core/plugins/sign.rb +201 -0
  50. data/lib/aws-sdk-core/plugins/signature_v2.rb +1 -0
  51. data/lib/aws-sdk-core/plugins/signature_v4.rb +15 -8
  52. data/lib/aws-sdk-core/plugins/stub_responses.rb +5 -1
  53. data/lib/aws-sdk-core/plugins/user_agent.rb +117 -14
  54. data/lib/aws-sdk-core/process_credentials.rb +9 -11
  55. data/lib/aws-sdk-core/refreshing_credentials.rb +41 -16
  56. data/lib/aws-sdk-core/refreshing_token.rb +71 -0
  57. data/lib/aws-sdk-core/rest/handler.rb +1 -1
  58. data/lib/aws-sdk-core/rest/request/headers.rb +14 -6
  59. data/lib/aws-sdk-core/rest/response/headers.rb +2 -0
  60. data/lib/aws-sdk-core/shared_config.rb +103 -12
  61. data/lib/aws-sdk-core/sso_credentials.rb +91 -50
  62. data/lib/aws-sdk-core/sso_token_provider.rb +135 -0
  63. data/lib/aws-sdk-core/static_token_provider.rb +14 -0
  64. data/lib/aws-sdk-core/structure.rb +6 -4
  65. data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
  66. data/lib/aws-sdk-core/token.rb +31 -0
  67. data/lib/aws-sdk-core/token_provider.rb +15 -0
  68. data/lib/aws-sdk-core/token_provider_chain.rb +51 -0
  69. data/lib/aws-sdk-core/waiters/poller.rb +3 -1
  70. data/lib/aws-sdk-core/xml/error_handler.rb +7 -0
  71. data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
  72. data/lib/aws-sdk-core/xml/parser/engines/ox.rb +1 -1
  73. data/lib/aws-sdk-core.rb +17 -0
  74. data/lib/aws-sdk-sso/client.rb +88 -13
  75. data/lib/aws-sdk-sso/endpoint_parameters.rb +66 -0
  76. data/lib/aws-sdk-sso/endpoint_provider.rb +51 -0
  77. data/lib/aws-sdk-sso/endpoints.rb +72 -0
  78. data/lib/aws-sdk-sso/plugins/endpoints.rb +76 -0
  79. data/lib/aws-sdk-sso/types.rb +8 -43
  80. data/lib/aws-sdk-sso.rb +5 -1
  81. data/lib/aws-sdk-ssooidc/client.rb +626 -0
  82. data/lib/aws-sdk-ssooidc/client_api.rb +216 -0
  83. data/lib/aws-sdk-ssooidc/customizations.rb +1 -0
  84. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +66 -0
  85. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +51 -0
  86. data/lib/aws-sdk-ssooidc/endpoints.rb +58 -0
  87. data/lib/aws-sdk-ssooidc/errors.rb +290 -0
  88. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +74 -0
  89. data/lib/aws-sdk-ssooidc/resource.rb +26 -0
  90. data/lib/aws-sdk-ssooidc/types.rb +502 -0
  91. data/lib/aws-sdk-ssooidc.rb +59 -0
  92. data/lib/aws-sdk-sts/client.rb +394 -362
  93. data/lib/aws-sdk-sts/client_api.rb +10 -0
  94. data/lib/aws-sdk-sts/endpoint_parameters.rb +78 -0
  95. data/lib/aws-sdk-sts/endpoint_provider.rb +112 -0
  96. data/lib/aws-sdk-sts/endpoints.rb +136 -0
  97. data/lib/aws-sdk-sts/plugins/endpoints.rb +84 -0
  98. data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +5 -1
  99. data/lib/aws-sdk-sts/presigner.rb +13 -15
  100. data/lib/aws-sdk-sts/types.rb +154 -227
  101. data/lib/aws-sdk-sts.rb +5 -1
  102. data/lib/seahorse/client/async_base.rb +0 -1
  103. data/lib/seahorse/client/configuration.rb +1 -5
  104. data/lib/seahorse/client/h2/connection.rb +12 -11
  105. data/lib/seahorse/client/net_http/connection_pool.rb +7 -0
  106. data/lib/seahorse/client/plugins/net_http.rb +33 -2
  107. data/lib/seahorse/client/plugins/request_callback.rb +9 -9
  108. data/lib/seahorse/client/response.rb +6 -0
  109. data/lib/seahorse/model/operation.rb +6 -0
  110. data/lib/seahorse/util.rb +4 -0
  111. metadata +62 -8
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ #@api private
5
+ class DefaultsModeConfigResolver
6
+
7
+ @@application_region = nil
8
+ @@application_region_mutex = Mutex.new
9
+ @@imds_client = EC2Metadata.new(retries: 0, http_open_timeout: 0.01)
10
+
11
+ # mappings from Ruby SDK configuration names to the
12
+ # sdk defaults option names and (optional) scale modifiers
13
+ CFG_OPTIONS = {
14
+ retry_mode: { name: "retryMode" },
15
+ sts_regional_endpoints: { name: "stsRegionalEndpoints" },
16
+ s3_us_east_1_regional_endpoint: { name: "s3UsEast1RegionalEndpoints" },
17
+ http_open_timeout: { name: "connectTimeoutInMillis", scale: 0.001 },
18
+ http_read_timeout: { name: "timeToFirstByteTimeoutInMillis", scale: 0.001 },
19
+ ssl_timeout: { name: "tlsNegotiationTimeoutInMillis", scale: 0.001 }
20
+ }.freeze
21
+
22
+ def initialize(sdk_defaults, cfg)
23
+ @sdk_defaults = sdk_defaults
24
+ @cfg = cfg
25
+ @resolved_mode = nil
26
+ @mutex = Mutex.new
27
+ end
28
+
29
+ # option_name should be the symbolized ruby name to resolve
30
+ # returns the ruby appropriate value or nil if none are resolved
31
+ def resolve(option_name)
32
+ return unless (std_option = CFG_OPTIONS[option_name])
33
+ mode = resolved_mode.downcase
34
+
35
+ return nil if mode == 'legacy'
36
+
37
+ value = resolve_for_mode(std_option[:name], mode)
38
+ value = value * std_option[:scale] if value && std_option[:scale]
39
+
40
+ value
41
+ end
42
+
43
+ private
44
+ def resolved_mode
45
+ @mutex.synchronize do
46
+ return @resolved_mode unless @resolved_mode.nil?
47
+
48
+ @resolved_mode = @cfg.defaults_mode == 'auto' ? resolve_auto_mode : @cfg.defaults_mode
49
+ end
50
+ end
51
+
52
+ def resolve_auto_mode
53
+ return "mobile" if env_mobile?
54
+
55
+ region = application_current_region
56
+
57
+ if region
58
+ @cfg.region == region ? "in-region": "cross-region"
59
+ else
60
+ # We don't seem to be mobile, and we couldn't determine whether we're running within an AWS region. Fall back to standard.
61
+ 'standard'
62
+ end
63
+ end
64
+
65
+ def application_current_region
66
+ resolved_region = @@application_region_mutex.synchronize do
67
+ return @@application_region unless @@application_region.nil?
68
+
69
+ region = nil
70
+ if ENV['AWS_EXECUTION_ENV']
71
+ region = ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION']
72
+ end
73
+
74
+ if region.nil? && ENV['AWS_EC2_METADATA_DISABLED']&.downcase != "true"
75
+ begin
76
+ region = @@imds_client.get('/latest/meta-data/placement/region')
77
+ rescue
78
+ # unable to get region, leave it unset
79
+ end
80
+ end
81
+
82
+ # required so that we cache the unknown/nil result
83
+ @@application_region = region || :unknown
84
+ end
85
+ resolved_region == :unknown ? nil : resolved_region
86
+ end
87
+
88
+ def resolve_for_mode(name, mode)
89
+ base_value = @sdk_defaults['base'][name]
90
+ mode_value = @sdk_defaults['modes'].fetch(mode, {})[name]
91
+
92
+ if mode_value.nil?
93
+ return base_value
94
+ end
95
+
96
+ return mode_value['override'] unless mode_value['override'].nil?
97
+ return base_value + mode_value['add'] unless mode_value['add'].nil?
98
+ return base_value * mode_value['multiply'] unless mode_value['multiply'].nil?
99
+ return base_value
100
+ end
101
+
102
+ def env_mobile?
103
+ false
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'aws-defaults/default_configuration'
@@ -88,5 +88,18 @@ module Aws
88
88
  resource: @resource
89
89
  }
90
90
  end
91
+
92
+ # Return the ARN as JSON
93
+ #
94
+ # @return [Hash]
95
+ def as_json(_options = nil)
96
+ {
97
+ 'partition' => @partition,
98
+ 'service' => @service,
99
+ 'region' => @region,
100
+ 'accountId' => @account_id,
101
+ 'resource' => @resource
102
+ }
103
+ end
91
104
  end
92
105
  end
@@ -3,20 +3,20 @@
3
3
  require 'set'
4
4
 
5
5
  module Aws
6
-
7
- # An auto-refreshing credential provider that works by assuming
8
- # a role via {Aws::STS::Client#assume_role}.
6
+ # An auto-refreshing credential provider that assumes a role via
7
+ # {Aws::STS::Client#assume_role}.
9
8
  #
10
9
  # role_credentials = Aws::AssumeRoleCredentials.new(
11
10
  # client: Aws::STS::Client.new(...),
12
11
  # role_arn: "linked::account::arn",
13
12
  # role_session_name: "session-name"
14
13
  # )
15
- #
16
14
  # ec2 = Aws::EC2::Client.new(credentials: role_credentials)
17
15
  #
18
- # If you omit `:client` option, a new {STS::Client} object will be
19
- # constructed.
16
+ # If you omit `:client` option, a new {Aws::STS::Client} object will be
17
+ # constructed with additional options that were provided.
18
+ #
19
+ # @see Aws::STS::Client#assume_role
20
20
  class AssumeRoleCredentials
21
21
 
22
22
  include CredentialProvider
@@ -28,23 +28,37 @@ module Aws
28
28
  # @option options [Integer] :duration_seconds
29
29
  # @option options [String] :external_id
30
30
  # @option options [STS::Client] :client
31
+ # @option options [Callable] before_refresh Proc called before
32
+ # credentials are refreshed. Useful for updating tokens.
33
+ # `before_refresh` is called when AWS credentials are
34
+ # required and need to be refreshed. Tokens can be refreshed using
35
+ # the following example:
36
+ #
37
+ # before_refresh = Proc.new do |assume_role_credentials| do
38
+ # assume_role_credentials.assume_role_params['token_code'] = update_token
39
+ # end
40
+ #
31
41
  def initialize(options = {})
32
42
  client_opts = {}
33
43
  @assume_role_params = {}
34
44
  options.each_pair do |key, value|
35
45
  if self.class.assume_role_options.include?(key)
36
46
  @assume_role_params[key] = value
37
- else
47
+ elsif !CLIENT_EXCLUDE_OPTIONS.include?(key)
38
48
  client_opts[key] = value
39
49
  end
40
50
  end
41
51
  @client = client_opts[:client] || STS::Client.new(client_opts)
52
+ @async_refresh = true
42
53
  super
43
54
  end
44
55
 
45
56
  # @return [STS::Client]
46
57
  attr_reader :client
47
58
 
59
+ # @return [Hash]
60
+ attr_reader :assume_role_params
61
+
48
62
  private
49
63
 
50
64
  def refresh
@@ -5,9 +5,8 @@ require 'securerandom'
5
5
  require 'base64'
6
6
 
7
7
  module Aws
8
-
9
- # An auto-refreshing credential provider that works by assuming
10
- # a role via {Aws::STS::Client#assume_role_with_web_identity}.
8
+ # An auto-refreshing credential provider that assumes a role via
9
+ # {Aws::STS::Client#assume_role_with_web_identity}.
11
10
  #
12
11
  # role_credentials = Aws::AssumeRoleWebIdentityCredentials.new(
13
12
  # client: Aws::STS::Client.new(...),
@@ -16,12 +15,12 @@ module Aws
16
15
  # role_session_name: "session-name"
17
16
  # ...
18
17
  # )
19
- # For full list of parameters accepted
20
- # @see Aws::STS::Client#assume_role_with_web_identity
18
+ # ec2 = Aws::EC2::Client.new(credentials: role_credentials)
21
19
  #
20
+ # If you omit `:client` option, a new {Aws::STS::Client} object will be
21
+ # constructed with additional options that were provided.
22
22
  #
23
- # If you omit `:client` option, a new {STS::Client} object will be
24
- # constructed.
23
+ # @see Aws::STS::Client#assume_role_with_web_identity
25
24
  class AssumeRoleWebIdentityCredentials
26
25
 
27
26
  include CredentialProvider
@@ -39,14 +38,20 @@ module Aws
39
38
  # encoded UUID is generated as the session name
40
39
  #
41
40
  # @option options [STS::Client] :client
41
+ #
42
+ # @option options [Callable] before_refresh Proc called before
43
+ # credentials are refreshed. `before_refresh` is called
44
+ # with an instance of this object when
45
+ # AWS credentials are required and need to be refreshed.
42
46
  def initialize(options = {})
43
47
  client_opts = {}
44
48
  @assume_role_web_identity_params = {}
45
49
  @token_file = options.delete(:web_identity_token_file)
50
+ @async_refresh = true
46
51
  options.each_pair do |key, value|
47
52
  if self.class.assume_role_web_identity_options.include?(key)
48
53
  @assume_role_web_identity_params[key] = value
49
- else
54
+ elsif !CLIENT_EXCLUDE_OPTIONS.include?(key)
50
55
  client_opts[key] = value
51
56
  end
52
57
  end
@@ -94,11 +99,10 @@ module Aws
94
99
  # @api private
95
100
  def assume_role_web_identity_options
96
101
  @arwio ||= begin
97
- input = STS::Client.api.operation(:assume_role_with_web_identity).input
102
+ input = Aws::STS::Client.api.operation(:assume_role_with_web_identity).input
98
103
  Set.new(input.shape.member_names)
99
104
  end
100
105
  end
101
-
102
106
  end
103
107
  end
104
108
  end
@@ -13,7 +13,7 @@ module Aws
13
13
  context.config.api.metadata['protocol'],
14
14
  eventstream_member,
15
15
  context.operation.input,
16
- context.config.sigv4_signer
16
+ signer_for(context)
17
17
  )
18
18
  context[:input_event_emitter] = input_es_handler.event_emitter
19
19
  end
@@ -22,6 +22,17 @@ module Aws
22
22
 
23
23
  private
24
24
 
25
+ def signer_for(context)
26
+ # New endpoint/signing logic, use the auth scheme to make a signer
27
+ if context[:auth_scheme]
28
+ Aws::Plugins::Sign.signer_for(context[:auth_scheme], context.config)
29
+ else
30
+ # Previous implementation always assumed sigv4_signer from config.
31
+ # Relies only on sigv4 signing (and plugin) for event stream services
32
+ context.config.sigv4_signer
33
+ end
34
+ end
35
+
25
36
  def eventstream_input?(ctx)
26
37
  ctx.operation.input.shape.members.each do |_, ref|
27
38
  return ref if ref.eventstream
@@ -262,13 +262,17 @@ module Aws
262
262
  end
263
263
 
264
264
  def convert_stub(operation_name, stub)
265
- case stub
265
+ stub = case stub
266
266
  when Proc then stub
267
267
  when Exception, Class then { error: stub }
268
268
  when String then service_error_stub(stub)
269
269
  when Hash then http_response_stub(operation_name, stub)
270
270
  else { data: stub }
271
271
  end
272
+ if Hash === stub
273
+ stub[:mutex] = Mutex.new
274
+ end
275
+ stub
272
276
  end
273
277
 
274
278
  def service_error_stub(error_code)
@@ -6,6 +6,9 @@ module Aws
6
6
  # @return [Credentials]
7
7
  attr_reader :credentials
8
8
 
9
+ # @return [Time]
10
+ attr_reader :expiration
11
+
9
12
  # @return [Boolean]
10
13
  def set?
11
14
  !!credentials && credentials.set?
@@ -161,7 +161,8 @@ module Aws
161
161
 
162
162
  def instance_profile_credentials(options)
163
163
  profile_name = determine_profile_name(options)
164
- if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
164
+ if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] ||
165
+ ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI']
165
166
  ECSCredentials.new(options)
166
167
  else
167
168
  InstanceProfileCredentials.new(options.merge(profile: profile_name))
@@ -169,12 +170,14 @@ module Aws
169
170
  end
170
171
 
171
172
  def assume_role_with_profile(options, profile_name)
172
- region = (options[:config] && options[:config].region)
173
- Aws.shared_config.assume_role_credentials_from_config(
173
+ assume_opts = {
174
174
  profile: profile_name,
175
- region: region,
176
175
  chain_config: @config
177
- )
176
+ }
177
+ if options[:config] && options[:config].region
178
+ assume_opts[:region] = options[:config].region
179
+ end
180
+ Aws.shared_config.assume_role_credentials_from_config(assume_opts)
178
181
  end
179
182
  end
180
183
  end
@@ -136,8 +136,9 @@ module Aws
136
136
 
137
137
  def fetch_token
138
138
  open_connection do |conn|
139
+ created_time = Time.now
139
140
  token_value, token_ttl = http_put(conn, @token_ttl)
140
- @token = Token.new(value: token_value, ttl: token_ttl)
141
+ @token = Token.new(value: token_value, ttl: token_ttl, created_time: created_time)
141
142
  end
142
143
  end
143
144
 
@@ -222,7 +223,7 @@ module Aws
222
223
  def initialize(options = {})
223
224
  @ttl = options[:ttl]
224
225
  @value = options[:value]
225
- @created_time = Time.now
226
+ @created_time = options[:created_time] || Time.now
226
227
  end
227
228
 
228
229
  # [String] Returns the token value.
@@ -2,10 +2,15 @@
2
2
 
3
3
  require 'time'
4
4
  require 'net/http'
5
+ require 'resolv'
5
6
 
6
7
  module Aws
8
+ # An auto-refreshing credential provider that loads credentials from
9
+ # instances running in ECS.
10
+ #
11
+ # ecs_credentials = Aws::ECSCredentials.new(retries: 3)
12
+ # ec2 = Aws::EC2::Client.new(credentials: ecs_credentials)
7
13
  class ECSCredentials
8
-
9
14
  include CredentialProvider
10
15
  include RefreshingCredentials
11
16
 
@@ -24,16 +29,22 @@ module Aws
24
29
  Errno::ENETUNREACH,
25
30
  SocketError,
26
31
  Timeout::Error,
27
- Non200Response,
28
- ]
32
+ Non200Response
33
+ ].freeze
29
34
 
30
35
  # @param [Hash] options
31
36
  # @option options [Integer] :retries (5) Number of times to retry
32
37
  # when retrieving credentials.
33
- # @option options [String] :ip_address ('169.254.170.2')
34
- # @option options [Integer] :port (80)
38
+ # @option options [String] :ip_address ('169.254.170.2') This value is
39
+ # ignored if `endpoint` is set and `credential_path` is not set.
40
+ # @option options [Integer] :port (80) This value is ignored if `endpoint`
41
+ # is set and `credential_path` is not set.
35
42
  # @option options [String] :credential_path By default, the value of the
36
43
  # AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable.
44
+ # @option options [String] :endpoint The ECS credential endpoint.
45
+ # By default, this is the value of the AWS_CONTAINER_CREDENTIALS_FULL_URI
46
+ # environment variable. This value is ignored if `credential_path` or
47
+ # ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] is set.
37
48
  # @option options [Float] :http_open_timeout (5)
38
49
  # @option options [Float] :http_read_timeout (5)
39
50
  # @option options [Numeric, Proc] :delay By default, failures are retried
@@ -43,21 +54,24 @@ module Aws
43
54
  # @option options [IO] :http_debug_output (nil) HTTP wire
44
55
  # traces are sent to this object. You can specify something
45
56
  # like $stdout.
46
- def initialize options = {}
57
+ # @option options [Callable] before_refresh Proc called before
58
+ # credentials are refreshed. `before_refresh` is called
59
+ # with an instance of this object when
60
+ # AWS credentials are required and need to be refreshed.
61
+ def initialize(options = {})
62
+ credential_path = options[:credential_path] ||
63
+ ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
64
+ endpoint = options[:endpoint] ||
65
+ ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI']
66
+ initialize_uri(options, credential_path, endpoint)
67
+ @authorization_token = ENV['AWS_CONTAINER_AUTHORIZATION_TOKEN']
68
+
47
69
  @retries = options[:retries] || 5
48
- @ip_address = options[:ip_address] || '169.254.170.2'
49
- @port = options[:port] || 80
50
- @credential_path = options[:credential_path]
51
- @credential_path ||= ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
52
- unless @credential_path
53
- raise ArgumentError.new(
54
- "Cannot instantiate an ECS Credential Provider without a credential path."
55
- )
56
- end
57
70
  @http_open_timeout = options[:http_open_timeout] || 5
58
71
  @http_read_timeout = options[:http_read_timeout] || 5
59
72
  @http_debug_output = options[:http_debug_output]
60
73
  @backoff = backoff(options[:backoff])
74
+ @async_refresh = false
61
75
  super
62
76
  end
63
77
 
@@ -67,11 +81,69 @@ module Aws
67
81
 
68
82
  private
69
83
 
84
+ def initialize_uri(options, credential_path, endpoint)
85
+ if credential_path
86
+ initialize_relative_uri(options, credential_path)
87
+ # Use FULL_URI/endpoint only if RELATIVE_URI/path is not set
88
+ elsif endpoint
89
+ initialize_full_uri(endpoint)
90
+ else
91
+ raise ArgumentError,
92
+ 'Cannot instantiate an ECS Credential Provider '\
93
+ 'without a credential path or endpoint.'
94
+ end
95
+ end
96
+
97
+ def initialize_relative_uri(options, path)
98
+ @host = options[:ip_address] || '169.254.170.2'
99
+ @port = options[:port] || 80
100
+ @scheme = 'http'
101
+ @credential_path = path
102
+ end
103
+
104
+ def initialize_full_uri(endpoint)
105
+ uri = URI.parse(endpoint)
106
+ validate_full_uri!(uri)
107
+ @host = uri.host
108
+ @port = uri.port
109
+ @scheme = uri.scheme
110
+ @credential_path = uri.path
111
+ end
112
+
113
+ # Validate that the full URI is using a loopback address if scheme is http.
114
+ def validate_full_uri!(full_uri)
115
+ return unless full_uri.scheme == 'http'
116
+
117
+ begin
118
+ return if ip_loopback?(IPAddr.new(full_uri.host))
119
+ rescue IPAddr::InvalidAddressError
120
+ addresses = Resolv.getaddresses(full_uri.host)
121
+ return if addresses.all? { |addr| ip_loopback?(IPAddr.new(addr)) }
122
+ end
123
+
124
+ raise ArgumentError,
125
+ 'AWS_CONTAINER_CREDENTIALS_FULL_URI must use a loopback '\
126
+ 'address when using the http scheme.'
127
+ end
128
+
129
+ # loopback? method is available in Ruby 2.5+
130
+ # Replicate the logic here.
131
+ def ip_loopback?(ip_address)
132
+ case ip_address.family
133
+ when Socket::AF_INET
134
+ ip_address & 0xff000000 == 0x7f000000
135
+ when Socket::AF_INET6
136
+ ip_address == 1
137
+ else
138
+ false
139
+ end
140
+ end
141
+
70
142
  def backoff(backoff)
71
143
  case backoff
72
144
  when Proc then backoff
73
- when Numeric then lambda { |_| sleep(backoff) }
74
- else lambda { |num_failures| Kernel.sleep(1.2 ** num_failures) }
145
+ when Numeric then ->(_) { sleep(backoff) }
146
+ else ->(num_failures) { Kernel.sleep(1.2**num_failures) }
75
147
  end
76
148
  end
77
149
 
@@ -79,68 +151,64 @@ module Aws
79
151
  # Retry loading credentials up to 3 times is the instance metadata
80
152
  # service is responding but is returning invalid JSON documents
81
153
  # in response to the GET profile credentials call.
82
- begin
83
- retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
84
- c = Aws::Json.load(get_credentials.to_s)
85
- @credentials = Credentials.new(
86
- c['AccessKeyId'],
87
- c['SecretAccessKey'],
88
- c['Token']
89
- )
90
- @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
91
- end
92
- rescue Aws::Json::ParseError
93
- raise Aws::Errors::MetadataParserError.new
154
+
155
+ retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
156
+ c = Aws::Json.load(get_credentials.to_s)
157
+ @credentials = Credentials.new(
158
+ c['AccessKeyId'],
159
+ c['SecretAccessKey'],
160
+ c['Token']
161
+ )
162
+ @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
94
163
  end
164
+ rescue Aws::Json::ParseError
165
+ raise Aws::Errors::MetadataParserError
95
166
  end
96
167
 
97
168
  def get_credentials
98
169
  # Retry loading credentials a configurable number of times if
99
170
  # the instance metadata service is not responding.
100
- begin
101
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
102
- open_connection do |conn|
103
- http_get(conn, @credential_path)
104
- end
171
+
172
+ retry_errors(NETWORK_ERRORS, max_retries: @retries) do
173
+ open_connection do |conn|
174
+ http_get(conn, @credential_path)
105
175
  end
106
- rescue
107
- '{}'
108
176
  end
177
+ rescue StandardError
178
+ '{}'
109
179
  end
110
180
 
111
181
  def open_connection
112
- http = Net::HTTP.new(@ip_address, @port, nil)
182
+ http = Net::HTTP.new(@host, @port, nil)
113
183
  http.open_timeout = @http_open_timeout
114
184
  http.read_timeout = @http_read_timeout
115
185
  http.set_debug_output(@http_debug_output) if @http_debug_output
186
+ http.use_ssl = @scheme == 'https'
116
187
  http.start
117
188
  yield(http).tap { http.finish }
118
189
  end
119
190
 
120
191
  def http_get(connection, path)
121
- response = connection.request(Net::HTTP::Get.new(path))
122
- if response.code.to_i == 200
123
- response.body
124
- else
125
- raise Non200Response
126
- end
192
+ request = Net::HTTP::Get.new(path)
193
+ request['Authorization'] = @authorization_token if @authorization_token
194
+ response = connection.request(request)
195
+ raise Non200Response unless response.code.to_i == 200
196
+
197
+ response.body
127
198
  end
128
199
 
129
- def retry_errors(error_classes, options = {}, &block)
200
+ def retry_errors(error_classes, options = {})
130
201
  max_retries = options[:max_retries]
131
202
  retries = 0
132
203
  begin
133
204
  yield
134
- rescue *error_classes => _error
135
- if retries < max_retries
136
- @backoff.call(retries)
137
- retries += 1
138
- retry
139
- else
140
- raise
141
- end
205
+ rescue *error_classes => _e
206
+ raise unless retries < max_retries
207
+
208
+ @backoff.call(retries)
209
+ retries += 1
210
+ retry
142
211
  end
143
212
  end
144
-
145
213
  end
146
214
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Endpoints
5
+ # This class is deprecated. It is used by the Runtime endpoint
6
+ # resolution approach. It has been replaced by a code generated
7
+ # approach in each service gem. It can be removed in a new
8
+ # major version. It has to exist because
9
+ # old service gems can use a new core version.
10
+ # @api private
11
+ class Condition
12
+ def initialize(fn:, argv:, assign: nil)
13
+ @fn = Function.new(fn: fn, argv: argv)
14
+ @assign = assign
15
+ @assigned = {}
16
+ end
17
+
18
+ attr_reader :fn
19
+ attr_reader :argv
20
+ attr_reader :assign
21
+
22
+ attr_reader :assigned
23
+
24
+ def match?(parameters, assigns)
25
+ output = @fn.call(parameters, assigns)
26
+ @assigned = @assigned.merge({ @assign => output }) if @assign
27
+ output
28
+ end
29
+
30
+ def self.from_json(conditions_json)
31
+ conditions_json.each.with_object([]) do |condition, conditions|
32
+ conditions << new(
33
+ fn: condition['fn'],
34
+ argv: condition['argv'],
35
+ assign: condition['assign']
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Endpoints
5
+ class Endpoint
6
+ def initialize(url:, properties: {}, headers: {})
7
+ @url = url
8
+ @properties = properties
9
+ @headers = headers
10
+ end
11
+
12
+ attr_reader :url
13
+ attr_reader :properties
14
+ attr_reader :headers
15
+ end
16
+ end
17
+ end