aws-sdk-core 3.171.1 → 3.234.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.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +787 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +5 -6
  5. data/lib/aws-defaults.rb +4 -1
  6. data/lib/aws-sdk-core/arn.rb +1 -3
  7. data/lib/aws-sdk-core/assume_role_credentials.rb +21 -13
  8. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +16 -9
  9. data/lib/aws-sdk-core/binary/decode_handler.rb +3 -9
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
  11. data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
  12. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
  13. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
  14. data/lib/aws-sdk-core/cbor/decoder.rb +308 -0
  15. data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
  16. data/lib/aws-sdk-core/cbor.rb +53 -0
  17. data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
  18. data/lib/aws-sdk-core/client_stubs.rb +33 -55
  19. data/lib/aws-sdk-core/credential_provider.rb +8 -1
  20. data/lib/aws-sdk-core/credential_provider_chain.rb +74 -25
  21. data/lib/aws-sdk-core/credentials.rb +19 -6
  22. data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
  23. data/lib/aws-sdk-core/ecs_credentials.rb +92 -24
  24. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  25. data/lib/aws-sdk-core/endpoints/matchers.rb +21 -19
  26. data/lib/aws-sdk-core/endpoints.rb +106 -22
  27. data/lib/aws-sdk-core/error_handler.rb +46 -0
  28. data/lib/aws-sdk-core/errors.rb +14 -5
  29. data/lib/aws-sdk-core/event_emitter.rb +1 -17
  30. data/lib/aws-sdk-core/ini_parser.rb +7 -0
  31. data/lib/aws-sdk-core/instance_profile_credentials.rb +168 -155
  32. data/lib/aws-sdk-core/json/builder.rb +8 -1
  33. data/lib/aws-sdk-core/json/error_handler.rb +29 -13
  34. data/lib/aws-sdk-core/json/handler.rb +13 -6
  35. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  36. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  37. data/lib/aws-sdk-core/json/parser.rb +33 -3
  38. data/lib/aws-sdk-core/json.rb +43 -14
  39. data/lib/aws-sdk-core/log/formatter.rb +6 -0
  40. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  41. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  42. data/lib/aws-sdk-core/log.rb +10 -0
  43. data/lib/aws-sdk-core/lru_cache.rb +75 -0
  44. data/lib/aws-sdk-core/pageable_response.rb +3 -1
  45. data/lib/aws-sdk-core/param_validator.rb +9 -4
  46. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  47. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +348 -169
  48. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -1
  49. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
  50. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +78 -56
  51. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  52. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  53. data/lib/aws-sdk-core/plugins/http_checksum.rb +3 -8
  54. data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
  55. data/lib/aws-sdk-core/plugins/logging.rb +2 -0
  56. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  57. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  58. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  59. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  60. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
  61. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
  62. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  63. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +162 -37
  64. data/lib/aws-sdk-core/plugins/request_compression.rb +226 -0
  65. data/lib/aws-sdk-core/plugins/retry_errors.rb +12 -3
  66. data/lib/aws-sdk-core/plugins/sign.rb +55 -33
  67. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  68. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  69. data/lib/aws-sdk-core/plugins/stub_responses.rb +59 -9
  70. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  71. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  72. data/lib/aws-sdk-core/plugins/user_agent.rb +192 -14
  73. data/lib/aws-sdk-core/plugins.rb +39 -0
  74. data/lib/aws-sdk-core/process_credentials.rb +48 -29
  75. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  76. data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
  77. data/lib/aws-sdk-core/query/handler.rb +4 -4
  78. data/lib/aws-sdk-core/query/param_builder.rb +2 -2
  79. data/lib/aws-sdk-core/query.rb +2 -1
  80. data/lib/aws-sdk-core/refreshing_credentials.rb +20 -23
  81. data/lib/aws-sdk-core/resources.rb +8 -0
  82. data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
  83. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  84. data/lib/aws-sdk-core/rest/request/body.rb +32 -5
  85. data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
  86. data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
  87. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +62 -36
  88. data/lib/aws-sdk-core/rest/response/body.rb +15 -1
  89. data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
  90. data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
  91. data/lib/aws-sdk-core/rest.rb +1 -0
  92. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  93. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  94. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  95. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
  96. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  97. data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
  98. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  99. data/lib/aws-sdk-core/shared_config.rb +135 -39
  100. data/lib/aws-sdk-core/shared_credentials.rb +1 -7
  101. data/lib/aws-sdk-core/sso_credentials.rb +6 -3
  102. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  103. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  104. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  105. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  106. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  107. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  108. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  109. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  110. data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
  111. data/lib/aws-sdk-core/stubbing.rb +22 -0
  112. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  113. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  114. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  115. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  116. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  117. data/lib/aws-sdk-core/telemetry.rb +78 -0
  118. data/lib/aws-sdk-core/token.rb +3 -3
  119. data/lib/aws-sdk-core/token_provider.rb +4 -0
  120. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  121. data/lib/aws-sdk-core/util.rb +41 -1
  122. data/lib/aws-sdk-core/waiters/poller.rb +12 -5
  123. data/lib/aws-sdk-core/xml/builder.rb +17 -9
  124. data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
  125. data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
  126. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  127. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  128. data/lib/aws-sdk-core.rb +82 -107
  129. data/lib/aws-sdk-sso/client.rb +205 -92
  130. data/lib/aws-sdk-sso/client_api.rb +7 -0
  131. data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
  132. data/lib/aws-sdk-sso/endpoint_provider.rb +30 -28
  133. data/lib/aws-sdk-sso/endpoints.rb +3 -54
  134. data/lib/aws-sdk-sso/plugins/endpoints.rb +23 -22
  135. data/lib/aws-sdk-sso/types.rb +1 -0
  136. data/lib/aws-sdk-sso.rb +15 -11
  137. data/lib/aws-sdk-ssooidc/client.rb +625 -125
  138. data/lib/aws-sdk-ssooidc/client_api.rb +94 -1
  139. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
  140. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -28
  141. data/lib/aws-sdk-ssooidc/endpoints.rb +3 -40
  142. data/lib/aws-sdk-ssooidc/errors.rb +62 -0
  143. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +23 -20
  144. data/lib/aws-sdk-ssooidc/types.rb +419 -53
  145. data/lib/aws-sdk-ssooidc.rb +15 -11
  146. data/lib/aws-sdk-sts/client.rb +526 -243
  147. data/lib/aws-sdk-sts/client_api.rb +48 -9
  148. data/lib/aws-sdk-sts/customizations.rb +5 -2
  149. data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
  150. data/lib/aws-sdk-sts/endpoint_provider.rb +82 -84
  151. data/lib/aws-sdk-sts/endpoints.rb +3 -118
  152. data/lib/aws-sdk-sts/errors.rb +15 -0
  153. data/lib/aws-sdk-sts/plugins/endpoints.rb +23 -30
  154. data/lib/aws-sdk-sts/presigner.rb +3 -7
  155. data/lib/aws-sdk-sts/types.rb +217 -36
  156. data/lib/aws-sdk-sts.rb +15 -11
  157. data/lib/seahorse/client/async_base.rb +4 -5
  158. data/lib/seahorse/client/async_response.rb +19 -0
  159. data/lib/seahorse/client/base.rb +18 -21
  160. data/lib/seahorse/client/configuration.rb +0 -4
  161. data/lib/seahorse/client/h2/connection.rb +18 -28
  162. data/lib/seahorse/client/h2/handler.rb +14 -3
  163. data/lib/seahorse/client/handler.rb +1 -1
  164. data/lib/seahorse/client/http/response.rb +1 -1
  165. data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
  166. data/lib/seahorse/client/net_http/handler.rb +21 -9
  167. data/lib/seahorse/client/net_http/patches.rb +1 -4
  168. data/lib/seahorse/client/networking_error.rb +1 -1
  169. data/lib/seahorse/client/plugin.rb +9 -0
  170. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  171. data/lib/seahorse/client/plugins/h2.rb +4 -4
  172. data/lib/seahorse/client/plugins/net_http.rb +57 -16
  173. data/lib/seahorse/client/plugins/request_callback.rb +31 -0
  174. data/lib/seahorse/client/request_context.rb +9 -2
  175. data/lib/seahorse/client/response.rb +8 -0
  176. data/lib/seahorse/model/operation.rb +3 -0
  177. data/lib/seahorse/model/shapes.rb +2 -2
  178. data/lib/seahorse/util.rb +2 -1
  179. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  180. data/sig/aws-sdk-core/client_stubs.rbs +10 -0
  181. data/sig/aws-sdk-core/errors.rbs +22 -0
  182. data/sig/aws-sdk-core/resources/collection.rbs +21 -0
  183. data/sig/aws-sdk-core/structure.rbs +4 -0
  184. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  185. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  186. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  187. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  188. data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
  189. data/sig/aws-sdk-core.rbs +7 -0
  190. data/sig/seahorse/client/async_base.rbs +18 -0
  191. data/sig/seahorse/client/base.rbs +25 -0
  192. data/sig/seahorse/client/handler_builder.rbs +16 -0
  193. data/sig/seahorse/client/response.rbs +61 -0
  194. metadata +106 -23
  195. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  196. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  197. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  198. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  199. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -13,10 +13,6 @@ module Aws
