aws-sdk-core 3.131.3 → 3.176.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +330 -1
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +4 -4
  5. data/lib/aws-sdk-core/arn.rb +13 -0
  6. data/lib/aws-sdk-core/binary/encode_handler.rb +12 -1
  7. data/lib/aws-sdk-core/credential_provider.rb +3 -0
  8. data/lib/aws-sdk-core/credential_provider_chain.rb +8 -5
  9. data/lib/aws-sdk-core/ecs_credentials.rb +111 -53
  10. data/lib/aws-sdk-core/endpoints/condition.rb +41 -0
  11. data/lib/aws-sdk-core/endpoints/endpoint.rb +17 -0
  12. data/lib/aws-sdk-core/endpoints/endpoint_rule.rb +75 -0
  13. data/lib/aws-sdk-core/endpoints/error_rule.rb +42 -0
  14. data/lib/aws-sdk-core/endpoints/function.rb +80 -0
  15. data/lib/aws-sdk-core/endpoints/matchers.rb +127 -0
  16. data/lib/aws-sdk-core/endpoints/reference.rb +31 -0
  17. data/lib/aws-sdk-core/endpoints/rule.rb +25 -0
  18. data/lib/aws-sdk-core/endpoints/rule_set.rb +52 -0
  19. data/lib/aws-sdk-core/endpoints/rules_provider.rb +37 -0
  20. data/lib/aws-sdk-core/endpoints/templater.rb +58 -0
  21. data/lib/aws-sdk-core/endpoints/tree_rule.rb +45 -0
  22. data/lib/aws-sdk-core/endpoints/url.rb +60 -0
  23. data/lib/aws-sdk-core/endpoints.rb +78 -0
  24. data/lib/aws-sdk-core/errors.rb +13 -0
  25. data/lib/aws-sdk-core/json/error_handler.rb +20 -1
  26. data/lib/aws-sdk-core/log/formatter.rb +6 -0
  27. data/lib/aws-sdk-core/pageable_response.rb +10 -1
  28. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +67 -0
  29. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +1 -1
  30. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +24 -0
  31. data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +6 -2
  32. data/lib/aws-sdk-core/plugins/recursion_detection.rb +14 -3
  33. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +5 -0
  34. data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +2 -1
  35. data/lib/aws-sdk-core/plugins/sign.rb +201 -0
  36. data/lib/aws-sdk-core/plugins/signature_v2.rb +1 -0
  37. data/lib/aws-sdk-core/plugins/signature_v4.rb +13 -7
  38. data/lib/aws-sdk-core/plugins/user_agent.rb +117 -14
  39. data/lib/aws-sdk-core/refreshing_credentials.rb +0 -6
  40. data/lib/aws-sdk-core/refreshing_token.rb +71 -0
  41. data/lib/aws-sdk-core/rest/request/headers.rb +2 -6
  42. data/lib/aws-sdk-core/shared_config.rb +78 -6
  43. data/lib/aws-sdk-core/sso_credentials.rb +80 -45
  44. data/lib/aws-sdk-core/sso_token_provider.rb +135 -0
  45. data/lib/aws-sdk-core/static_token_provider.rb +14 -0
  46. data/lib/aws-sdk-core/structure.rb +6 -4
  47. data/lib/aws-sdk-core/token.rb +31 -0
  48. data/lib/aws-sdk-core/token_provider.rb +15 -0
  49. data/lib/aws-sdk-core/token_provider_chain.rb +51 -0
  50. data/lib/aws-sdk-core/waiters/poller.rb +3 -1
  51. data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
  52. data/lib/aws-sdk-core.rb +14 -0
  53. data/lib/aws-sdk-sso/client.rb +56 -11
  54. data/lib/aws-sdk-sso/endpoint_parameters.rb +66 -0
  55. data/lib/aws-sdk-sso/endpoint_provider.rb +51 -0
  56. data/lib/aws-sdk-sso/endpoints.rb +72 -0
  57. data/lib/aws-sdk-sso/plugins/endpoints.rb +76 -0
  58. data/lib/aws-sdk-sso/types.rb +8 -43
  59. data/lib/aws-sdk-sso.rb +5 -1
  60. data/lib/aws-sdk-ssooidc/client.rb +611 -0
  61. data/lib/aws-sdk-ssooidc/client_api.rb +216 -0
  62. data/lib/aws-sdk-ssooidc/customizations.rb +1 -0
  63. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +66 -0
  64. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +51 -0
  65. data/lib/aws-sdk-ssooidc/endpoints.rb +58 -0
  66. data/lib/aws-sdk-ssooidc/errors.rb +290 -0
  67. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +74 -0
  68. data/lib/aws-sdk-ssooidc/resource.rb +26 -0
  69. data/lib/aws-sdk-ssooidc/types.rb +502 -0
  70. data/lib/aws-sdk-ssooidc.rb +59 -0
  71. data/lib/aws-sdk-sts/client.rb +263 -243
  72. data/lib/aws-sdk-sts/endpoint_parameters.rb +78 -0
  73. data/lib/aws-sdk-sts/endpoint_provider.rb +112 -0
  74. data/lib/aws-sdk-sts/endpoints.rb +136 -0
  75. data/lib/aws-sdk-sts/plugins/endpoints.rb +84 -0
  76. data/lib/aws-sdk-sts/presigner.rb +13 -15
  77. data/lib/aws-sdk-sts/types.rb +87 -195
  78. data/lib/aws-sdk-sts.rb +5 -1
  79. data/lib/seahorse/client/async_base.rb +0 -1
  80. data/lib/seahorse/client/configuration.rb +2 -2
  81. data/lib/seahorse/client/h2/connection.rb +12 -11
  82. data/lib/seahorse/client/plugins/request_callback.rb +9 -9
  83. data/lib/seahorse/util.rb +4 -0
  84. metadata +47 -6
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'time'
4
4
  require 'net/http'
