aws-sdk-resources 2.0.33 → 2.0.34

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 190313b8ccdee719af5e4a0ff6509dd19802db18
4
- data.tar.gz: fe9ef27d4492c1ad92c2612a1bc4d61c8cc7060f
3
+ metadata.gz: e919f0b752d0c452b8a330bfe8e20d0e05ea32e6
4
+ data.tar.gz: cac98b1667805d16c0d07ec074a17dee0692515b
5
5
  SHA512:
6
- metadata.gz: f5e756d2a2f972cef49a1a13928491af89d461075d4f76482607033a8bc56c38a46d6bb8824ced486ad5edf7427787a0317d74901635ba400b9b1176b65624d8
7
- data.tar.gz: 9d5ee1f9f6ea15ce80478e382026569c0bf46d5ca74d669690724592e075f7df6c46d34bd890b1a50df868fe6f10c497288d2c24fd6b402bd2c9d7eb641806bb
6
+ metadata.gz: bd0ac1a60590c3563ca0cfb33df6b7d8dd7c35401130b82ee9a9b66f78592f67352c3090b4c55fcd021a5bfae9f4f8cdb2db2dcf2a2a721e997aa0cb18cdfc69
7
+ data.tar.gz: bfce885ffbc5105dfb9e4b8cb16fa504139858ff82f045228d97df8909e6d054ba2530a28bf73e90c2756a17b84c8fa7fd318629749f95812a930fe69973b40d
@@ -34,6 +34,19 @@ module Aws
34
34
  !@data.nil?
35
35
  end
36
36
 
37
+ # @api private
38
+ def exists?
39
+ wait_until_exists { |w| w.max_attempts = 1 }
40
+ true
41
+ rescue Waiters::Errors::UnexpectedError => e
42
+ raise e.error
43
+ rescue Waiters::Errors::WaiterFailed
44
+ false
45
+ rescue NoMethodError
46
+ msg = "#exists? is not implemented for #{self.class.name}"
47
+ raise NotImplementedError, msg
48
+ end
49
+
37
50
  # Loads data for this resource.
38
51
  # @note Calling this method will send a request to AWS.
39
52
  # @return [self]
@@ -12,6 +12,7 @@ module Aws
12
12
  autoload :FileUploader, 'aws-sdk-resources/services/s3/file_uploader'
13
13
  autoload :MultipartFileUploader, 'aws-sdk-resources/services/s3/multipart_file_uploader'
14
14
  autoload :MultipartUploadError, 'aws-sdk-resources/services/s3/multipart_upload_error'
15
+ autoload :PresignedPost, 'aws-sdk-resources/services/s3/presigned_post'
15
16
 
16
17
  end
17
18
  end
@@ -39,6 +39,24 @@ module Aws
39
39
  url.to_s
40
40
  end
41
41
 
42
+ # Creates a {PresignedPost} that makes it easy to upload a file from
43
+ # a web browser direct to Amazon S3 using an HTML post form with
44
+ # a file field.
45
+ #
46
+ # See the {PresignedPost} documentation for more information.
47
+ # @note You must specify `:key` or `:key_starts_with`. All other options
48
+ # are optional.
49
+ # @option (see PresignedPost#initialize)
50
+ # @return [PresignedPost]
51
+ # @see PresignedPost
52
+ def presigned_post(options = {})
53
+ PresignedPost.new(
54
+ client.config.credentials,
55
+ client.config.region,
56
+ name,
57
+ options)
58
+ end
59
+
42
60
  private
43
61
 
44
62
  def dns_compatible?(scheme)
@@ -5,22 +5,13 @@ module Aws
5
5
  module Encryption
6
6
  class Materials
7
7
 
8
- # @option options [required, OpenSSL::PKey::RSA, String] :encryption_key
8
+ # @option options [required, OpenSSL::PKey::RSA, String] :key
9
9
  # The master key to use for encrypting/decrypting all objects.
10
10
  #