13
13
  option(:sigv4_region)
14
14
  option(:unsigned_operations, default: [])
15
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
16
  def add_handlers(handlers, cfg)
21
17
  operations = cfg.api.operation_names - cfg.unsigned_operations
22
18
  handlers.add(Handler, step: :sign, operations: operations)
@@ -24,12 +20,16 @@ module Aws
24
20
 
25
21
  # @api private
26
22
  # Return a signer with the `sign(context)` method
27
- def self.signer_for(auth_scheme, config, region_override = nil)
23
+ def self.signer_for(auth_scheme, config, sigv4_region_override = nil, sigv4_credentials_override = nil)
28
24
  case auth_scheme['name']
29
- when 'sigv4', 'sigv4a'
30
- SignatureV4.new(auth_scheme, config, region_override)
25
+ when 'sigv4', 'sigv4a', 'sigv4-s3express'
26
+ sigv4_overrides = {
27
+ region: sigv4_region_override,
28
+ credentials: sigv4_credentials_override
29
+ }
30
+ SignatureV4.new(auth_scheme, config, sigv4_overrides)
31
31
  when 'bearer'
32
- Bearer.new
32
+ Bearer.new(config)
33
33
  else
34
34
  NullSigner.new
35
35
  end
@@ -42,15 +42,27 @@ module Aws
42
42
  signer = Sign.signer_for(
43
43
  context[:auth_scheme],
44
44
  context.config,
45
- context[:sigv4_region]
45
+ context[:sigv4_region],
46
+ context[:sigv4_credentials]
46
47
  )