5
+ require 'resolv'
5
6
 
6
7
  module Aws
7
8
  # An auto-refreshing credential provider that loads credentials from
@@ -10,7 +11,6 @@ module Aws
10
11
  # ecs_credentials = Aws::ECSCredentials.new(retries: 3)
11
12
  # ec2 = Aws::EC2::Client.new(credentials: ecs_credentials)
12
13
  class ECSCredentials
13
-
14
14
  include CredentialProvider
15
15
  include RefreshingCredentials
16
16
 
@@ -29,16 +29,22 @@ module Aws
29
29
  Errno::ENETUNREACH,
30
30
  SocketError,
31
31
  Timeout::Error,
32
- Non200Response,
33
- ]
32
+ Non200Response
33
+ ].freeze
34
34
 
35
35
  # @param [Hash] options
36
36
  # @option options [Integer] :retries (5) Number of times to retry
37
37
  # when retrieving credentials.
38
- # @option options [String] :ip_address ('169.254.170.2')
39
- # @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.
40
42
  # @option options [String] :credential_path By default, the value of the
41
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.
42
48
  # @option options [Float] :http_open_timeout (5)
43
49
  # @option options [Float] :http_read_timeout (5)
44
50
  # @option options [Numeric, Proc] :delay By default, failures are retried
@@ -52,17 +58,15 @@ module Aws
52
58
  # credentials are refreshed. `before_refresh` is called
53
59
  # with an instance of this object when
54
60
  # AWS credentials are required and need to be refreshed.
55
- def initialize options = {}
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
+
56
69
  @retries = options[:retries] || 5
57
- @ip_address = options[:ip_address] || '169.254.170.2'
58
- @port = options[:port] || 80
59
- @credential_path = options[:credential_path]
60
- @credential_path ||= ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
61
- unless @credential_path
62
- raise ArgumentError.new(
63
- "Cannot instantiate an ECS Credential Provider without a credential path."
64
- )
65
- end
66
70
  @http_open_timeout = options[:http_open_timeout] || 5
67
71
  @http_read_timeout = options[:http_read_timeout] || 5
68
72
  @http_debug_output = options[:http_debug_output]
@@ -77,11 +81,69 @@ module Aws
77
81
 
78
82
  private
79
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
+
80
142
  def backoff(backoff)
81
143
  case backoff
82
144
  when Proc then backoff
83
- when Numeric then lambda { |_| sleep(backoff) }
84
- 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) }
85
147
  end
86
148
  end
87
149
 
@@ -89,68 +151,64 @@ module Aws
89
151
  # Retry loading credentials up to 3 times is the instance metadata
90
152
  # service is responding but is returning invalid JSON documents
91
153
  # in response to the GET profile credentials call.