11
- # @option options [String<JSON>] :materials_description ('{}')
11
+ # @option options [String<JSON>] :description ('{}')
12
12
  # The encryption materials description. This is must be
13
13
  # a JSON document string.
14
14
  #
15
- # @option options [Symbol] :materials_location (:metadata) Where to
16
- # store the envelope encryption keys. This must be one of
17
- # the following values:
18
- #
19
- # * `:metadata`
20
- # * `:instruction_file`
21
- #
22
- # @option options [String] :instruction_file_suffix ('.instruction')
23
- #
24
15
  def initialize(options = {})
25
16
  @key = validate_key(options[:key])
26
17
  @description = validate_desc(options[:description])
@@ -103,6 +103,24 @@ module Aws
103
103
  true
104
104
  end
105
105
 
106
+ # Creates a {PresignedPost} that makes it easy to upload a file from
107
+ # a web browser direct to Amazon S3 using an HTML post form with
108
+ # a file field.
109
+ #
110
+ # See the {PresignedPost} documentation for more information.
111
+ # @note The `:key` is populated by {#key}. Do not specify
112
+ # the `:key` or `:key_starts_with` options.
113
+ # @option (see PresignedPost#initialize)
114
+ # @return [PresignedPost]
115
+ # @see PresignedPost
116
+ def presigned_post(options = {})
117
+ PresignedPost.new(
118
+ client.config.credentials,
119
+ client.config.region,
120
+ bucket_name,
121
+ options.merge(key: key))
122
+ end
123
+
106
124
  end
107
125
  end
108
126
  end