47
48
  signer.sign(context)
48
49
  end
49
- @handler.call(context)
50
+ with_metrics(signer) { @handler.call(context) }
50
51
  end
51
52
 
52
53
  private
53
54
 
55
+ def with_metrics(signer, &block)
56
+ case signer
57
+ when SignatureV4
58
+ Aws::Plugins::UserAgent.metric(*signer.credentials.metrics, &block)
59
+ when Bearer
60
+ Aws::Plugins::UserAgent.metric(*signer.token_provider.metrics, &block)
61
+ else
62
+ block.call
63
+ end
64
+ end
65
+
54
66
  def v2_signing?(config)
55
67
  # 's3' is legacy signing, 'v4' is default
56
68
  config.respond_to?(:signature_version) &&
@@ -60,21 +72,19 @@ module Aws
60
72
 
61
73
  # @api private
62
74
  class Bearer
63
- def initialize
75
+ def initialize(config)
76
+ @token_provider = config.token_provider
64
77
  end
65
78
 
79
+ attr_reader :token_provider
80
+
66
81
  def sign(context)
67
82
  if context.http_request.endpoint.scheme != 'https'
68
- raise ArgumentError,
69
- 'Unable to use bearer authorization on non https endpoint.'
83
+ raise ArgumentError, 'Unable to use bearer authorization on non https endpoint.'
70
84
  end
85
+ raise Errors::MissingBearerTokenError unless @token_provider && @token_provider.set?
71
86
 
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}"
87
+ context.http_request.headers['Authorization'] = "Bearer #{@token_provider.token.token}"
78
88
  end
79
89
 
80
90
  def presign_url(*args)
@@ -88,33 +98,33 @@ module Aws
88
98
 
89
99
  # @api private
90
100
  class SignatureV4
91
- def initialize(auth_scheme, config, region_override = nil)
101
+ def initialize(auth_scheme, config, sigv4_overrides = {})
92
102
  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}"
103
+ unless %w[sigv4 sigv4a sigv4-s3express].include?(scheme_name)
104
+ raise ArgumentError, "Expected sigv4, sigv4a, or sigv4-s3express auth scheme, got #{scheme_name}"
97
105
  end
98
-
99
106
  region = if scheme_name == 'sigv4a'
100
- auth_scheme['signingRegionSet'].first
107
+ auth_scheme['signingRegionSet'].join(',')
101
108
  else
102
109
  auth_scheme['signingRegion']
103
110
  end
104
111
  begin