92
- begin
93
- retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
94
- c = Aws::Json.load(get_credentials.to_s)
95
- @credentials = Credentials.new(
96
- c['AccessKeyId'],
97
- c['SecretAccessKey'],
98
- c['Token']
99
- )
100
- @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
101
- end
102
- rescue Aws::Json::ParseError
103
- 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
104
163
  end
164
+ rescue Aws::Json::ParseError
165
+ raise Aws::Errors::MetadataParserError
105
166
  end
106
167
 
107
168
  def get_credentials
108
169
  # Retry loading credentials a configurable number of times if
109
170
  # the instance metadata service is not responding.
110
- begin
111
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
112
- open_connection do |conn|
113
- http_get(conn, @credential_path)
114
- end
171
+
172
+ retry_errors(NETWORK_ERRORS, max_retries: @retries) do
173
+ open_connection do |conn|
174
+ http_get(conn, @credential_path)
115
175
  end
116
- rescue
117
- '{}'
118
176
  end
177
+ rescue StandardError
178
+ '{}'
119
179
  end
120
180
 
121
181
  def open_connection
122
- http = Net::HTTP.new(@ip_address, @port, nil)
182
+ http = Net::HTTP.new(@host, @port, nil)
123
183
  http.open_timeout = @http_open_timeout
124
184
  http.read_timeout = @http_read_timeout
125
185
  http.set_debug_output(@http_debug_output) if @http_debug_output
186
+ http.use_ssl = @scheme == 'https'
126
187
  http.start
127
188
  yield(http).tap { http.finish }
128
189
  end
129
190
 
130
191
  def http_get(connection, path)
131
- response = connection.request(Net::HTTP::Get.new(path))
132
- if response.code.to_i == 200
133
- response.body
134
- else
135
- raise Non200Response
136
- 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
137
198
  end
138
199
 
139
- def retry_errors(error_classes, options = {}, &block)
200
+ def retry_errors(error_classes, options = {})
140
201
  max_retries = options[:max_retries]
141
202
  retries = 0
142
203
  begin
143
204
  yield
144
- rescue *error_classes => _error
145
- if retries < max_retries
146
- @backoff.call(retries)
147
- retries += 1
148
- retry
149
- else
150
- raise
151
- end
205
+ rescue *error_classes => _e
206
+ raise unless retries < max_retries
207
+
208
+ @backoff.call(retries)
209
+ retries += 1
210
+ retry
152
211
  end
153
212
  end
154
-
155
213
  end
