aws-sdk-sqs 1.5.0 → 1.80.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
 
3
5
  module Aws
4
6
  module SQS
5
7
  module Plugins
6
8
  class Md5s < Seahorse::Client::Plugin
7
-
8
9
  # @api private
9
10
  class Handler < Seahorse::Client::Handler
10
11
  def call(context)
@@ -24,16 +25,17 @@ module Aws
24
25
  'String' => 1,
25
26
  'Binary' => 2,
26
27
  'Number' => 1
27
- }
28
+ }.freeze
28
29
 
29
- DATA_TYPE = /\A(String|Binary|Number)(\..+)?\z/
30
+ DATA_TYPE = /\A(String|Binary|Number)(\..+)?\z/.freeze
30
31
 
31
32
  NORMALIZED_ENCODING = Encoding::UTF_8
32
33
 
33
34
  def validate_send_message(context, response)
34
35
  body = context.params[:message_body]
35
36
  attributes = context.params[:message_attributes]
36
- validate_single_message(body, attributes, response)
37
+ system_attributes = context.params[:message_system_attributes]
38
+ validate_single_message(body, attributes, system_attributes, response)
37
39
  end
38
40
 
39
41
  def validate_send_message_batch(context, response)
@@ -41,61 +43,87 @@ module Aws
41
43
  id = entry[:id]
42
44
  body = entry[:message_body]
43
45
  attributes = entry[:message_attributes]
46
+ system_attributes = entry[:message_system_attributes]
44
47
  message_response = response.successful.select { |r| r.id == id }[0]
45
48
  unless message_response.nil?
46
- validate_single_message(body, attributes, message_response)
49
+ validate_single_message(body, attributes, system_attributes, message_response)
47
50
  end
48
51
  end
49
52
  end
50
53
 
51
- def validate_single_message(body, attributes, response)
54
+ def validate_single_message(body, attributes, system_attributes, response)
52
55
  validate_body(body, response)
53
- validate_attributes(attributes, response) unless attributes.nil?
56
+ unless attributes.nil? || attributes.empty?
57
+ validate_attributes(attributes, response)
58
+ end
59
+ unless system_attributes.nil? || system_attributes.empty?
60
+ validate_system_attributes(system_attributes, response)
61
+ end
54
62
  end
55
63
 
56
64
  def validate_body(body, response)
57
65
  calculated_md5 = md5_of_message_body(body)
58
66
  returned_md5 = response.md5_of_message_body
59
- if calculated_md5 != returned_md5
60
- error_message = mismatch_error_message(
61
- 'message body',
62
- calculated_md5,
63
- returned_md5,
64
- response)
65
- raise Aws::Errors::ChecksumError, error_message
66
- end
67
+ return unless calculated_md5 != returned_md5
68
+
69
+ error_message = mismatch_error_message(
70
+ 'message body',
71
+ calculated_md5,
72
+ returned_md5,
73
+ response
74
+ )
75
+ raise Aws::Errors::ChecksumError, error_message
67
76
  end
68
77
 
69
78
  def validate_attributes(attributes, response)
70
79
  calculated_md5 = md5_of_message_attributes(attributes)
71
80
  returned_md5 = response.md5_of_message_attributes
72
- if returned_md5 != calculated_md5
73
- error_message = mismatch_error_message(
74
- 'message attributes',
75
- calculated_md5,
76
- returned_md5,
77
- response)
78
- raise Aws::Errors::ChecksumError, error_message
79
- end
81
+ return unless returned_md5 != calculated_md5
82
+
83
+ error_message = mismatch_error_message(
84
+ 'message attributes',
85
+ calculated_md5,
86
+ returned_md5,
87
+ response
88
+ )
89
+ raise Aws::Errors::ChecksumError, error_message
90
+ end
91
+
92
+ def validate_system_attributes(system_attributes, response)
93
+ calculated_md5 = md5_of_message_system_attributes(system_attributes)
94
+ returned_md5 = response.md5_of_message_system_attributes
95
+ return unless returned_md5 != calculated_md5
96
+
97
+ error_message = mismatch_error_message(
98
+ 'message system attributes',
99
+ calculated_md5,
100
+ returned_md5,
101
+ response
102
+ )
103
+ raise Aws::Errors::ChecksumError, error_message
80
104
  end
81
105
 
82
106
  def md5_of_message_body(message_body)
83
107
  OpenSSL::Digest::MD5.hexdigest(message_body)
84
108
  end
85
109
 
110
+ # MD5 of Message Attributes and System Attributes are effectively
111
+ # the same calculation. However, keeping these as two methods because
112
+ # they are modeled as two different shapes.
113
+ ###
86
114
  def md5_of_message_attributes(message_attributes)
87
- encoded = { }
115
+ encoded = {}
88
116
  message_attributes.each do |name, attribute|
89
117
  name = name.to_s
90
118
  encoded[name] = String.new
91
119
  data_type_without_label = DATA_TYPE.match(attribute[:data_type])[1]
92
120
  encoded[name] << encode_length_and_bytes(name) <<
93
- encode_length_and_bytes(attribute[:data_type]) <<
94
- [TRANSPORT_TYPE_ENCODINGS[data_type_without_label]].pack('C'.freeze)
121
+ encode_length_and_bytes(attribute[:data_type]) <<
122
+ [TRANSPORT_TYPE_ENCODINGS[data_type_without_label]].pack('C')
95
123
 