105
- @signer = Aws::Sigv4::Signer.new(
112
+ @signer = config.sigv4_signer || Aws::Sigv4::Signer.new(
106
113
  service: config.sigv4_name || auth_scheme['signingName'],
107
- region: region_override || config.sigv4_region || region,
108
- credentials_provider: config.credentials,
114
+ region: sigv4_overrides[:region] || config.sigv4_region || region,
115
+ credentials_provider: sigv4_overrides[:credentials] || config.credentials,
109
116
  signing_algorithm: scheme_name.to_sym,
110
- uri_escape_path: !!!auth_scheme['disableDoubleEncoding'],
111
- unsigned_headers: %w[content-length user-agent x-amzn-trace-id]
117
+ uri_escape_path: !auth_scheme['disableDoubleEncoding'],
118
+ normalize_path: !auth_scheme['disableNormalizePath'],
119
+ unsigned_headers: %w[content-length user-agent x-amzn-trace-id expect transfer-encoding connection]
112
120
  )
113
121
  rescue Aws::Sigv4::Errors::MissingCredentialsError
114
122
  raise Aws::Errors::MissingCredentialsError
115
123
  end
116
124
  end
117
125
 
126
+ attr_reader :signer
127
+
118
128
  def sign(context)
119
129
  req = context.http_request
120
130
 
@@ -150,15 +160,27 @@ module Aws
150
160
  @signer.sign_event(*args)
151
161
  end
152
162
 
163
+ def credentials
164
+ @signer.credentials_provider
165
+ end
166
+
153
167
  private
154
168
 
155
169
  def apply_authtype(context, req)
156
- if context.operation['authtype'].eql?('v4-unsigned-body') &&
157
- req.endpoint.scheme.eql?('https')
170
+ # only used for event streaming at input
171
+ if context[:input_event_emitter]
172
+ req.headers['X-Amz-Content-Sha256'] = 'STREAMING-AWS4-HMAC-SHA256-EVENTS'
173
+ elsif unsigned_payload?(context, req)
158
174
  req.headers['X-Amz-Content-Sha256'] ||= 'UNSIGNED-PAYLOAD'
159
175
  end
160
176
  end
161
177
 
178
+ def unsigned_payload?(context, req)
179
+ (context.operation['unsignedPayload'] ||
180
+ context.operation['authtype'] == 'v4-unsigned-body') &&
181
+ req.endpoint.scheme == 'https'
182
+ end
183
+
162
184
  def reset_signature(req)
163
185
  # in case this request is being re-signed
164
186
  req.headers.delete('Authorization')
@@ -3,7 +3,8 @@
3
3
  module Aws
4
4
  module Plugins
5
5
  # @api private
6
- # Necessary to keep after Endpoints 2.0
6
+ # Deprecated - does not look at new traits like `auth` and `unsignedPayload`
7
+ # Necessary to exist after endpoints 2.0 for old service clients + new core
7
8
  class SignatureV2 < Seahorse::Client::Plugin
8
9
 
9
10
  option(:v2_signer) do |cfg|
@@ -5,7 +5,8 @@ require 'aws-sigv4'
5
5
  module Aws
6
6
  module Plugins
7
7
  # @api private
8
- # Necessary to exist after endpoints 2.0
8
+ # Deprecated - does not look at new traits like `auth` and `unsignedPayload`
9
+ # Necessary to exist after endpoints 2.0 for old service clients + new core
9
10
  class SignatureV4 < Seahorse::Client::Plugin
10
11
 
11
12
  V4_AUTH = %w[v4 v4-unsigned-payload v4-unsigned-body]
@@ -8,6 +8,7 @@ module Aws
8
8
  option(:stub_responses,
9
9
  default: false,
10
10
  doc_type: 'Boolean',
11
+ rbs_type: 'untyped',
11
12
  docstring: <<-DOCS)
12
13
  Causes the client to return stubbed responses. By default
13
14
  fake responses are generated and returned. You can specify
@@ -28,8 +29,22 @@ requests are made, and retries are disabled.
28
29
  end
29
30
  end
30
31
 
32
+ option(:token_provider) do |config|
33
+ if config.stub_responses
34
+ StaticTokenProvider.new('stubbed-token')
35
+ end
36
+ end
37
+
38
+ option(:stubs) { {} }
39
+ option(:stubs_mutex) { Mutex.new }
40
+ option(:api_requests) { [] }
41
+ option(:api_requests_mutex) { Mutex.new }
42
+
31
43
  def add_handlers(handlers, config)
32
- handlers.add(Handler, step: :send) if config.stub_responses
44
+ return unless config.stub_responses
45
+
46
+ handlers.add(ApiRequestsHandler)
47
+ handlers.add(StubbingHandler, step: :send)
33
48
  end
34
49
 
35
50
  def after_initialize(client)
@@ -45,20 +60,43 @@ requests are made, and retries are disabled.
45
60
  end
46
61
  end
47
62
 
48
- class Handler < Seahorse::Client::Handler
63
+ class ApiRequestsHandler < Seahorse::Client::Handler
64
+ def call(context)
65
+ context.config.api_requests_mutex.synchronize do
66
+ context.config.api_requests << {
67
+ operation_name: context.operation_name,
68
+ params: context.params,
69
+ context: context
70
+ }
71
+ end
72
+ @handler.call(context)
73
+ end
74
+ end
49
75
 
76
+ class StubbingHandler < Seahorse::Client::Handler
50
77
  def call(context)
51
- stub = context.client.next_stub(context)
78
+ span_wrapper(context) do
79
+ stub_responses(context)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def stub_responses(context)
52
86
  resp = Seahorse::Client::Response.new(context: context)
53
87
  async_mode = context.client.is_a? Seahorse::Client::AsyncBase
54
- if Hash === stub && stub[:mutex]
55
- stub[:mutex].synchronize { apply_stub(stub, resp, async_mode) }
88
+ stub = context.client.next_stub(context)
89
+ stub[:mutex].synchronize { apply_stub(stub, resp, async_mode) }
90
+
91
+ if async_mode
92
+ Seahorse::Client::AsyncResponse.new(
93
+ context: context,
94
+ stream: context[:input_event_stream_handler].event_emitter.stream,
95
+ sync_queue: Queue.new
96
+ )
56
97
  else
57
- apply_stub(stub, resp, async_mode)
98
+ resp
58
99
  end
59
-
60
- async_mode ? Seahorse::Client::AsyncResponse.new(
61
- context: context, stream: context[:input_event_stream_handler].event_emitter.stream, sync_queue: Queue.new) : resp
62
100
  end
63
101
 
64
102
  def apply_stub(stub, response, async_mode = false)
@@ -98,6 +136,18 @@ requests are made, and retries are disabled.
98
136
  http_resp.signal_done
99
137
  end
100
138
 
139
+ def span_wrapper(context, &block)
140
+ context.tracer.in_span(
141
+ 'Handler.StubResponses',
142
+ attributes: Aws::Telemetry.http_request_attrs(context)
143
+ ) do |span|
144
+ block.call.tap do
145
+ span.add_attributes(
146
+ Aws::Telemetry.http_response_attrs(context)
147
+ )
148
+ end
149
+ end
150
+ end
101
151
  end
102
152
  end
103
153
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Plugins
5
+ # @api private
6
+ class Telemetry < Seahorse::Client::Plugin
7
+ option(
8
+ :telemetry_provider,
9
+ default: Aws::Telemetry::NoOpTelemetryProvider,
10
+ doc_type: Aws::Telemetry::TelemetryProviderBase,
11
+ rbs_type: Aws::Telemetry::TelemetryProviderBase,
12
+ docstring: <<-DOCS) do |_cfg|
13
+ Allows you to provide a telemetry provider, which is used to
14
+ emit telemetry data. By default, uses `NoOpTelemetryProvider` which
15
+ will not record or emit any telemetry data. The SDK supports the
16
+ following telemetry providers:
17
+
18
+ * OpenTelemetry (OTel) - To use the OTel provider, install and require the
19
+ `opentelemetry-sdk` gem and then, pass in an instance of a
20
+ `Aws::Telemetry::OTelProvider` for telemetry provider.
21
+ DOCS
22
+ Aws::Telemetry::NoOpTelemetryProvider.new
23
+ end
24
+
25
+ def after_initialize(client)
26
+ validate_telemetry_provider(client.config)
27
+ end
28
+
29
+ def validate_telemetry_provider(config)
30
+ unless config.telemetry_provider.is_a?(Aws::Telemetry::TelemetryProviderBase)
31
+ raise ArgumentError,
32
+ 'Must provide a telemetry provider for the '\
33
+ '`telemetry_provider` configuration option.'
34
+ end
35
+ end
36
+
37
+ class Handler < Seahorse::Client::Handler
38
+ def call(context)
39
+ span_wrapper(context) { @handler.call(context) }
40
+ end
41
+
42
+ private
43
+
44
+ def span_wrapper(context, &block)
45
+ service_id = service_id(context)
46
+ attributes = {
47
+ 'rpc.system' => 'aws-api',
48
+ 'rpc.service' => service_id,
49
+ 'rpc.method' => context.operation.name,
50
+ 'code.function' => context.operation_name.to_s,
51
+ 'code.namespace' => 'Aws::Plugins::Telemetry'
52
+ }
53
+ context.tracer.in_span(
54
+ parent_span_name(context, service_id),
55
+ attributes: attributes,
56
+ kind: Aws::Telemetry::SpanKind::CLIENT,
57
+ &block
58
+ )
59
+ end
60
+
61
+ def service_id(context)
62
+ context.config.api.metadata['serviceId'] ||
63
+ context.config.api.metadata['serviceAbbreviation'] ||
64
+ context.config.api.metadata['serviceFullName']
65
+ end
66
+
67
+ def parent_span_name(context, service_id)
68
+ "#{service_id}.#{context.operation.name}".delete(' ')
69
+ end
70
+ end
71
+
72
+ handler(Handler, step: :initialize, priority: 99)
73
+ end
74
+ end
75
+ end
@@ -5,7 +5,8 @@ module Aws
5
5
 
6
6
  # For Streaming Input Operations, when `requiresLength` is enabled
7
7
  # checking whether `Content-Length` header can be set,
8
- # for `v4-unsigned-body` operations, set `Transfer-Encoding` header
8
+ # for `unsignedPayload` and `v4-unsigned-body` operations,
9
+ # set `Transfer-Encoding` header.
9
10
  class TransferEncoding < Seahorse::Client::Plugin
10
11
 
11
12
  # @api private
@@ -16,8 +17,8 @@ module Aws
16
17
  unless context.http_request.body.respond_to?(:size)
17
18
  if requires_length?(context.operation.input)
18
19
  # if size of the IO is not available but required
19
- raise Aws::Errors::MissingContentLength.new
20
- elsif context.operation['authtype'] == "v4-unsigned-body"
20
+ raise Aws::Errors::MissingContentLength
21
+ elsif unsigned_payload?(context.operation)
21
22
  context.http_request.headers['Transfer-Encoding'] = 'chunked'
22
23
  end
23
24
  end
@@ -29,18 +30,24 @@ module Aws
29
30
  private
30
31
 
31
32
  def streaming?(ref)
32
- if payload = ref[:payload_member]
33
- payload["streaming"] || # checking ref and shape
34
- payload.shape["streaming"]
33
+ if (payload = ref[:payload_member])
34
+ payload['streaming'] || payload.shape['streaming']
35
35
  else
36
36
  false
37
37
  end
38
38
  end
39
39
 
40
+ def unsigned_payload?(operation)
41
+ operation['unsignedPayload'] ||
42
+ operation['authtype'] == 'v4-unsigned-body'
43
+ end
44
+
40
45
  def requires_length?(ref)
41
- payload = ref[:payload_member]
42
- payload["requiresLength"] || # checking ref and shape
43
- payload.shape["requiresLength"]
46
+ if (payload = ref[:payload_member])
47
+ payload['requiresLength'] || payload.shape['requiresLength']
48
+ else
49
+ false
50
+ end
44
51
  end
45
52
 
46
53
  end
@@ -4,7 +4,93 @@ module Aws
4
4
  module Plugins
5
5
  # @api private
6
6
  class UserAgent < Seahorse::Client::Plugin
7
+ METRICS = Aws::Json.load(<<-METRICS)
8
+ {
9
+ "RESOURCE_MODEL": "A",
10
+ "WAITER": "B",
11
+ "PAGINATOR": "C",
12
+ "RETRY_MODE_LEGACY": "D",
13
+ "RETRY_MODE_STANDARD": "E",
14
+ "RETRY_MODE_ADAPTIVE": "F",
15
+ "S3_TRANSFER": "G",
16
+ "S3_CRYPTO_V1N": "H",
17
+ "S3_CRYPTO_V2": "I",
18
+ "S3_EXPRESS_BUCKET": "J",
19
+ "S3_ACCESS_GRANTS": "K",
20
+ "GZIP_REQUEST_COMPRESSION": "L",
21
+ "PROTOCOL_RPC_V2_CBOR": "M",
22
+ "ENDPOINT_OVERRIDE": "N",
23
+ "ACCOUNT_ID_ENDPOINT": "O",
24
+ "ACCOUNT_ID_MODE_PREFERRED": "P",
25
+ "ACCOUNT_ID_MODE_DISABLED": "Q",
26
+ "ACCOUNT_ID_MODE_REQUIRED": "R",
27
+ "SIGV4A_SIGNING": "S",
28
+ "RESOLVED_ACCOUNT_ID": "T",
29
+ "FLEXIBLE_CHECKSUMS_REQ_CRC32" : "U",
30
+ "FLEXIBLE_CHECKSUMS_REQ_CRC32C" : "V",
31
+ "FLEXIBLE_CHECKSUMS_REQ_CRC64" : "W",
32
+ "FLEXIBLE_CHECKSUMS_REQ_SHA1" : "X",
33
+ "FLEXIBLE_CHECKSUMS_REQ_SHA256" : "Y",
34
+ "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED" : "Z",
35
+ "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED" : "a",
36
+ "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED" : "b",
37
+ "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c",
38
+ "DDB_MAPPER": "d",
39
+ "CREDENTIALS_CODE" : "e",
40
+ "CREDENTIALS_ENV_VARS" : "g",
41
+ "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN" : "h",
42
+ "CREDENTIALS_STS_ASSUME_ROLE" : "i",
43
+ "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID" : "k",
44
+ "CREDENTIALS_PROFILE" : "n",
45
+ "CREDENTIALS_PROFILE_SOURCE_PROFILE" : "o",
46
+ "CREDENTIALS_PROFILE_NAMED_PROVIDER" : "p",
47
+ "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN" : "q",
48
+ "CREDENTIALS_PROFILE_SSO" : "r",
49
+ "CREDENTIALS_SSO" : "s",
50
+ "CREDENTIALS_PROFILE_SSO_LEGACY" : "t",
51
+ "CREDENTIALS_SSO_LEGACY" : "u",
52
+ "CREDENTIALS_PROFILE_PROCESS" : "v",
53
+ "CREDENTIALS_PROCESS" : "w",
54
+ "CREDENTIALS_HTTP" : "z",
55
+ "CREDENTIALS_IMDS" : "0",
56
+ "SSO_LOGIN_DEVICE" : "1",
57
+ "SSO_LOGIN_AUTH" : "2",
58
+ "BEARER_SERVICE_ENV_VARS": "3"
59
+ }
60
+ METRICS
61
+
62
+ # @api private
7
63
  option(:user_agent_suffix)
64
+ # @api private
65
+ option(:user_agent_frameworks, default: [])
66
+
67
+ option(
68
+ :sdk_ua_app_id,
69
+ doc_type: 'String',
70
+ docstring: <<-DOCS) do |cfg|
71
+ A unique and opaque application ID that is appended to the
72
+ User-Agent header as app/sdk_ua_app_id. It should have a
73
+ maximum length of 50. This variable is sourced from environment
74
+ variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id.
75
+ DOCS
76
+ app_id = ENV['AWS_SDK_UA_APP_ID']
77
+ app_id ||= Aws.shared_config.sdk_ua_app_id(profile: cfg.profile)
78
+ app_id
79
+ end
80
+
81
+ # Deprecated - must exist for old service gems
82
+ def self.feature(_feature, &block)
83
+ block.call
84
+ end
85
+
86
+ def self.metric(*metrics, &block)
87
+ Thread.current[:aws_sdk_core_user_agent_metric] ||= []
88
+ metrics = metrics.map { |metric| METRICS[metric] }.compact
89
+ Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics)
90
+ block.call
91
+ ensure
92
+ Thread.current[:aws_sdk_core_user_agent_metric].pop(metrics.size)
93
+ end
8
94
 
