mss-sdk 1.0.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.
- checksums.yaml +7 -0
- data/.yardopts +9 -0
- data/LICENSE.txt +0 -0
- data/README.md +192 -0
- data/bin/mss-rb +178 -0
- data/ca-bundle.crt +3554 -0
- data/lib/mss/core/async_handle.rb +89 -0
- data/lib/mss/core/cacheable.rb +76 -0
- data/lib/mss/core/client.rb +786 -0
- data/lib/mss/core/collection/simple.rb +81 -0
- data/lib/mss/core/collection/with_limit_and_next_token.rb +70 -0
- data/lib/mss/core/collection/with_next_token.rb +96 -0
- data/lib/mss/core/collection.rb +262 -0
- data/lib/mss/core/configuration.rb +527 -0
- data/lib/mss/core/credential_providers.rb +653 -0
- data/lib/mss/core/data.rb +251 -0
- data/lib/mss/core/deprecations.rb +83 -0
- data/lib/mss/core/endpoints.rb +36 -0
- data/lib/mss/core/http/connection_pool.rb +374 -0
- data/lib/mss/core/http/curb_handler.rb +150 -0
- data/lib/mss/core/http/handler.rb +88 -0
- data/lib/mss/core/http/net_http_handler.rb +144 -0
- data/lib/mss/core/http/patch.rb +98 -0
- data/lib/mss/core/http/request.rb +258 -0
- data/lib/mss/core/http/response.rb +80 -0
- data/lib/mss/core/indifferent_hash.rb +87 -0
- data/lib/mss/core/inflection.rb +55 -0
- data/lib/mss/core/ini_parser.rb +41 -0
- data/lib/mss/core/json_client.rb +46 -0
- data/lib/mss/core/json_parser.rb +75 -0
- data/lib/mss/core/json_request_builder.rb +34 -0
- data/lib/mss/core/json_response_parser.rb +78 -0
- data/lib/mss/core/lazy_error_classes.rb +107 -0
- data/lib/mss/core/log_formatter.rb +426 -0
- data/lib/mss/core/managed_file.rb +31 -0
- data/lib/mss/core/meta_utils.rb +44 -0
- data/lib/mss/core/model.rb +61 -0
- data/lib/mss/core/naming.rb +29 -0
- data/lib/mss/core/option_grammar.rb +737 -0
- data/lib/mss/core/options/json_serializer.rb +81 -0
- data/lib/mss/core/options/validator.rb +154 -0
- data/lib/mss/core/options/xml_serializer.rb +117 -0
- data/lib/mss/core/page_result.rb +74 -0
- data/lib/mss/core/policy.rb +938 -0
- data/lib/mss/core/query_client.rb +40 -0
- data/lib/mss/core/query_error_parser.rb +23 -0
- data/lib/mss/core/query_request_builder.rb +46 -0
- data/lib/mss/core/query_response_parser.rb +34 -0
- data/lib/mss/core/region.rb +84 -0
- data/lib/mss/core/region_collection.rb +79 -0
- data/lib/mss/core/resource.rb +412 -0
- data/lib/mss/core/resource_cache.rb +39 -0
- data/lib/mss/core/response.rb +214 -0
- data/lib/mss/core/response_cache.rb +49 -0
- data/lib/mss/core/rest_error_parser.rb +23 -0
- data/lib/mss/core/rest_json_client.rb +39 -0
- data/lib/mss/core/rest_request_builder.rb +153 -0
- data/lib/mss/core/rest_response_parser.rb +65 -0
- data/lib/mss/core/rest_xml_client.rb +46 -0
- data/lib/mss/core/service_interface.rb +82 -0
- data/lib/mss/core/signers/base.rb +45 -0
- data/lib/mss/core/signers/cloud_front.rb +55 -0
- data/lib/mss/core/signers/s3.rb +158 -0
- data/lib/mss/core/signers/version_2.rb +71 -0
- data/lib/mss/core/signers/version_3.rb +85 -0
- data/lib/mss/core/signers/version_3_https.rb +60 -0
- data/lib/mss/core/signers/version_4/chunk_signed_stream.rb +190 -0
- data/lib/mss/core/signers/version_4.rb +227 -0
- data/lib/mss/core/uri_escape.rb +43 -0
- data/lib/mss/core/xml/frame.rb +245 -0
- data/lib/mss/core/xml/frame_stack.rb +84 -0
- data/lib/mss/core/xml/grammar.rb +306 -0
- data/lib/mss/core/xml/parser.rb +69 -0
- data/lib/mss/core/xml/root_frame.rb +64 -0
- data/lib/mss/core/xml/sax_handlers/libxml.rb +46 -0
- data/lib/mss/core/xml/sax_handlers/nokogiri.rb +55 -0
- data/lib/mss/core/xml/sax_handlers/ox.rb +40 -0
- data/lib/mss/core/xml/sax_handlers/rexml.rb +46 -0
- data/lib/mss/core/xml/stub.rb +122 -0
- data/lib/mss/core.rb +602 -0
- data/lib/mss/errors.rb +161 -0
- data/lib/mss/rails.rb +194 -0
- data/lib/mss/s3/access_control_list.rb +262 -0
- data/lib/mss/s3/acl_object.rb +263 -0
- data/lib/mss/s3/acl_options.rb +200 -0
- data/lib/mss/s3/bucket.rb +757 -0
- data/lib/mss/s3/bucket_collection.rb +161 -0
- data/lib/mss/s3/bucket_lifecycle_configuration.rb +472 -0
- data/lib/mss/s3/bucket_region_cache.rb +51 -0
- data/lib/mss/s3/bucket_tag_collection.rb +110 -0
- data/lib/mss/s3/bucket_version_collection.rb +78 -0
- data/lib/mss/s3/cipher_io.rb +119 -0
- data/lib/mss/s3/client/xml.rb +265 -0
- data/lib/mss/s3/client.rb +2076 -0
- data/lib/mss/s3/config.rb +60 -0
- data/lib/mss/s3/cors_rule.rb +107 -0
- data/lib/mss/s3/cors_rule_collection.rb +193 -0
- data/lib/mss/s3/data_options.rb +190 -0
- data/lib/mss/s3/encryption_utils.rb +145 -0
- data/lib/mss/s3/errors.rb +93 -0
- data/lib/mss/s3/multipart_upload.rb +353 -0
- data/lib/mss/s3/multipart_upload_collection.rb +75 -0
- data/lib/mss/s3/object_collection.rb +355 -0
- data/lib/mss/s3/object_metadata.rb +102 -0
- data/lib/mss/s3/object_upload_collection.rb +76 -0
- data/lib/mss/s3/object_version.rb +153 -0
- data/lib/mss/s3/object_version_collection.rb +88 -0
- data/lib/mss/s3/paginated_collection.rb +74 -0
- data/lib/mss/s3/policy.rb +73 -0
- data/lib/mss/s3/prefix_and_delimiter_collection.rb +46 -0
- data/lib/mss/s3/prefixed_collection.rb +84 -0
- data/lib/mss/s3/presign_v4.rb +135 -0
- data/lib/mss/s3/presigned_post.rb +574 -0
- data/lib/mss/s3/region_detection.rb +75 -0
- data/lib/mss/s3/request.rb +61 -0
- data/lib/mss/s3/s3_object.rb +1795 -0
- data/lib/mss/s3/tree/branch_node.rb +67 -0
- data/lib/mss/s3/tree/child_collection.rb +103 -0
- data/lib/mss/s3/tree/leaf_node.rb +93 -0
- data/lib/mss/s3/tree/node.rb +21 -0
- data/lib/mss/s3/tree/parent.rb +86 -0
- data/lib/mss/s3/tree.rb +115 -0
- data/lib/mss/s3/uploaded_part.rb +81 -0
- data/lib/mss/s3/uploaded_part_collection.rb +83 -0
- data/lib/mss/s3/website_configuration.rb +101 -0
- data/lib/mss/s3.rb +161 -0
- data/lib/mss/version.rb +16 -0
- data/lib/mss-sdk.rb +2 -0
- data/lib/mss.rb +14 -0
- data/rails/init.rb +14 -0
- metadata +201 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# For S3 buckets with versioning enabled, objects will store versions
|
17
|
+
# each time you write to them.
|
18
|
+
#
|
19
|
+
# object = bucket.objects['myobj']
|
20
|
+
# object.write('1')
|
21
|
+
# object.write('2')
|
22
|
+
# object.write('3')
|
23
|
+
#
|
24
|
+
# object.versions.collect(&:read)
|
25
|
+
# #=> ['1', '2', '3']
|
26
|
+
#
|
27
|
+
# To see all the version id for a particular object, access the any particular version,
|
28
|
+
# and see the latest version:
|
29
|
+
#
|
30
|
+
# object.versions.each do |version| puts version.version_id end
|
31
|
+
# #=> T2TwAiZ3SmNr7tOfe0QBa4RZnSb3GSLq
|
32
|
+
# #=> kAEHC_ysT65bT4P3zyYOP1ELA6ajar_6
|
33
|
+
# #=> itHPX6m8na_sog0cAtkgP3QITEE8v5ij
|
34
|
+
#
|
35
|
+
# object.versions['itHPX6m8na_sog0cAtkgP3QITEE8v5ij']
|
36
|
+
# #=> <MSS::S3::ObjectVersion:<<bucket>>:myobj:itHPX6m8na_sog0cAtkgP3QITEE8v5ij>
|
37
|
+
#
|
38
|
+
# object.versions.latest
|
39
|
+
# #=> <MSS::S3::ObjectVersion:<<bucket>>:myobj:T2TwAiZ3SmNr7tOfe0QBa4RZnSb3GSLq>
|
40
|
+
#
|
41
|
+
# If you know the id of a particular version you can get that object.
|
42
|
+
#
|
43
|
+
# bucket.objects['myobj'].version[version_id].delete
|
44
|
+
#
|
45
|
+
class ObjectVersionCollection
|
46
|
+
|
47
|
+
include Core::Model
|
48
|
+
include Enumerable
|
49
|
+
|
50
|
+
# @return [S3Object] The object this collection belongs to.
|
51
|
+
attr_reader :object
|
52
|
+
|
53
|
+
# @param [S3Object] object
|
54
|
+
def initialize object, options = {}
|
55
|
+
@object = object
|
56
|
+
super(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns an object that represents a single version of the {#object}.
|
60
|
+
# @param [String] version_id
|
61
|
+
# @return [ObjectVersion]
|
62
|
+
def [] version_id
|
63
|
+
ObjectVersion.new(object, version_id)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @note Generally you will just want to grab the object key its key.
|
67
|
+
# @return [ObjectVersion] Returns the latest version of this object.
|
68
|
+
def latest
|
69
|
+
self.find{|version| true }
|
70
|
+
end
|
71
|
+
|
72
|
+
# Yields once for each version of the {#object}.
|
73
|
+
#
|
74
|
+
# @yield [object_version]
|
75
|
+
# @yieldparam [ObectVersion] object_version
|
76
|
+
# @return [nil]
|
77
|
+
def each &block
|
78
|
+
object.bucket.versions.with_prefix(object.key).each do |version|
|
79
|
+
if version.key == object.key
|
80
|
+
yield(version)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
module PaginatedCollection
|
18
|
+
|
19
|
+
include Core::Collection::WithLimitAndNextToken
|
20
|
+
|
21
|
+
protected
|
22
|
+
def _each_item markers, limit, options = {}, &block
|
23
|
+
|
24
|
+
options = list_options(options)
|
25
|
+
options.merge!(markers) unless markers.nil? or markers.empty?
|
26
|
+
options[limit_param] = limit || 1000
|
27
|
+
|
28
|
+
response = list_request(options)
|
29
|
+
|
30
|
+
each_member_in_page(response, &block)
|
31
|
+
|
32
|
+
response.data[:truncated] ? next_markers(response) : nil
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def each_member_in_page(page, &block); end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def list_request(options)
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
def list_options options
|
46
|
+
opts = {}
|
47
|
+
opts[:bucket_name] = bucket.name if respond_to?(:bucket)
|
48
|
+
opts
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
def limit_param
|
53
|
+
raise NotImplementedError
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def pagination_markers
|
58
|
+
[:key_marker]
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
def next_markers page
|
63
|
+
pagination_markers.inject({}) do |markers, marker_name|
|
64
|
+
if marker = page.data[:"next_#{marker_name}"]
|
65
|
+
markers[marker_name] = marker if marker
|
66
|
+
end
|
67
|
+
markers
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# (see Core::Policy)
|
17
|
+
class Policy < Core::Policy
|
18
|
+
|
19
|
+
class Statement < Core::Policy::Statement
|
20
|
+
|
21
|
+
ACTION_MAPPING = {
|
22
|
+
:list_buckets => "s3:ListAllMyBuckets",
|
23
|
+
:create_bucket => "s3:CreateBucket",
|
24
|
+
:delete_bucket => "s3:DeleteBucket",
|
25
|
+
:list_objects => "s3:ListBucket",
|
26
|
+
:list_object_versions => "s3:ListBucketVersions",
|
27
|
+
:list_multipart_uploads => "s3:ListBucketMultipartUploads",
|
28
|
+
:get_object => "s3:GetObject",
|
29
|
+
:get_object_version => "s3:GetObjectVersion",
|
30
|
+
:put_object => "s3:PutObject",
|
31
|
+
:get_object_acl => "s3:GetObjectAcl",
|
32
|
+
:get_object_version_acl => "s3:GetObjectVersionAcl",
|
33
|
+
:set_object_acl => "s3:PutObjectAcl",
|
34
|
+
:set_object_acl_version => "s3:PutObjectAclVersion",
|
35
|
+
:delete_object => "s3:DeleteObject",
|
36
|
+
:delete_object_version => "s3:DeleteObjectVersion",
|
37
|
+
:list_multipart_upload_parts => "s3:ListMultipartUploadParts",
|
38
|
+
:abort_multipart_upload => "s3:AbortMultipartUpload",
|
39
|
+
:get_bucket_acl => "s3:GetBucketAcl",
|
40
|
+
:set_bucket_acl => "s3:PutBucketAcl",
|
41
|
+
:get_bucket_versioning => "s3:GetBucketVersioning",
|
42
|
+
:set_bucket_versioning => "s3:PutBucketVersioning",
|
43
|
+
:get_bucket_requester_pays => "s3:GetBucketRequesterPays",
|
44
|
+
:set_bucket_requester_pays => "s3:PutBucketRequesterPays",
|
45
|
+
:get_bucket_location => "s3:GetBucketLocation",
|
46
|
+
:get_bucket_policy => "s3:GetBucketPolicy",
|
47
|
+
:set_bucket_policy => "s3:PutBucketPolicy",
|
48
|
+
:get_bucket_notification => "s3:GetBucketNotification",
|
49
|
+
:set_bucket_notification => "s3:PutBucketNotification"
|
50
|
+
}
|
51
|
+
|
52
|
+
protected
|
53
|
+
def resource_arn resource
|
54
|
+
prefix = 'arn:mss:s3:::'
|
55
|
+
case resource
|
56
|
+
when Bucket
|
57
|
+
"#{prefix}#{resource.name}"
|
58
|
+
when S3Object
|
59
|
+
"#{prefix}#{resource.bucket.name}/#{resource.key}"
|
60
|
+
when ObjectCollection
|
61
|
+
"#{prefix}#{resource.bucket.name}/#{resource.prefix}*"
|
62
|
+
when /^arn:/
|
63
|
+
resource
|
64
|
+
else
|
65
|
+
"arn:mss:s3:::#{resource}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
module PrefixAndDelimiterCollection
|
18
|
+
|
19
|
+
include PrefixedCollection
|
20
|
+
|
21
|
+
# @see Bucket#as_tree
|
22
|
+
def as_tree options = {}
|
23
|
+
Tree.new(self, { :prefix => prefix }.merge(options))
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
protected
|
28
|
+
def each_member_in_page(page, &block)
|
29
|
+
super
|
30
|
+
page.common_prefixes.each do |p|
|
31
|
+
yield(with_prefix(p[:prefix]))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
protected
|
37
|
+
def list_options(options)
|
38
|
+
opts = super
|
39
|
+
opts[:delimiter] = options[:delimiter] if options.key?(:delimiter)
|
40
|
+
opts
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
module PrefixedCollection
|
17
|
+
|
18
|
+
include PaginatedCollection
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def initialize *args
|
22
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
23
|
+
@prefix = options[:prefix]
|
24
|
+
args.push(options)
|
25
|
+
super(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [String,nil] The prefix of this collection.
|
29
|
+
attr_reader :prefix
|
30
|
+
|
31
|
+
# Returns a new collection with a different prefix
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
#
|
35
|
+
# objects = collection.with_prefix('photos')
|
36
|
+
# objects.prefix #=> 'photos'
|
37
|
+
#
|
38
|
+
# @example Chaining with_prefix replaces previous prefix
|
39
|
+
#
|
40
|
+
# objects = collection.with_prefix('photos').with_prefix('videos')
|
41
|
+
# objects.prefix #=> 'videos'
|
42
|
+
#
|
43
|
+
# @example Chaining with_prefix with :append
|
44
|
+
#
|
45
|
+
# objects = collection.with_prefix('a/').with_prefix('b/', :append)
|
46
|
+
# objects.prefix #=> 'a/b/'
|
47
|
+
#
|
48
|
+
# @example Chaining with_prefix with :prepend
|
49
|
+
#
|
50
|
+
# objects = collection.with_prefix('a/').with_prefix('b/', :prepend)
|
51
|
+
# objects.prefix #=> 'b/a/'
|
52
|
+
#
|
53
|
+
# @param [String] prefix The prefix condition that limits what objects
|
54
|
+
# are returned by this collection.
|
55
|
+
# @param [Symbol] mode (:replace) If you chain calls to #with_prefix
|
56
|
+
# the `mode` affects if the prefix prepends, appends, or replaces.
|
57
|
+
# Valid modes are:
|
58
|
+
# * `:replace`
|
59
|
+
# * `:append`
|
60
|
+
# * `:prepend`
|
61
|
+
# @return [Collection] Returns a new collection with a modified prefix.
|
62
|
+
def with_prefix prefix, mode = :replace
|
63
|
+
new_prefix = case mode
|
64
|
+
when :replace then prefix
|
65
|
+
when :append then "#{@prefix}#{prefix}"
|
66
|
+
when :prepend then "#{prefix}#{@prefix}"
|
67
|
+
else
|
68
|
+
raise ArgumentError, "invalid prefix mode `#{mode}`, it must be " +
|
69
|
+
":replace, :append or :prepend"
|
70
|
+
end
|
71
|
+
self.class.new(bucket, :prefix => new_prefix)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @api private
|
75
|
+
protected
|
76
|
+
def list_options(options)
|
77
|
+
opts = super
|
78
|
+
opts[:prefix] = prefix if prefix
|
79
|
+
opts
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# Utility class for building pre-signed URLs for Amazon S3 objects using
|
17
|
+
# signature version 4.
|
18
|
+
class PresignV4
|
19
|
+
|
20
|
+
# @param [S3Object] object
|
21
|
+
def initialize(object)
|
22
|
+
@object = object
|
23
|
+
@client = object.client
|
24
|
+
@signer = object.client.send(:v4_signer)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [S3Object]
|
28
|
+
attr_reader :object
|
29
|
+
|
30
|
+
# @return [Client]
|
31
|
+
attr_reader :client
|
32
|
+
|
33
|
+
# @return [Core::Signers::Version4]
|
34
|
+
attr_reader :signer
|
35
|
+
|
36
|
+
# @param (see S3Object#url_for)
|
37
|
+
# @option (see S3Object#url_for)
|
38
|
+
# @return (see S3Object#url_for)
|
39
|
+
def presign(method, options = {})
|
40
|
+
|
41
|
+
now = Time.now.utc
|
42
|
+
one_week = 60 * 60 * 24 * 7
|
43
|
+
if options[:expires] - now.to_i > one_week
|
44
|
+
msg = "presigned URLs using sigv4 may not expire more than one week out"
|
45
|
+
raise ArgumentError, msg
|
46
|
+
end
|
47
|
+
|
48
|
+
now = now.strftime("%Y%m%dT%H%M%SZ")
|
49
|
+
|
50
|
+
request = build_request(method, options)
|
51
|
+
|
52
|
+
request.headers.clear
|
53
|
+
request.headers['host'] = request.host
|
54
|
+
signed_headers = 'Host'
|
55
|
+
|
56
|
+
if options[:acl]
|
57
|
+
request.add_param("x-amz-acl", options[:acl].to_s.gsub(/_/, '-'))
|
58
|
+
end
|
59
|
+
|
60
|
+
# must be sent along with the PUT request headers
|
61
|
+
if options[:content_md5]
|
62
|
+
request.headers['Content-MD5'] = options[:content_md5]
|
63
|
+
signed_headers << ';Content-MD5'
|
64
|
+
end
|
65
|
+
|
66
|
+
request_params = Core::Signers::S3::QUERY_PARAMS.map do |p|
|
67
|
+
param = p.tr("-","_").to_sym
|
68
|
+
if options.key?(param)
|
69
|
+
request.add_param(p, options[param])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
token = client.credential_provider.session_token
|
74
|
+
|
75
|
+
request.add_param("X-Amz-Algorithm", "MSS4-HMAC-SHA256")
|
76
|
+
request.add_param("X-Amz-Date", now)
|
77
|
+
request.add_param("X-Amz-SignedHeaders", signed_headers)
|
78
|
+
request.add_param("X-Amz-Expires", seconds_away(options[:expires]))
|
79
|
+
request.add_param('X-Amz-Security-Token', token) if token
|
80
|
+
request.add_param("X-Amz-Credential", signer.credential(now))
|
81
|
+
request.add_param("X-Amz-Signature", signature(request, now))
|
82
|
+
|
83
|
+
build_uri(request, options)
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def build_request(method, options)
|
90
|
+
path_style = object.config.s3_force_path_style
|
91
|
+
params = options.merge(
|
92
|
+
:bucket_name => object.bucket.name,
|
93
|
+
:key => object.key,
|
94
|
+
:data => ''
|
95
|
+
)
|
96
|
+
req = client.send(:build_request, operation_name(method), params)
|
97
|
+
req.force_path_style = options.fetch(:force_path_style, path_style)
|
98
|
+
req
|
99
|
+
end
|
100
|
+
|
101
|
+
def operation_name(method)
|
102
|
+
case method
|
103
|
+
when :get, :read then :get_object
|
104
|
+
when :put, :write then :put_object
|
105
|
+
when :delete then :delete_object
|
106
|
+
when :head then :head_object
|
107
|
+
else
|
108
|
+
msg = "invalid method, expected :get, :put or :delete, got "
|
109
|
+
msg << method.inspect
|
110
|
+
raise ArgumentError msg
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def signature(request, datetime)
|
115
|
+
key = signer.derive_key(datetime)
|
116
|
+
signer.signature(request, key, datetime, 'UNSIGNED-PAYLOAD')
|
117
|
+
end
|
118
|
+
|
119
|
+
def build_uri(request, options)
|
120
|
+
uri_class = options[:secure] ? URI::HTTPS : URI::HTTP
|
121
|
+
uri_class.build(
|
122
|
+
:host => request.host,
|
123
|
+
:port => request.port,
|
124
|
+
:path => request.path,
|
125
|
+
:query => request.querystring
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def seconds_away(expires)
|
130
|
+
expires - Time.now.to_i
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|