96
- if attribute[:string_value] != nil
124
+ if !attribute[:string_value].nil?
97
125
  encoded[name] << encode_length_and_string(attribute[:string_value])
98
- elsif attribute[:binary_value] != nil
126
+ elsif !attribute[:binary_value].nil?
99
127
  encoded[name] << encode_length_and_bytes(attribute[:binary_value])
100
128
  end
101
129
  end
@@ -106,6 +134,30 @@ module Aws
106
134
  OpenSSL::Digest::MD5.hexdigest(buffer)
107
135
  end
108
136
 
137
+ def md5_of_message_system_attributes(message_system_attributes)
138
+ encoded = {}
139
+ message_system_attributes.each do |name, attribute|
140
+ name = name.to_s
141
+ encoded[name] = String.new
142
+ data_type_without_label = DATA_TYPE.match(attribute[:data_type])[1]
143
+ encoded[name] << encode_length_and_bytes(name) <<
144
+ encode_length_and_bytes(attribute[:data_type]) <<
145
+ [TRANSPORT_TYPE_ENCODINGS[data_type_without_label]].pack('C')
146
+
147
+ if !attribute[:string_value].nil?
148
+ encoded[name] << encode_length_and_string(attribute[:string_value])
149
+ elsif !attribute[:binary_value].nil?
150
+ encoded[name] << encode_length_and_bytes(attribute[:binary_value])
151
+ end
152
+ end
153
+
154
+ buffer = encoded.keys.sort.reduce(String.new) do |string, name|
155
+ string << encoded[name]
156
+ end
157
+ OpenSSL::Digest::MD5.hexdigest(buffer)
158
+ end
159
+ ###
160
+
109
161
  def encode_length_and_string(string)
110
162
  string = String.new(string)
111
163
  string.encode!(NORMALIZED_ENCODING)
@@ -113,18 +165,16 @@ module Aws
113
165
  end
114
166
 
115
167
  def encode_length_and_bytes(bytes)
116
- [bytes.bytesize, bytes].pack('L>a*'.freeze)
168
+ [bytes.bytesize, bytes].pack('L>a*')
117
169
  end
118
170
 
119
171
  def mismatch_error_message(section, local_md5, returned_md5, response)
120
- m = "MD5 returned by SQS does not match " <<
121
- "the calculation on the original request. ("
122
-
172
+ m = 'MD5 returned by SQS does not match '\
173
+ 'the calculation on the original request. ('
123
174
  if response.respond_to?(:id) && !response.id.nil?
124
- m << "Message ID: #{response.id}, "
175
+ m = "#{m}Message ID: #{response.id}, "
125
176
  end
126
-
127
- m << "MD5 calculated by the #{section}: " <<
177
+ "#{m}MD5 calculated by the #{section}: "\
128
178
  "'#{local_md5}', MD5 checksum returned: '#{returned_md5}')"
129
179
  end
130
180
  end
@@ -152,13 +202,14 @@ not match.
152
202
  end
153
203
 
154
204
  def add_handlers(handlers, config)
155
- if config.verify_checksums
156
- handlers.add(Handler, {
157
- priority: 10 ,
158
- step: :validate,
159
- operations: [:send_message, :send_message_batch]
160
- })
161
- end
205
+ return unless config.verify_checksums
206
+
207
+ handlers.add(
208
+ Handler,
209
+ priority: 10,
210
+ step: :validate,
211
+ operations: %i[send_message send_message_batch]
212
+ )
162
213
  end
163
214
  end
164
215
  end
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module SQS
3
5
  module Plugins
4
6
  # @api private
5
7
  class QueueUrls < Seahorse::Client::Plugin
6
-
8
+ # Extract region from a provided queue_url
7
9
  class Handler < Seahorse::Client::Handler
8
-
9
10
  def call(context)
10
- if queue_url = context.params[:queue_url]
11
+ if (queue_url = context.params[:queue_url])
11
12
  update_endpoint(context, queue_url)
12
13
  update_region(context, queue_url)
13
14
  end
@@ -19,18 +20,31 @@ module Aws
19
20
  end
20
21
 
21
22
  # If the region in the queue url is not the configured
22
- # region, then we will modify the request to have
23
- # a sigv4 signer for the proper region.
23
+ # region, then we will modify signing to use it
24
24
  def update_region(context, queue_url)
25
- if queue_region = queue_url.to_s.split('.')[1]
26
- if queue_region != context.config.region
27
- config = context.config.dup
28
- config.region = queue_region
29
- config.sigv4_region = queue_region
30
- config.sigv4_signer = Aws::Plugins::SignatureV4.build_signer(config)
31
- context.config = config
25
+ if (queue_region = parse_region(queue_url)) &&
26
+ queue_region != context.config.region
27
+ context[:auth_scheme]['signingRegion'] = queue_region
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # take the first component after the SQS service component
34
+ # Will return us-east-1 for:
35
+ # https://sqs.us-east-1.amazonaws.com/1234567890/demo
36
+ # https://vpce-x-y.sqs.us-east-1.vpce.amazonaws.com/1234567890/demo
37
+ # Will not return for:
38
+ # https://localstack-sqs.example.dev/queue/example
39
+ def parse_region(url)
40
+ parts = URI.parse(url).host.split('.')
41
+ parts.each_with_index do |part, index|
42
+ if part == 'sqs'
43
+ # assume region is the part right after the 'sqs' part
44
+ return parts[index + 1]
32
45
  end
33
46
  end
47
+ nil # no region found
34
48
  end
35
49
 
36
50
  end