9
95
  # @api private
10
96
  class Handler < Seahorse::Client::Handler
@@ -14,33 +100,125 @@ module Aws
14
100
  end
15
101
 
16
102
  def set_user_agent(context)
17
- ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
103
+ context.http_request.headers['User-Agent'] = UserAgent.new(context).to_s
104
+ end
105
+
106
+ class UserAgent
107
+ def initialize(context)
108
+ @context = context
109
+ end
110
+
111
+ def to_s
112
+ ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
113
+ ua += ' ua/2.1'
114
+ if (api_m = api_metadata)
115
+ ua += " #{api_m}"
116
+ end
117
+ ua += " #{os_metadata}"
118
+ ua += " #{language_metadata}"
119
+ if (env_m = env_metadata)
120
+ ua += " #{env_m}"
121
+ end
122
+ if (app_id_m = app_id_metadata)
123
+ ua += " #{app_id_m}"
124
+ end
125
+ if (framework_m = framework_metadata)
126
+ ua += " #{framework_m}"
127
+ end
128
+ if (metric_m = metric_metadata)
129
+ ua += " #{metric_m}"
130
+ end
131
+ if @context.config.user_agent_suffix
132
+ ua += " #{@context.config.user_agent_suffix}"
133
+ end
134
+ ua.strip
135
+ end
136
+
137
+ private
18
138
 