156
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
@@ -0,0 +1,75 @@
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. # @api private
10
+ class EndpointRule < Rule
11
+ def initialize(type: 'endpoint', conditions:, endpoint:,
12
+ documentation: nil)
13
+ @type = type
14
+ @conditions = Condition.from_json(conditions)
15
+ @endpoint = endpoint
16
+ @documentation = documentation
17
+ end
18
+
19
+ attr_reader :type
20
+ attr_reader :conditions
21
+ attr_reader :endpoint
22
+ attr_reader :documentation
23
+
24
+ def match(parameters, assigned = {})
25
+ assigns = assigned.dup
26
+ matched = conditions.all? do |condition|
27
+ output = condition.match?(parameters, assigns)
28
+ assigns = assigns.merge(condition.assigned) if condition.assign
29
+ output
30
+ end
31
+ resolved_endpoint(parameters, assigns) if matched
32
+ end
33
+
34
+ def resolved_endpoint(parameters, assigns)
35
+ Endpoint.new(
36
+ url: resolve_value(@endpoint['url'], parameters, assigns),
37
+ properties: resolve_properties(
38
+ @endpoint['properties'] || {},
39
+ parameters,
40
+ assigns
41
+ ),
42
+ headers: resolve_headers(parameters, assigns)
43
+ )
44
+ end
45
+
46
+ private
47
+
48
+ def resolve_headers(parameters, assigns)
49
+ (@endpoint['headers'] || {}).each.with_object({}) do |(key, arr), headers|
50
+ headers[key] = []
51
+ arr.each do |value|
52
+ headers[key] << resolve_value(value, parameters, assigns)
53
+ end
54
+ end
55
+ end
56
+
57
+ def resolve_properties(obj, parameters, assigns)
58
+ case obj
59
+ when Hash
60
+ obj.each.with_object({}) do |(key, value), hash|
61
+ hash[key] = resolve_properties(value, parameters, assigns)
62
+ end
63
+ when Array
64
+ obj.collect { |value| resolve_properties(value, parameters, assigns) }
65
+ else
66
+ if obj.is_a?(String)
67
+ Templater.resolve(obj, parameters, assigns)
68
+ else
69
+ obj
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,42 @@
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 ErrorRule < Rule
12
+ def initialize(type: 'error', conditions:, error: nil, documentation: nil)
13
+ @type = type
14
+ @conditions = Condition.from_json(conditions)
15
+ @error = error
16
+ @documentation = documentation
17
+ end
18
+
19
+ attr_reader :type
20
+ attr_reader :conditions
21
+ attr_reader :error
22
+ attr_reader :documentation
23
+
24
+ def match(parameters, assigned = {})
25
+ assigns = assigned.dup
26
+ matched = conditions.all? do |condition|
27
+ output = condition.match?(parameters, assigns)
28
+ assigns = assigns.merge(condition.assigned) if condition.assign
29
+ output
30
+ end
31
+ resolved_error(parameters, assigns) if matched
32
+ end
33
+
34
+ private
35
+
36
+ def resolved_error(parameters, assigns)
37
+ error = resolve_value(@error, parameters, assigns)
38
+ ArgumentError.new(error)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,80 @@
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 Function
12
+ def initialize(fn:, argv:)
13
+ @fn = fn
14
+ @argv = build_argv(argv)
15
+ end
16
+
17
+ attr_reader :fn
18
+ attr_reader :argv
19
+
20
+ def call(parameters, assigns)
21
+ args = []
22
+ @argv.each do |arg|
23
+ if arg.is_a?(Reference)
24
+ args << arg.resolve(parameters, assigns)
25
+ elsif arg.is_a?(Function)
26
+ args << arg.call(parameters, assigns)
27
+ else
28
+ if arg.is_a?(String)
29
+ arg = Templater.resolve(arg, parameters, assigns)
30
+ end
31
+ args << arg
32
+ end
33
+ end
34
+
35
+ case @fn
36
+ when 'isSet'
37
+ Matchers.set?(*args)
38
+ when 'not'
39
+ Matchers.not(*args)
40
+ when 'getAttr'
41
+ Matchers.attr(*args)
42
+ when 'substring'
43
+ Matchers.substring(*args)
44
+ when 'stringEquals'
45
+ Matchers.string_equals?(*args)
46
+ when 'booleanEquals'
47
+ Matchers.boolean_equals?(*args)
48
+ when 'uriEncode'
49
+ Matchers.uri_encode(*args)
50
+ when 'parseURL'
51
+ Matchers.parse_url(*args)
52
+ when 'isValidHostLabel'
53
+ Matchers.valid_host_label?(*args)
54
+ when 'aws.partition'
55
+ Matchers.aws_partition(*args)
56
+ when 'aws.parseArn'
57
+ Matchers.aws_parse_arn(*args)
58
+ when 'aws.isVirtualHostableS3Bucket'
59
+ Matchers.aws_virtual_hostable_s3_bucket?(*args)
60
+ else
61
+ raise "Function not found: #{@fn}"
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def build_argv(argv_json)
68
+ argv_json.each.with_object([]) do |arg, argv|
69
+ argv << if arg.is_a?(Hash) && arg['ref']
70
+ Reference.new(ref: arg['ref'])
71
+ elsif arg.is_a?(Hash) && arg['fn']
72
+ Function.new(fn: arg['fn'], argv: arg['argv'])
73
+ else
74
+ arg
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ module Aws
6
+ module Endpoints
7
+ # generic matcher functions for service endpoints
8
+ # @api private
9
+ module Matchers
10
+ # Regex that extracts anything in square brackets
11
+ BRACKET_REGEX = /\[(.*?)\]/.freeze
12
+
13
+ # CORE
14
+
15
+ # isSet(value: Option<T>) bool
16
+ def self.set?(value)
17
+ !value.nil?
18
+ end
19
+
20
+ # not(value: bool) bool
21
+ def self.not(bool)
22
+ !bool
23
+ end
24
+
25
+ # getAttr(value: Object | Array, path: string) Document
26
+ def self.attr(value, path)
27
+ parts = path.split('.')
28
+
29
+ val = if (index = parts.first[BRACKET_REGEX, 1])
30
+ # remove brackets and index from part before indexing
31
+ value[parts.first.gsub(BRACKET_REGEX, '')][index.to_i]
32
+ else
33
+ value[parts.first]
34
+ end
35
+
36
+ if parts.size == 1
37
+ val
38
+ else
39
+ attr(val, parts.slice(1..-1).join('.'))
40
+ end
41
+ end
42
+
43
+ def self.substring(input, start, stop, reverse)
44
+ return nil if start >= stop || input.size < stop
45
+
46
+ return nil if input.chars.any? { |c| c.ord > 127 }
47
+
48
+ return input[start...stop] unless reverse
49
+
50
+ r_start = input.size - stop
51
+ r_stop = input.size - start
52
+ input[r_start...r_stop]
53
+ end
54
+
55
+ # stringEquals(value1: string, value2: string) bool
56
+ def self.string_equals?(value1, value2)
57
+ value1 == value2
58
+ end
59
+
60
+ # booleanEquals(value1: bool, value2: bool) bool
61
+ def self.boolean_equals?(value1, value2)
62
+ value1 == value2
63
+ end
64
+
65
+ # uriEncode(value: string) string
66
+ def self.uri_encode(value)
67
+ CGI.escape(value.encode('UTF-8')).gsub('+', '%20').gsub('%7E', '~')
68
+ end
69
+
70
+ # parseUrl(value: string) Option<URL>
71
+ def self.parse_url(value)
72
+ URL.new(value).as_json
73
+ rescue ArgumentError, URI::InvalidURIError
74
+ nil
75
+ end
76
+
77
+ # isValidHostLabel(value: string, allowSubDomains: bool) bool
78
+ def self.valid_host_label?(value, allow_sub_domains = false)
79
+ return false if value.empty?
80
+
81
+ if allow_sub_domains
82
+ labels = value.split('.')
83
+ return labels.all? { |l| valid_host_label?(l) }
84
+ end
85
+
86
+ value =~ /\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z/
87
+ end
88
+
89
+ # AWS
90
+
91
+ # aws.partition(value: string) Option<Partition>
92
+ def self.aws_partition(value)
93
+ partition =
94
+ Aws::Partitions.find { |p| p.region?(value) } ||
95
+ Aws::Partitions.find { |p| value.match(p.region_regex) } ||
96
+ Aws::Partitions.find { |p| p.name == 'aws' }
97
+
98
+ return nil unless partition
99
+
100
+ partition.metadata
101
+ end
102
+
103
+ # aws.parseArn(value: string) Option<ARN>
104
+ def self.aws_parse_arn(value)
105
+ arn = Aws::ARNParser.parse(value)
106
+ json = arn.as_json
107
+ # HACK: because of poor naming and also requirement of splitting
108
+ resource = json.delete('resource')
109
+ json['resourceId'] = resource.split(%r{[:\/]}, -1)
110
+ json
111
+ rescue Aws::Errors::InvalidARNError
112
+ nil
113
+ end
114
+
115
+ # aws.isVirtualHostableS3Bucket(value: string, allowSubDomains: bool) bool
116
+ def self.aws_virtual_hostable_s3_bucket?(value, allow_sub_domains = false)
117
+ !!(value.size < 64 &&
118
+ # regular naming rules
119
+ value =~ /^[a-z0-9][a-z0-9\-#{'.' if allow_sub_domains}]+[a-z0-9]$/ &&
120
+ # not IP address
121
+ value !~ /(\d+\.){3}\d+/ &&
122
+ # no dash and hyphen together
123
+ value !~ /[.-]{2}/)
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,31 @@
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 Reference
12
+ def initialize(ref:)
13
+ @ref = ref
14
+ end
15
+
16
+ attr_reader :ref
17
+
18
+ def resolve(parameters, assigns)
19
+ if parameters.class.singleton_class::PARAM_MAP.key?(@ref)
20
+ member_name = parameters.class.singleton_class::PARAM_MAP[@ref]
21
+ parameters[member_name]
22
+ elsif assigns.key?(@ref)
23
+ assigns[@ref]
24
+ else
25
+ raise ArgumentError,
26
+ "Reference #{@ref} is not a param or an assigned value."
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
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 Rule
12
+ # Resolves a value that is a function, reference, or template string.
13
+ def resolve_value(value, parameters, assigns)
14
+ if value.is_a?(Hash) && value['fn']
15
+ Function.new(fn: value['fn'], argv: value['argv'])
16
+ .call(parameters, assigns)
17
+ elsif value.is_a?(Hash) && value['ref']
18
+ Reference.new(ref: value['ref']).resolve(parameters, assigns)
19
+ else
20
+ Templater.resolve(value, parameters, assigns)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end