aws-sdk-sns 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ # utility classes
2
+ require 'aws-sdk-sns/message_verifier'
@@ -0,0 +1,23 @@
1
+ # WARNING ABOUT GENERATED CODE
2
+ #
3
+ # This file is generated. See the contributing for info on making contributions:
4
+ # https://github.com/aws/aws-sdk-ruby/blob/master/CONTRIBUTING.md
5
+ #
6
+ # WARNING ABOUT GENERATED CODE
7
+
8
+ module Aws
9
+ module SNS
10
+ module Errors
11
+
12
+ extend Aws::Errors::DynamicErrors
13
+
14
+ # Raised when calling #load or #data on a resource class that can not be
15
+ # loaded. This can happen when:
16
+ #
17
+ # * A resource class has identifiers, but no data attributes.
18
+ # * Resource data is only available when making an API call that
19
+ # enumerates all resources of that type.
20
+ class ResourceNotLoadable < RuntimeError; end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,157 @@
1
+ require 'net/http'
2
+ require 'openssl'
3
+ require 'base64'
4
+
5
+ module Aws
6
+ module SNS
7
+
8
+ # A utility class that can be used to verify the authenticity of messages
9
+ # sent by Amazon SNS.
10
+ #
11
+ # verifier = Aws::SNS::MessageVerifier.new
12
+ #
13
+ # # returns true/false
14
+ # verifier.authentic?(message_body)
15
+ #
16
+ # # raises a Aws::SNS::MessageVerifier::VerificationError on failure
17
+ # verifier.authenticate!(message_body)
18
+ #
19
+ # You can re-use a single {MessageVerifier} instance to authenticate
20
+ # multiple SNS messages.
21
+ class MessageVerifier
22
+
23
+ class VerificationError < StandardError; end
24
+
25
+ # @api private
26
+ SIGNABLE_KEYS = [
27
+ 'Message',
28
+ 'MessageId',
29
+ 'Subject',
30
+ 'SubscribeURL',
31
+ 'Timestamp',
32
+ 'Token',
33
+ 'TopicArn',
34
+ 'Type',
35
+ ].freeze
36
+
37
+ # @api private
38
+ AWS_HOSTNAMES = [
39
+ /^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/
40
+ ]
41
+
42
+ def initialize
43
+ @cached_pems = {}
44
+ end
45
+
46
+ # @param [String<JSON>] message_body
47
+ # @return [Boolean] Returns `true` if the given message has been
48
+ # successfully verified. Returns `false` otherwise.
49
+ def authentic?(message_body)
50
+ authenticate!(message_body)
51
+ rescue VerificationError
52
+ false
53
+ end
54
+
55
+ # @param [String<JSON>] message_body
56
+ # @return [Boolean] Returns `true` when the given message has been
57
+ # successfully verified.
58
+ # @raise [VerificationError] Raised when the given message has failed
59
+ # verification.
60
+ def authenticate!(message_body)
61
+ msg = Json.load(message_body)
62
+ if public_key(msg).verify(sha1, signature(msg), canonical_string(msg))
63
+ true
64
+ else
65
+ msg = 'the authenticity of the message cannot be verified'
66
+ raise VerificationError, msg
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def sha1
73
+ OpenSSL::Digest::SHA1.new
74
+ end
75
+
76
+ def signature(message)
77
+ Base64.decode64(message['Signature'])
78
+ end
79
+
80
+ def canonical_string(message)
81
+ parts = []
82
+ SIGNABLE_KEYS.each do |key|
83
+ value = message[key]
84
+ unless value.nil? or value.empty?
85
+ parts << "#{key}\n#{value}\n"
86
+ end
87
+ end
88
+ parts.join
89
+ end
90
+
91
+ def public_key(message)
92
+ x509_url = URI.parse(message['SigningCertURL'])
93
+ x509 = OpenSSL::X509::Certificate.new(pem(x509_url))
94
+ OpenSSL::PKey::RSA.new(x509.public_key)
95
+ end
96
+
97
+ def pem(uri)
98
+ if @cached_pems[uri.to_s]
99
+ @cached_pems[uri.to_s]
100
+ else
101
+ @cached_pems[uri.to_s] = download_pem(uri)
102
+ end
103
+ end
104
+
105
+ def download_pem(uri)
106
+ verify_uri!(uri)
107
+ https_get(uri)
108
+ end
109
+
110
+ def verify_uri!(uri)
111
+ verify_https!(uri)
112
+ verify_hosted_by_aws!(uri)
113
+ verify_pem!(uri)
114
+ end
115
+
116
+ def verify_https!(uri)
117
+ unless uri.scheme == 'https'
118
+ msg = "the SigningCertURL must be https, got: #{uri}"
119
+ raise VerificationError, msg
120
+ end
121
+ end
122
+
123
+ def verify_hosted_by_aws!(uri)
124
+ unless AWS_HOSTNAMES.any? { |pattern| pattern.match(uri.host) }
125
+ msg = "signing cert is not hosted by AWS: #{uri}"
126
+ raise VerificationError, msg
127
+ end
128
+ end
129
+
130
+ def verify_pem!(uri)
131
+ unless File.extname(uri.path) == '.pem'
132
+ msg = "the SigningCertURL must link to a .pem file"
133
+ raise VerificationError, msg
134
+ end
135
+ end
136
+
137
+ def https_get(uri, failed_attempts = 0)
138
+ http = Net::HTTP.new(uri.host, uri.port)
139
+ http.use_ssl = true
140
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
141
+ http.start
142
+ resp = http.request(Net::HTTP::Get.new(uri.request_uri))
143
+ http.finish
144
+ if resp.code == '200'
145
+ resp.body
146
+ else
147
+ raise VerificationError, resp.body
148
+ end
149
+ rescue => error
150
+ failed_attempts += 1
151
+ retry if failed_attempts < 3
152
+ raise VerificationError, error.message
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,235 @@
1
+ # WARNING ABOUT GENERATED CODE
2
+ #
3
+ # This file is generated. See the contributing for info on making contributions:
4
+ # https://github.com/aws/aws-sdk-ruby/blob/master/CONTRIBUTING.md
5
+ #
6
+ # WARNING ABOUT GENERATED CODE
7
+
8
+ module Aws
9
+ module SNS
10
+ class PlatformApplication
11
+
12
+ extend Aws::Deprecations
13
+
14
+ # @overload def initialize(arn, options = {})
15
+ # @param [String] arn
16
+ # @option options [Client] :client
17
+ # @overload def initialize(options = {})
18
+ # @option options [required, String] :arn
19
+ # @option options [Client] :client
20
+ def initialize(*args)
21
+ options = Hash === args.last ? args.pop.dup : {}
22
+ @arn = extract_arn(args, options)
23
+ @data = options.delete(:data)
24
+ @client = options.delete(:client) || Client.new(options)
25
+ end
26
+
27
+ # @!group Read-Only Attributes
28
+
29
+ # @return [String]
30
+ def arn
31
+ @arn
32
+ end
33
+
34
+ # Attributes include the following:
35
+ #
36
+ # * `EventEndpointCreated` -- Topic ARN to which EndpointCreated event
37
+ # notifications should be sent.
38
+ #
39
+ # * `EventEndpointDeleted` -- Topic ARN to which EndpointDeleted event
40
+ # notifications should be sent.
41
+ #
42
+ # * `EventEndpointUpdated` -- Topic ARN to which EndpointUpdate event
43
+ # notifications should be sent.
44
+ #
45
+ # * `EventDeliveryFailure` -- Topic ARN to which DeliveryFailure event
46
+ # notifications should be sent upon Direct Publish delivery failure
47
+ # (permanent) to one of the application's endpoints.
48
+ # @return [Hash<String,String>]
49
+ def attributes
50
+ data.attributes
51
+ end
52
+
53
+ # @!endgroup
54
+
55
+ # @return [Client]
56
+ def client
57
+ @client
58
+ end
59
+
60
+ # Loads, or reloads {#data} for the current {PlatformApplication}.
61
+ # Returns `self` making it possible to chain methods.
62
+ #
63
+ # platform_application.reload.data
64
+ #
65
+ # @return [self]
66
+ def load
67
+ resp = @client.get_platform_application_attributes(platform_application_arn: @arn)
68
+ @data = resp.data
69
+ self
70
+ end
71
+ alias :reload :load
72
+
73
+ # @return [Types::GetPlatformApplicationAttributesResponse]
74
+ # Returns the data for this {PlatformApplication}. Calls
75
+ # {Client#get_platform_application_attributes} if {#data_loaded?} is `false`.
76
+ def data
77
+ load unless @data
78
+ @data
79
+ end
80
+
81
+ # @return [Boolean]
82
+ # Returns `true` if this resource is loaded. Accessing attributes or
83
+ # {#data} on an unloaded resource will trigger a call to {#load}.
84
+ def data_loaded?
85
+ !!@data
86
+ end
87
+
88
+ # @!group Actions
89
+
90
+ # @example Request syntax with placeholder values
91
+ #
92
+ # platformendpoint = platform_application.create_platform_endpoint({
93
+ # token: "String", # required
94
+ # custom_user_data: "String",
95
+ # attributes: {
96
+ # "String" => "String",
97
+ # },
98
+ # })
99
+ # @param [Hash] options ({})
100
+ # @option options [required, String] :token
101
+ # Unique identifier created by the notification service for an app on a
102
+ # device. The specific name for Token will vary, depending on which
103
+ # notification service is being used. For example, when using APNS as
104
+ # the notification service, you need the device token. Alternatively,
105
+ # when using GCM or ADM, the device token equivalent is called the
106
+ # registration ID.
107
+ # @option options [String] :custom_user_data
108
+ # Arbitrary user data to associate with the endpoint. Amazon SNS does
109
+ # not use this data. The data must be in UTF-8 format and less than 2KB.
110
+ # @option options [Hash<String,String>] :attributes
111
+ # For a list of attributes, see [SetEndpointAttributes][1].
112
+ #
113
+ #
114
+ #
115
+ # [1]: http://docs.aws.amazon.com/sns/latest/api/API_SetEndpointAttributes.html
116
+ # @return [PlatformEndpoint]
117
+ def create_platform_endpoint(options = {})
118
+ options = options.merge(platform_application_arn: @arn)
119
+ resp = @client.create_platform_endpoint(options)
120
+ PlatformEndpoint.new(
121
+ arn: resp.data.endpoint_arn,
122
+ client: @client
123
+ )
124
+ end
125
+
126
+ # @example Request syntax with placeholder values
127
+ #
128
+ # platform_application.delete()
129
+ # @param [Hash] options ({})
130
+ # @return [EmptyStructure]
131
+ def delete(options = {})
132
+ options = options.merge(platform_application_arn: @arn)
133
+ resp = @client.delete_platform_application(options)
134
+ resp.data
135
+ end
136
+
137
+ # @example Request syntax with placeholder values
138
+ #
139
+ # platform_application.set_attributes({
140
+ # attributes: { # required
141
+ # "String" => "String",
142
+ # },
143
+ # })
144
+ # @param [Hash] options ({})
145
+ # @option options [required, Hash<String,String>] :attributes
146
+ # A map of the platform application attributes. Attributes in this map
147
+ # include the following:
148
+ #
149
+ # * `PlatformCredential` -- The credential received from the
150
+ # notification service. For APNS/APNS\_SANDBOX, PlatformCredential is
151
+ # private key. For GCM, PlatformCredential is "API key". For ADM,
152
+ # PlatformCredential is "client secret".
153
+ #
154
+ # * `PlatformPrincipal` -- The principal received from the notification
155
+ # service. For APNS/APNS\_SANDBOX, PlatformPrincipal is SSL
156
+ # certificate. For GCM, PlatformPrincipal is not applicable. For ADM,
157
+ # PlatformPrincipal is "client id".
158
+ #
159
+ # * `EventEndpointCreated` -- Topic ARN to which EndpointCreated event
160
+ # notifications should be sent.
161
+ #
162
+ # * `EventEndpointDeleted` -- Topic ARN to which EndpointDeleted event
163
+ # notifications should be sent.
164
+ #
165
+ # * `EventEndpointUpdated` -- Topic ARN to which EndpointUpdate event
166
+ # notifications should be sent.
167
+ #
168
+ # * `EventDeliveryFailure` -- Topic ARN to which DeliveryFailure event
169
+ # notifications should be sent upon Direct Publish delivery failure
170
+ # (permanent) to one of the application's endpoints.
171
+ #
172
+ # * `SuccessFeedbackRoleArn` -- IAM role ARN used to give Amazon SNS
173
+ # write access to use CloudWatch Logs on your behalf.
174
+ #
175
+ # * `FailureFeedbackRoleArn` -- IAM role ARN used to give Amazon SNS
176
+ # write access to use CloudWatch Logs on your behalf.
177
+ #
178
+ # * `SuccessFeedbackSampleRate` -- Sample rate percentage (0-100) of
179
+ # successfully delivered messages.
180
+ # @return [EmptyStructure]
181
+ def set_attributes(options = {})
182
+ options = options.merge(platform_application_arn: @arn)
183
+ resp = @client.set_platform_application_attributes(options)
184
+ resp.data
185
+ end
186
+
187
+ # @!group Associations
188
+
189
+ # @example Request syntax with placeholder values
190
+ #
191
+ # endpoints = platform_application.endpoints()
192
+ # @param [Hash] options ({})
193
+ # @return [PlatformEndpoint::Collection]
194
+ def endpoints(options = {})
195
+ batches = Enumerator.new do |y|
196
+ options = options.merge(platform_application_arn: @arn)
197
+ resp = @client.list_endpoints_by_platform_application(options)
198
+ resp.each_page do |page|
199
+ batch = []
200
+ page.data.endpoints.each do |e|
201
+ batch << PlatformEndpoint.new(
202
+ arn: e.endpoint_arn,
203
+ client: @client
204
+ )
205
+ end
206
+ y.yield(batch)
207
+ end
208
+ end
209
+ PlatformEndpoint::Collection.new(batches)
210
+ end
211
+
212
+ # @deprecated
213
+ # @api private
214
+ def identifiers
215
+ { arn: @arn }
216
+ end
217
+ deprecated(:identifiers)
218
+
219
+ private
220
+
221
+ def extract_arn(args, options)
222
+ value = args[0] || options.delete(:arn)
223
+ case value
224
+ when String then value
225
+ when nil then raise ArgumentError, "missing required option :arn"
226
+ else
227
+ msg = "expected :arn to be a String, got #{value.class}"
228
+ raise ArgumentError, msg
229
+ end
230
+ end
231
+
232
+ class Collection < Aws::Resources::Collection; end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,266 @@
1
+ # WARNING ABOUT GENERATED CODE
2
+ #
3
+ # This file is generated. See the contributing for info on making contributions:
4
+ # https://github.com/aws/aws-sdk-ruby/blob/master/CONTRIBUTING.md
5
+ #
6
+ # WARNING ABOUT GENERATED CODE
7
+
8
+ module Aws
9
+ module SNS
10
+ class PlatformEndpoint
11
+
12
+ extend Aws::Deprecations
13
+
14
+ # @overload def initialize(arn, options = {})
15
+ # @param [String] arn
16
+ # @option options [Client] :client
17
+ # @overload def initialize(options = {})
18
+ # @option options [required, String] :arn
19
+ # @option options [Client] :client
20
+ def initialize(*args)
21
+ options = Hash === args.last ? args.pop.dup : {}
22
+ @arn = extract_arn(args, options)
23
+ @data = options.delete(:data)
24
+ @client = options.delete(:client) || Client.new(options)
25
+ end
26
+
27
+ # @!group Read-Only Attributes
28
+
29
+ # @return [String]
30
+ def arn
31
+ @arn
32
+ end
33
+
34
+ # Attributes include the following:
35
+ #
36
+ # * `CustomUserData` -- arbitrary user data to associate with the
37
+ # endpoint. Amazon SNS does not use this data. The data must be in
38
+ # UTF-8 format and less than 2KB.
39
+ #
40
+ # * `Enabled` -- flag that enables/disables delivery to the endpoint.
41
+ # Amazon SNS will set this to false when a notification service
42
+ # indicates to Amazon SNS that the endpoint is invalid. Users can set
43
+ # it back to true, typically after updating Token.
44
+ #
45
+ # * `Token` -- device token, also referred to as a registration id, for
46
+ # an app and mobile device. This is returned from the notification
47
+ # service when an app and mobile device are registered with the
48
+ # notification service.
49
+ # @return [Hash<String,String>]
50
+ def attributes
51
+ data.attributes
52
+ end
53
+
54
+ # @!endgroup
55
+
56
+ # @return [Client]
57
+ def client
58
+ @client
59
+ end
60
+
61
+ # Loads, or reloads {#data} for the current {PlatformEndpoint}.
62
+ # Returns `self` making it possible to chain methods.
63
+ #
64
+ # platform_endpoint.reload.data
65
+ #
66
+ # @return [self]
67
+ def load
68
+ resp = @client.get_endpoint_attributes(endpoint_arn: @arn)
69
+ @data = resp.data
70
+ self
71
+ end
72
+ alias :reload :load
73
+
74
+ # @return [Types::GetEndpointAttributesResponse]
75
+ # Returns the data for this {PlatformEndpoint}. Calls
76
+ # {Client#get_endpoint_attributes} if {#data_loaded?} is `false`.
77
+ def data
78
+ load unless @data
79
+ @data
80
+ end
81
+
82
+ # @return [Boolean]
83
+ # Returns `true` if this resource is loaded. Accessing attributes or
84
+ # {#data} on an unloaded resource will trigger a call to {#load}.
85
+ def data_loaded?
86
+ !!@data
87
+ end
88
+
89
+ # @!group Actions
90
+
91
+ # @example Request syntax with placeholder values
92
+ #
93
+ # platform_endpoint.delete()
94
+ # @param [Hash] options ({})
95
+ # @return [EmptyStructure]
96
+ def delete(options = {})
97
+ options = options.merge(endpoint_arn: @arn)
98
+ resp = @client.delete_endpoint(options)
99
+ resp.data
100
+ end
101
+
102
+ # @example Request syntax with placeholder values
103
+ #
104
+ # platform_endpoint.publish({
105
+ # topic_arn: "topicARN",
106
+ # phone_number: "String",
107
+ # message: "message", # required
108
+ # subject: "subject",
109
+ # message_structure: "messageStructure",
110
+ # message_attributes: {
111
+ # "String" => {
112
+ # data_type: "String", # required
113
+ # string_value: "String",
114
+ # binary_value: "data",
115
+ # },
116
+ # },
117
+ # })
118
+ # @param [Hash] options ({})
119
+ # @option options [String] :topic_arn
120
+ # The topic you want to publish to.
121
+ #
122
+ # If you don't specify a value for the `TopicArn` parameter, you must
123
+ # specify a value for the `PhoneNumber` or `TargetArn` parameters.
124
+ # @option options [String] :phone_number
125
+ # The phone number to which you want to deliver an SMS message. Use
126
+ # E.164 format.
127
+ #
128
+ # If you don't specify a value for the `PhoneNumber` parameter, you
129
+ # must specify a value for the `TargetArn` or `TopicArn` parameters.
130
+ # @option options [required, String] :message
131
+ # The message you want to send to the topic.
132
+ #
133
+ # If you want to send the same message to all transport protocols,
134
+ # include the text of the message as a String value.
135
+ #
136
+ # If you want to send different messages for each transport protocol,
137
+ # set the value of the `MessageStructure` parameter to `json` and use a
138
+ # JSON object for the `Message` parameter.
139
+ #
140
+ # Constraints: Messages must be UTF-8 encoded strings at most 256 KB in
141
+ # size (262144 bytes, not 262144 characters).
142
+ #
143
+ # JSON-specific constraints:
144
+ #
145
+ # * Keys in the JSON object that correspond to supported transport
146
+ # protocols must have simple JSON string values.
147
+ #
148
+ # * The values will be parsed (unescaped) before they are used in
149
+ # outgoing messages.
150
+ #
151
+ # * Outbound notifications are JSON encoded (meaning that the characters
152
+ # will be reescaped for sending).
153
+ #
154
+ # * Values have a minimum length of 0 (the empty string, "", is
155
+ # allowed).
156
+ #
157
+ # * Values have a maximum length bounded by the overall message size
158
+ # (so, including multiple protocols may limit message sizes).
159
+ #
160
+ # * Non-string values will cause the key to be ignored.
161
+ #
162
+ # * Keys that do not correspond to supported transport protocols are
163
+ # ignored.
164
+ #
165
+ # * Duplicate keys are not allowed.
166
+ #
167
+ # * Failure to parse or validate any key or value in the message will
168
+ # cause the `Publish` call to return an error (no partial delivery).
169
+ # @option options [String] :subject
170
+ # Optional parameter to be used as the "Subject" line when the message
171
+ # is delivered to email endpoints. This field will also be included, if
172
+ # present, in the standard JSON messages delivered to other endpoints.
173
+ #
174
+ # Constraints: Subjects must be ASCII text that begins with a letter,
175
+ # number, or punctuation mark; must not include line breaks or control
176
+ # characters; and must be less than 100 characters long.
177
+ # @option options [String] :message_structure
178
+ # Set `MessageStructure` to `json` if you want to send a different
179
+ # message for each protocol. For example, using one publish action, you
180
+ # can send a short message to your SMS subscribers and a longer message
181
+ # to your email subscribers. If you set `MessageStructure` to `json`,
182
+ # the value of the `Message` parameter must:
183
+ #
184
+ # * be a syntactically valid JSON object; and
185
+ #
186
+ # * contain at least a top-level JSON key of "default" with a value
187
+ # that is a string.
188
+ #
189
+ # You can define other top-level keys that define the message you want
190
+ # to send to a specific transport protocol (e.g., "http").
191
+ #
192
+ # For information about sending different messages for each protocol
193
+ # using the AWS Management Console, go to [Create Different Messages for
194
+ # Each Protocol][1] in the *Amazon Simple Notification Service Getting
195
+ # Started Guide*.
196
+ #
197
+ # Valid value: `json`
198
+ #
199
+ #
200
+ #
201
+ # [1]: http://docs.aws.amazon.com/sns/latest/gsg/Publish.html#sns-message-formatting-by-protocol
202
+ # @option options [Hash<String,Types::MessageAttributeValue>] :message_attributes
203
+ # Message attributes for Publish action.
204
+ # @return [Types::PublishResponse]
205
+ def publish(options = {})
206
+ options = options.merge(target_arn: @arn)
207
+ resp = @client.publish(options)
208
+ resp.data
209
+ end
210
+
211
+ # @example Request syntax with placeholder values
212
+ #
213
+ # platform_endpoint.set_attributes({
214
+ # attributes: { # required
215
+ # "String" => "String",
216
+ # },
217
+ # })
218
+ # @param [Hash] options ({})
219
+ # @option options [required, Hash<String,String>] :attributes
220
+ # A map of the endpoint attributes. Attributes in this map include the
221
+ # following:
222
+ #
223
+ # * `CustomUserData` -- arbitrary user data to associate with the
224
+ # endpoint. Amazon SNS does not use this data. The data must be in
225
+ # UTF-8 format and less than 2KB.
226
+ #
227
+ # * `Enabled` -- flag that enables/disables delivery to the endpoint.
228
+ # Amazon SNS will set this to false when a notification service
229
+ # indicates to Amazon SNS that the endpoint is invalid. Users can set
230
+ # it back to true, typically after updating Token.
231
+ #
232
+ # * `Token` -- device token, also referred to as a registration id, for
233
+ # an app and mobile device. This is returned from the notification
234
+ # service when an app and mobile device are registered with the
235
+ # notification service.
236
+ # @return [EmptyStructure]
237
+ def set_attributes(options = {})
238
+ options = options.merge(endpoint_arn: @arn)
239
+ resp = @client.set_endpoint_attributes(options)
240
+ resp.data
241
+ end
242
+
243
+ # @deprecated
244
+ # @api private
245
+ def identifiers
246
+ { arn: @arn }
247
+ end
248
+ deprecated(:identifiers)
249
+
250
+ private
251
+
252
+ def extract_arn(args, options)
253
+ value = args[0] || options.delete(:arn)
254
+ case value
255
+ when String then value
256
+ when nil then raise ArgumentError, "missing required option :arn"
257
+ else
258
+ msg = "expected :arn to be a String, got #{value.class}"
259
+ raise ArgumentError, msg
260
+ end
261
+ end
262
+
263
+ class Collection < Aws::Resources::Collection; end
264
+ end
265
+ end
266
+ end