19
- begin
20
- ua += " #{RUBY_ENGINE}/#{RUBY_VERSION}"
21
- rescue
22
- ua += " RUBY_ENGINE_NA/#{RUBY_VERSION}"
139
+ # Used to be gem_name/gem_version
140
+ def api_metadata
141
+ service_id = @context.config.api.metadata['serviceId']
142
+ return unless service_id
143
+
144
+ service_id = service_id.gsub(' ', '_').downcase
145
+ gem_version = @context[:gem_version]
146
+ "api/#{service_id}##{gem_version}"
23
147
  end
24
148
 
25
- ua += " #{RUBY_PLATFORM}"
149
+ # Used to be RUBY_PLATFORM
150
+ def os_metadata
151
+ os =
152
+ case RbConfig::CONFIG['host_os']
153
+ when /mac|darwin/
154
+ 'macos'
155
+ when /linux|cygwin/
156
+ 'linux'
157
+ when /mingw|mswin/
158
+ 'windows'
159
+ else
160
+ 'other'
161
+ end
162
+ metadata = "os/#{os}"
163
+ local_version = Gem::Platform.local.version
164
+ metadata += "##{local_version}" if local_version
165
+ metadata += " md/#{RbConfig::CONFIG['host_cpu']}"
166
+ end
26
167
 