@@ -0,0 +1,647 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+ require 'multi_json'
4
+
5
+ module Aws
6
+ module S3
7
+
8
+ # @note Normally you do not need to construct a {PresignedPost} yourself.
9
+ # See {Bucket#presigned_post} and {Object#presigned_post}.
10
+ #
11
+ # ## Basic Usage
12
+ #
13
+ # To generate a presigned post, you need AWS credentials, the region
14
+ # your bucket is in, and the name of your bucket. You can apply constraints
15
+ # to the post object as options to {#initialize} or by calling
16
+ # methods such as {#key} and {#content_length_range}.
17
+ #
18
+ # The following two examples are equivalent.
19
+ #
20
+ # ```ruby
21
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket, {
22
+ # key: '/uploaded/object/key',
23
+ # content_length_range: 0..1024,
24
+ # acl: 'public-read',
25
+ # metadata: {
26
+ # 'original-filename' => '${filename}'
27
+ # }
28
+ # })
29
+ # post.fields
30
+ # #=> { ... }
31
+ #
32
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket).
33
+ # key('/uploaded/object/key').
34
+ # content_length_range(0..1024).
35
+ # acl('public-read').
36
+ # metadata('original-filename' => '${filename}').
37
+ # fields
38
+ # #=> { ... }
39
+ # ```
40
+ #
41
+ # ## HTML Forms
42
+ #
43
+ # You can use a {PresignedPost} object to build an HTML form. It is
44
+ # recommended to use some helper to build the form tag and input
45
+ # tags that properly escapes values.
46
+ #
47
+ # ### Form Tag
48
+ #
49
+ # To upload a file to Amazon S3 using a browser, you need to create
50
+ # a post form. The {#url} method returns the value you should use
51
+ # as the form action.
52
+ #
53
+ # ```erb
54
+ # <form action="<%= @post.url %>" method="post" enctype="multipart/form-data">
55
+ # ...
56
+ # </form>
57
+ # ```
58
+ #
59
+ # The follow attributes must be set on the form:
60
+ #
61
+ # * `action` - This must be the {#url}.
62
+ # * `method` - This must be `post`.
63
+ # * `enctype` - This must be `multipart/form-data`.
64
+ #
65
+ # ### Form Fields
66
+ #
67
+ # The {#fields} method returns a hash of form fields to render inside
68
+ # the form. Typically these are rendered as hidden input fields.
69
+ #
70
+ # ```erb
71
+ # <% @post.fields.each do |name, value| %>
72
+ # <input type="hidden" name="<%= name %>" value="<%= value %>"/>
73
+ # <% end %>
74
+ # ```
75
+ #
76
+ # Lastly, the form must have a file field with the name `file`.
77
+ #
78
+ # ```erb
79
+ # <input type="file" name="file"/>
80
+ # ```
81
+ #
82
+ # ## Post Policy
83
+ #
84
+ # When you construct a {PresignedPost}, you must specify every form
85
+ # field name that will be posted by the browser. If you omit a form
86
+ # field sent by the browser, Amazon S3 will reject the request.
87
+ # You can specify accepted form field values three ways:
88
+ #
89
+ # * Specify exactly what the value must be.
90
+ # * Specify what value the field starts with.
91
+ # * Specify the field may have any value.
92
+ #
93
+ # ### Field Equals
94
+ #
95
+ # You can specify that a form field must be a certain value.
96
+ # Simply pass an option like `:content_type` to the constructor,
97
+ # or call the associated method.
98
+ #
99
+ # ```ruby
100
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket).
101
+ # post.content_type('text/plain')
102
+ # ```
103
+ #
104
+ # If any of the given values are changed by the user in the form, then
105
+ # Amazon S3 will reject the POST request.
106
+ #
107
+ # ### Field Starts With
108
+ #
109
+ # You can specify prefix values for many of the POST form fields.
110
+ # To specify a required prefix, use the `:<fieldname>_starts_with`
111
+ # option or call the associated `#<field_name>_starts_with` method.
112
+ #
113
+ # ```ruby
114
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket, {
115
+ # key_starts_with: '/images/',
116
+ # content_type_starts_with: 'image/',
117
+ # # ...
118
+ # })
119
+ # ```
120
+ #
121
+ # When using starts with, the form must contain a field where the
122
+ # user can specify the value. The {PresignedPost} will not add
123
+ # a value for these fields.
124
+ #
125
+ # ### Any Field Value
126
+ #
127
+ # To white-list a form field to send any value, you can name that
128
+ # field with `:allow_any` or {#allow_any}.
129
+ #
130
+ # ```ruby
131
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket, {
132
+ # key: 'object-key',
133
+ # allow_any: ['Filename'],
134
+ # # ...
135
+ # })
136
+ # ```
137
+ #
138
+ # ### Metadata
139
+ #
140
+ # You can add rules for metadata fields using `:metadata`, {#metadata},
141
+ # `:metadata_starts_with` and {#metadata_starts_with}. Unlike other
142
+ # form fields, you pass a hash value to these options/methods:
143
+ #
144
+ # ```ruby
145
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket).
146
+ # key('/fixed/key').
147
+ # metadata(foo: 'bar')
148
+ #
149
+ # post.fields['x-amz-meta-foo']
150
+ # #=> 'bar'
151
+ # ```
152
+ #
153
+ # ### The `${filename}` Variable
154
+ #
155
+ # The string `${filename}` is automatically replaced with the name of the
156
+ # file provided by the user and is recognized by all form fields. It is
157
+ # not supported with `starts_with` conditions.
158
+ #
159
+ # If the browser or client provides a full or partial path to the file,
160
+ # only the text following the last slash (/) or backslash (\) will be used
161
+ # (e.g., "C:\Program Files\directory1\file.txt" will be interpreted
162
+ # as "file.txt"). If no file or file name is provided, the variable is
163
+ # replaced with an empty string.
164
+ #
165
+ # In the following example, we use `${filename}` to store the original
166
+ # filename in the `x-amz-meta-` hash with the uploaded object.
167
+ #
168
+ # ```ruby
169
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket, {
170
+ # key: '/fixed/key',
171
+ # metadata: {
172
+ # 'original-filename': '${filename}'
173
+ # }
174
+ # })
175
+ # ```
176
+ #
177
+ class PresignedPost
178
+
179
+ # @param [Credentials] credentials Security credentials for signing
180
+ # the post policy.
181
+ # @param [String] bucket_region Region of the target bucket.
182
+ # @param [String] bucket_name Name of the target bucket.
183
+ # @option options [Time] :signature_expiration Specify when the signature on
184
+ # the post will expire. Defaults to one hour from creation of the
185
+ # presigned post. May not exceed one week from creation time.
186
+ # @option options [String] :key See {PresignedPost#key}.
187
+ # @option options [String] :key_starts_with See {PresignedPost#key_starts_with}.
188
+ # @option options [String] :acl See {PresignedPost#acl}.
189
+ # @option options [String] :acl_starts_with See {PresignedPost#acl_starts_with}.
190
+ # @option options [String] :cache_control See {PresignedPost#cache_control}.
191
+ # @option options [String] :cache_control_starts_with See {PresignedPost#cache_control_starts_with}.
192
+ # @option options [String] :content_type See {PresignedPost#content_type}.
193
+ # @option options [String] :content_type_starts_with See {PresignedPost#content_type_starts_with}.
194
+ # @option options [String] :content_disposition See {PresignedPost#content_disposition}.
195
+ # @option options [String] :content_disposition_starts_with See {PresignedPost#content_disposition_starts_with}.
196
+ # @option options [String] :content_encoding See {PresignedPost#content_encoding}.
197
+ # @option options [String] :content_encoding_starts_with See {PresignedPost#content_encoding_starts_with}.
198
+ # @option options [String] :expires See {PresignedPost#expires}.
199
+ # @option options [String] :expires_starts_with See {PresignedPost#expires_starts_with}.
200
+ # @option options [Range<Integer>] :content_length_range See {PresignedPost#content_length_range}.
201
+ # @option options [String] :success_action_redirect See {PresignedPost#success_action_redirect}.
202
+ # @option options [String] :success_action_redirect_starts_with See {PresignedPost#success_action_redirect_starts_with}.
203
+ # @option options [String] :success_action_status See {PresignedPost#success_action_status}.
204
+ # @option options [String] :storage_class See {PresignedPost#storage_class}.
205
+ # @option options [String] :website_redirect_location See {PresignedPost#website_redirect_location}.
206
+ # @option options [Hash<String,String>] :metadata See {PresignedPost#metadata}.
207
+ # @option options [Hash<String,String>] :metadata_starts_with See {PresignedPost#metadata_starts_with}.
208
+ # @option options [String] :server_side_encryption See {PresignedPost#server_side_encryption}.
209
+ # @option options [String] :server_side_encryption_aws_kms_key_id See {PresignedPost#server_side_encryption_aws_kms_key_id}.
210
+ # @option options [String] :server_side_encryption_customer_algorithm See {PresignedPost#server_side_encryption_customer_algorithm}.
211
+ # @option options [String] :server_side_encryption_customer_key See {PresignedPost#server_side_encryption_customer_key}.
212
+ def initialize(credentials, bucket_region, bucket_name, options = {})
213
+ @credentials = credentials
214
+ @bucket_region = bucket_region
215
+ @bucket_name = bucket_name
216
+ @url = bucket_url
217
+ @fields = {}
218
+ @signature_expiration = Time.now + 3600
219
+ @conditions = [{ 'bucket' => @bucket_name }]
220
+ options.each do |option_name, option_value|
221
+ case option_name
222
+ when :allow_any then allow_any(option_value)
223
+ when :signature_expiration then @signature_expiration = option_value
224
+ else send("#{option_name}", option_value)
225
+ end
226
+ end
227
+ end
228
+
229
+ # @return [String] The URL to post a file upload to. This should be
230
+ # the form action.
231
+ attr_reader :url
232
+
233
+ # @return [Hash] A hash of fields to render in an HTML form
234
+ # as hidden input fields.
235
+ def fields
236
+ check_required_values!
237
+ datetime = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
238
+ fields = @fields.dup
239
+ fields.update('policy' => policy(datetime))
240
+ fields.update(signature_fields(datetime))
241
+ fields.update('x-amz-signature' => signature(datetime, fields['policy']))
242
+ end
243
+
244
+ # A list of form fields to white-list with any value.
245
+ # @param [Sting, Array<String>] field_names
246
+ # @return [self]
247
+ def allow_any(*field_names)
248
+ field_names.flatten.each do |field_name|
249
+ @key_set = true if field_name.to_s == 'key'
250
+ starts_with(field_name, '')
251
+ end
252
+ self
253
+ end
254
+
255
+ # @api private
256
+ def self.define_field(field, *args)
257
+ options = args.last.is_a?(Hash) ? args.pop : {}
258
+ field_name = args.last || field.to_s
259
+
260
+ define_method("#{field}") do |value|
261
+ with(field_name, value)
262
+ end
263
+
264
+ if options[:starts_with]
265
+ define_method("#{field}_starts_with") do |value|
266
+ starts_with(field_name, value)
267
+ end
268
+ end
269
+ end
270
+
271
+ # @!group Fields
272
+
273
+ # The key to use for the uploaded object. Use can use `${filename}`
274
+ # as a variable in the key. This will be replaced with the name
275
+ # of the file as provided by the user.
276
+ #
277
+ # For example, if the key is given as `/user/betty/${filename}` and
278
+ # the file uploaded is named `lolcatz.jpg`, the resultant key will
279
+ # be `/user/betty/lolcatz.jpg`.
280
+ #
281
+ # @param [String] key
282
+ # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html)
283
+ # @return [self]
284
+ def key(key)
285
+ @key_set = true
286
+ with('key', key)
287
+ end
288
+
289
+ # Specify a prefix the uploaded
290
+ # @param [String] prefix
291
+ # @see #key
292
+ # @return [self]
293
+ def key_starts_with(prefix)
294
+ @key_set = true
295
+ starts_with('key', prefix)
296
+ end
297
+
298
+ # @!method acl(canned_acl)
299
+ # Specify the cannedl ACL (access control list) for the object.
300
+ # May be one of the following values:
301
+ #
302
+ # * `private`
303
+ # * `public-read`
304
+ # * `public-read-write`
305
+ # * `authenticated-read`
306
+ # * `bucket-owner-read`
307
+ # * `bucket-owner-full-control`
308
+ #
309
+ # @param [String] canned_acl
310
+ # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
311
+ # @return [self]
312
+ #
313
+ # @!method acl_starts_with(prefix)
314
+ # @param [String] prefix
315
+ # @see #acl
316
+ # @return [self]
317
+ define_field(:acl, starts_with: true)
318
+
319
+ # @!method cache_control(value)
320
+ # Specify caching behavior along the request/reply chain.
321
+ # @param [String] value
322
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.
323
+ # @return [self]
324
+ #
325
+ # @!method cache_control_starts_with(prefix)
326
+ # @param [String] prefix
327
+ # @see #cache_control
328
+ # @return [self]
329
+ define_field(:cache_control, 'Cache-Control', starts_with: true)
330
+
331
+ # @return [String]
332
+ # @!method content_type(value)
333
+ # A standard MIME type describing the format of the contents.
334
+ # @param [String] value
335
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
336
+ # @return [self]
337
+ #
338
+ # @!method content_type_starts_with(prefix)
339
+ # @param [String] prefix
340
+ # @see #content_type
341
+ # @return [self]
342
+ define_field(:content_type, 'Content-Type', starts_with: true)
343
+
344
+ # @!method content_disposition(value)
345
+ # Specifies presentational information for the object.
346
+ # @param [String] value
347
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
348
+ # @return [self]
349
+ #
350
+ # @!method content_disposition_starts_with(prefix)
351
+ # @param [String] prefix
352
+ # @see #content_disposition
353
+ # @return [self]
354
+ define_field(:content_disposition, 'Content-Disposition', starts_with: true)
355
+
356
+ # @!method content_encoding(value)
357
+ # Specifies what content encodings have been applied to the object
358
+ # and thus what decoding mechanisms must be applied to obtain the
359
+ # media-type referenced by the Content-Type header field.
360
+ # @param [String] value
361
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
362
+ # @return [self]
363
+ #
364
+ # @!method content_encoding_starts_with(prefix)
365
+ # @param [String] prefix
366
+ # @see #content_encoding
367
+ # @return [self]
368
+ define_field(:content_encoding, 'Content-Encoding', starts_with: true)
369
+
370
+ # The date and time at which the object is no longer cacheable.
371
+ # @note This does not affect the expiration of the presigned post
372
+ # signature.
373
+ # @param [Time] time
374
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
375
+ # @return [self]
376
+ def expires(time)
377
+ with('Expires', time.httpdate)
378
+ end
379
+
380
+ # @param [String] prefix
381
+ # @see #expires
382
+ # @return [self]
383
+ def expires_starts_with(prefix)
384
+ starts_with('Expires', prefix)
385
+ end
386
+
387
+ # The minimum and maximum allowable size for the uploaded content.
388
+ # @param [Range<Ineger>] byte_range
389
+ # @return [self]
390
+ def content_length_range(byte_range)
391
+ min = byte_range.begin
392
+ max = byte_range.end
393
+ max -= 1 if byte_range.exclude_end?
394
+ @conditions << ['content-length-range', min, max]
395
+ self
396
+ end
397
+
398
+ # @!method success_action_redirect(value)
399
+ # The URL to which the client is redirected
400
+ # upon successful upload. If {#success_action_redirect} is not
401
+ # specified, Amazon S3 returns the empty document type specified
402
+ # by {#success_action_status}.
403
+ #
404
+ # If Amazon S3 cannot interpret the URL, it acts as if the field
405
+ # is not present. If the upload fails, Amazon S3 displays an error
406
+ # and does not redirect the user to a URL.
407
+ #
408
+ # @param [String] value
409
+ # @return [self]
410
+ #
411
+ # @!method success_action_redirect_starts_with(prefix)
412
+ # @param [String] prefix
413
+ # @see #success_action_redirect
414
+ # @return [self]
415
+ define_field(:success_action_redirect, starts_with: true)
416
+
417
+ # @!method success_action_status(value)
418
+ # The status code returned to the client upon
419
+ # successful upload if {#success_action_redirect} is not
420
+ # specified.
421
+ #
422
+ # Accepts the values `200`, `201`, or `204` (default).
423
+ #
424
+ # If the value is set to 200 or 204, Amazon S3 returns an empty
425
+ # document with a 200 or 204 status code. If the value is set to 201,
426
+ # Amazon S3 returns an XML document with a 201 status code.
427
+ #
428
+ # If the value is not set or if it is set to an invalid value, Amazon
429
+ # S3 returns an empty document with a 204 status code.
430
+ #
431
+ # @param [String] The status code returned to the client upon
432
+ # @return [self]
433
+ define_field(:success_action_status)
434
+
435
+ # @!method storage_class(value)
436
+ # Storage class to use for storing the object. Defaults to
437
+ # `STANDARD`. Must be one of:
438
+ #
439
+ # * `STANDARD`
440
+ # * `REDUCED_REDUNDANCY`
441
+ #
442
+ # You cannot specify `GLACIER` as the storage class. To transition
443
+ # objects to the GLACIER storage class you can use lifecycle
444
+ # configuration.
445
+ # @param [String] value Storage class to use for storing the
446
+ # @return [self]
447
+ define_field(:storage_class)
448
+
449
+ # @!method website_redirect_location(value)
450
+ # If the bucket is configured as a website,
451
+ # redirects requests for this object to another object in the
452
+ # same bucket or to an external URL. Amazon S3 stores this value
453
+ # in the object metadata.
454
+ #
455
+ # The value must be prefixed by, "/", "http://" or "https://".
456
+ # The length of the value is limited to 2K.
457
+ #
458
+ # @param [String] value
459
+ # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
460
+ # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
461
+ # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/how-to-page-redirect.html
462
+ # @return [self]
463
+ define_field(:website_redirect_location, 'x-amz-website-redirect-location')
464
+
465
+ # Metadata hash to store with the uploaded object. Hash keys will be
466
+ # prefixed with "x-amz-meta-".
467
+ # @param [Hash<String,String>] hash
468
+ # @return [self]
469
+ def metadata(hash)
470
+ hash.each do |key, value|
471
+ with("x-amz-meta-#{key}", value)
472
+ end
473
+ self
474
+ end
475
+
476
+ # Specify allowable prefix for each key in the metadata hash.
477
+ # @param [Hash<String,String>] hash
478
+ # @see #metadata
479
+ # @return [self]
480
+ def metadata_starts_with(hash)
481
+ hash.each do |key, value|
482
+ starts_with("x-amz-meta-#{key}", value)
483
+ end
484
+ self
485
+ end
486
+
487
+ # @!endgroup
488
+
489
+ # @!group Server-Side Encryption Fields
490
+
491
+ # @!method server_side_encryption(value)
492
+ # Specifies a server-side encryption algorithm to use when Amazon
493
+ # S3 creates an object. Valid values include:
494
+ #
495
+ # * `aws:kms`
496
+ # * `AES256`
497
+ #
498
+ # @param [String] value
499
+ # @return [self]
500
+ define_field(:server_side_encryption, 'x-amz-server-side-encryption')
501
+
502
+ # @!method server_side_encryption_aws_kms_key_id(value)
503
+ # If {#server_side_encryption} is called with the value of `aws:kms`,
504
+ # this method specifies the ID of the AWS Key Management Service
505
+ # (KMS) master encryption key to use for the object.
506
+ # @param [String] value
507
+ # @return [self]
508
+ define_field(:server_side_encryption_aws_kms_key_id, 'x-amz-server-side-encryption-aws-kms-key-id')
509
+
510
+ # @!endgroup
511
+
512
+ # @!group Server-Side Encryption with Customer-Provided Key Fields
513
+
514
+ # @!method server_side_encryption_customer_algorithm(value)
515
+ # Specifies the algorithm to use to when encrypting the object.
516
+ # Must be set to `AES256` when using customer-provided encryption
517
+ # keys. Must also call {#server_side_encryption_customer_key}.
518
+ # @param [String] value
519
+ # @see #server_side_encryption_customer_key
520
+ # @return [self]
521
+ define_field(:server_side_encryption_customer_algorithm, 'x-amz-server-side-encryption-customer-algorithm')
522
+
523
+ # Specifies the customer-provided encryption key for Amazon S3 to use
524
+ # in encrypting data. This value is used to store the object and then
525
+ # it is discarded; Amazon does not store the encryption key.
526
+ #
527
+ # You must also call {#server_side_encryption_customer_algorithm}.
528
+ #
529
+ # @param [String] value
530
+ # @see #server_side_encryption_customer_algorithm
531
+ # @return [self]
532
+ def server_side_encryption_customer_key(value)
533
+ field_name = 'x-amz-server-side-encryption-customer-key'
534
+ with(field_name, value)
535
+ with(field_name + '-MD5', base64(OpenSSL::Digest::MD5.digest(value)))
536
+ end
537
+
538
+ # @param [String] prefix
539
+ # @see #server_side_encryption_customer_key
540
+ # @return [self]
541
+ def server_side_encryption_customer_key_starts_with(prefix)
542
+ field_name = 'x-amz-server-side-encryption-customer-key'
543
+ starts_with(field_name, prefix)
544
+ end
545
+
546
+ # @!endgroup
547
+
548
+ private
549
+
550
+ def with(field_name, value)
551
+ fvar = '${filename}'
552
+ if index = value.rindex(fvar)
553
+ if index + fvar.size == value.size
554
+ @fields[field_name] = value
555
+ starts_with(field_name, value[0,index])
556
+ else
557
+ msg = "${filename} only supported at the end of #{field_name}"
558
+ raise ArgumentError, msg
559
+ end
560
+ else
561
+ @fields[field_name] = value.to_s
562
+ @conditions << { field_name => value.to_s }
563
+ end
564
+ self
565
+ end
566
+
567
+ def starts_with(field_name, value, &block)
568
+ @conditions << ['starts-with', "$#{field_name}", value.to_s]
569
+ self
570
+ end
571
+
572
+ def check_required_values!
573
+ unless @key_set
574
+ msg = "key required; you must provide a key via :key, "
575
+ msg << ":key_starts_with, or :allow_any => ['key']"
576
+ raise msg
577
+ end
578
+ end
579
+
580
+ def bucket_url
581
+ url = EndpointProvider.resolve(@bucket_region, 's3')
582
+ url = URI.parse(url)
583
+ if Plugins::S3BucketDns.dns_compatible?(@bucket_name, true)
584
+ url.host = @bucket_name + '.' + url.host
585
+ else
586
+ url.path = '/' + @bucket_name
587
+ end
588
+ url.to_s
589
+ end
590
+
591
+ # @return [Hash]
592
+ def policy(datetime)
593
+ check_required_values!
594
+ policy = {}
595
+ policy['expiration'] = @signature_expiration.utc.iso8601
596
+ policy['conditions'] = @conditions.dup
597
+ signature_fields(datetime).each do |name, value|
598
+ policy['conditions'] << { name => value }
599
+ end
600
+ base64(MultiJson.dump(policy))
601
+ end
602
+
603
+ def signature_fields(datetime)
604
+ fields = {}
605
+ fields['x-amz-credential'] = credential_scope(datetime)
606
+ fields['x-amz-algorithm'] = 'AWS4-HMAC-SHA256'
607
+ fields['x-amz-date'] = datetime
608
+ if session_token = @credentials.session_token
609
+ fields['x-amz-security-token'] = session_token
610
+ end
611
+ fields
612
+ end
613
+
614
+ def signature(datetime, string_to_sign)
615
+ k_secret = @credentials.secret_access_key
616
+ k_date = hmac("AWS4" + k_secret, datetime[0,8])
617
+ k_region = hmac(k_date, @bucket_region)
618
+ k_service = hmac(k_region, 's3')
619
+ k_credentials = hmac(k_service, 'aws4_request')
620
+ hexhmac(k_credentials, string_to_sign)
621
+ end
622
+
623
+ def hmac(key, value)
624
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, value)
625
+ end
626
+
627
+ def hexhmac(key, value)
628
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, value)
629
+ end
630
+
631
+ def credential_scope(datetime)
632
+ parts = []
633
+ parts << @credentials.access_key_id
634
+ parts << datetime[0,8]
635
+ parts << @bucket_region
636
+ parts << 's3'
637
+ parts << 'aws4_request'
638
+ parts.join('/')
639
+ end
640
+
641
+ def base64(str)
642
+ Base64.strict_encode64(str)
643
+ end
644
+
645
+ end
646
+ end
647
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-sdk-resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.33
4
+ version: 2.0.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-26 00:00:00.000000000 Z
11
+ date: 2015-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.33
19
+ version: 2.0.34
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.0.33
26
+ version: 2.0.34
27
27
  description: Provides resource oriented interfaces and other higher-level abstractions
28
28
  for many AWS services. This gem is part of the official AWS SDK for Ruby.
29
29
  email:
@@ -77,6 +77,7 @@ files:
77
77
  - lib/aws-sdk-resources/services/s3/multipart_upload_error.rb
78
78
  - lib/aws-sdk-resources/services/s3/object.rb
79
79
  - lib/aws-sdk-resources/services/s3/object_summary.rb
80
+ - lib/aws-sdk-resources/services/s3/presigned_post.rb
80
81
  - lib/aws-sdk-resources/services/s3/public_url.rb
81
82
  - lib/aws-sdk-resources/services/sns.rb
82
83
  - lib/aws-sdk-resources/services/sns/message_verifier.rb