27
- if context[:gem_name] && context[:gem_version]
28
- ua += " #{context[:gem_name]}/#{context[:gem_version]}"
168
+ # Used to be RUBY_ENGINE/RUBY_VERSION
169
+ def language_metadata
170
+ "lang/#{RUBY_ENGINE}##{RUBY_ENGINE_VERSION} md/#{RUBY_VERSION}"
29
171
  end
30
172
 
31
- if (execution_env = ENV['AWS_EXECUTION_ENV'])
32
- ua += " exec-env/#{execution_env}"
173
+ def env_metadata
174
+ return unless (execution_env = ENV['AWS_EXECUTION_ENV'])
175
+
176
+ "exec-env/#{execution_env}"
33
177
  end
34
178
 
35
- if context.config.user_agent_suffix
36
- ua += " #{context.config.user_agent_suffix}"
179
+ def app_id_metadata
180
+ return unless (app_id = @context.config.sdk_ua_app_id)
181
+
182
+ # Sanitize and only allow these characters
183
+ app_id = app_id.gsub(/[^!#$%&'*+\-.^_`|~0-9A-Za-z]/, '-')
184
+ "app/#{app_id}"
37
185
  end
38
186
 
39
- context.http_request.headers['User-Agent'] = ua.strip
187
+ def framework_metadata
188
+ if (frameworks_cfg = @context.config.user_agent_frameworks).empty?
189
+ return
190
+ end
191
+
192
+ # Frameworks may be aws-record, aws-sdk-rails, etc.
193
+ regex = /gems\/(?<name>#{frameworks_cfg.join('|')})-(?<version>\d+\.\d+\.\d+)/.freeze
194
+ frameworks = {}
195
+ Kernel.caller.each do |line|
196
+ match = line.match(regex)
197
+ next unless match
198
+
199
+ frameworks[match[:name]] = match[:version]
200
+ end
201
+ frameworks.map { |n, v| "lib/#{n}##{v}" }.join(' ')
202
+ end
203
+
204
+ def metric_metadata
205
+ if Thread.current[:aws_sdk_core_user_agent_metric].nil? ||
206
+ Thread.current[:aws_sdk_core_user_agent_metric].empty?
207
+ return
208
+ end
209
+
210
+ metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',')
211
+ # Metric metadata is limited to 1024 bytes
212
+ return "m/#{metrics}" if metrics.bytesize <= 1024
213
+
214
+ # Removes the last unfinished metric
215
+ "m/#{metrics[0...metrics[0..1024].rindex(',')]}"
216
+ end
40
217
  end
41
218
  end
42
219
 
43
- handler(Handler)
220
+ # Priority set to 5 in order to add user agent as late as possible after signing
221
+ handler(Handler, step: :sign, priority: 5)
44
222
  end
45
223
  end
46
224
  end