aliyun-sdk 0.1.8 → 0.2.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +28 -4
- data/examples/aliyun/oss/bucket.rb +1 -1
- data/examples/aliyun/oss/object.rb +1 -1
- data/examples/aliyun/oss/resumable_download.rb +1 -1
- data/examples/aliyun/oss/resumable_upload.rb +1 -1
- data/examples/aliyun/oss/streaming.rb +1 -1
- data/examples/aliyun/oss/using_sts.rb +48 -0
- data/examples/aliyun/sts/assume_role.rb +59 -0
- data/lib/aliyun/common.rb +6 -0
- data/lib/aliyun/common/exception.rb +18 -0
- data/lib/aliyun/{oss → common}/logging.rb +3 -3
- data/lib/aliyun/common/struct.rb +56 -0
- data/lib/aliyun/oss.rb +1 -2
- data/lib/aliyun/oss/bucket.rb +1 -1
- data/lib/aliyun/oss/client.rb +2 -2
- data/lib/aliyun/oss/config.rb +3 -2
- data/lib/aliyun/oss/download.rb +3 -0
- data/lib/aliyun/oss/exception.rb +2 -14
- data/lib/aliyun/oss/http.rb +3 -1
- data/lib/aliyun/oss/multipart.rb +2 -4
- data/lib/aliyun/oss/object.rb +1 -1
- data/lib/aliyun/oss/protocol.rb +1 -1
- data/lib/aliyun/oss/struct.rb +5 -54
- data/lib/aliyun/oss/upload.rb +3 -0
- data/lib/aliyun/oss/util.rb +1 -1
- data/lib/aliyun/sts.rb +9 -0
- data/lib/aliyun/sts/client.rb +38 -0
- data/lib/aliyun/sts/config.rb +21 -0
- data/lib/aliyun/sts/exception.rb +53 -0
- data/lib/aliyun/sts/protocol.rb +130 -0
- data/lib/aliyun/sts/struct.rb +64 -0
- data/lib/aliyun/sts/util.rb +48 -0
- data/lib/aliyun/{oss/version.rb → version.rb} +1 -3
- data/spec/aliyun/oss/client/client_spec.rb +21 -1
- data/spec/aliyun/sts/client_spec.rb +150 -0
- data/spec/aliyun/sts/util_spec.rb +39 -0
- metadata +21 -4
@@ -0,0 +1,48 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'cgi'
|
5
|
+
require 'base64'
|
6
|
+
require 'openssl'
|
7
|
+
require 'digest/md5'
|
8
|
+
|
9
|
+
module Aliyun
|
10
|
+
module STS
|
11
|
+
##
|
12
|
+
# Util functions to help generate formatted Date, signatures,
|
13
|
+
# etc.
|
14
|
+
#
|
15
|
+
module Util
|
16
|
+
|
17
|
+
class << self
|
18
|
+
|
19
|
+
include Common::Logging
|
20
|
+
|
21
|
+
# Calculate request signatures
|
22
|
+
def get_signature(verb, params, key)
|
23
|
+
logger.debug("Sign, verb: #{verb}, params: #{params}")
|
24
|
+
|
25
|
+
cano_query = params.sort.map {
|
26
|
+
|k, v| [CGI.escape(k), CGI.escape(v)].join('=') }.join('&')
|
27
|
+
|
28
|
+
string_to_sign =
|
29
|
+
verb + '&' + CGI.escape('/') + '&' + CGI.escape(cano_query)
|
30
|
+
|
31
|
+
logger.debug("String to sign: #{string_to_sign}")
|
32
|
+
|
33
|
+
Util.sign(key + '&', string_to_sign)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sign a string using HMAC and BASE64
|
37
|
+
# @param [String] key the secret key
|
38
|
+
# @param [String] string_to_sign the string to sign
|
39
|
+
# @return [String] the signature
|
40
|
+
def sign(key, string_to_sign)
|
41
|
+
Base64.strict_encode64(
|
42
|
+
OpenSSL::HMAC.digest('sha1', key, string_to_sign))
|
43
|
+
end
|
44
|
+
|
45
|
+
end # self
|
46
|
+
end # Util
|
47
|
+
end # STS
|
48
|
+
end # Aliyun
|
@@ -14,12 +14,14 @@ module Aliyun
|
|
14
14
|
endpoint = 'oss-cn-hangzhou.aliyuncs.com'
|
15
15
|
client = Client.new(
|
16
16
|
:endpoint => endpoint,
|
17
|
-
:access_key_id => 'xxx ', :access_key_secret => ' yyy '
|
17
|
+
:access_key_id => 'xxx ', :access_key_secret => ' yyy ',
|
18
|
+
:sts_token => 'sts-token')
|
18
19
|
|
19
20
|
config = client.instance_variable_get('@config')
|
20
21
|
expect(config.endpoint.to_s).to eq("http://#{endpoint}")
|
21
22
|
expect(config.access_key_id).to eq('xxx')
|
22
23
|
expect(config.access_key_secret).to eq('yyy')
|
24
|
+
expect(config.sts_token).to eq('sts-token')
|
23
25
|
end
|
24
26
|
|
25
27
|
it "should not set Authorization with anonymous client" do
|
@@ -37,6 +39,24 @@ module Aliyun
|
|
37
39
|
.with{ |req| not req.headers.has_key?('Authorization') }
|
38
40
|
end
|
39
41
|
|
42
|
+
it "should set STS header" do
|
43
|
+
endpoint = 'oss-cn-hangzhou.aliyuncs.com'
|
44
|
+
bucket = 'rubysdk-bucket'
|
45
|
+
object = 'rubysdk-object'
|
46
|
+
client = Client.new(
|
47
|
+
:endpoint => endpoint,
|
48
|
+
:access_key_id => 'xxx', :access_key_secret => 'yyy',
|
49
|
+
:sts_token => 'sts-token')
|
50
|
+
|
51
|
+
stub_request(:get, "#{bucket}.#{endpoint}/#{object}")
|
52
|
+
|
53
|
+
client.get_bucket(bucket).get_object(object) {}
|
54
|
+
|
55
|
+
expect(WebMock)
|
56
|
+
.to have_requested(:get, "#{bucket}.#{endpoint}/#{object}")
|
57
|
+
.with{ |req| not req.headers.has_key?('x-oss-security-token') }
|
58
|
+
end
|
59
|
+
|
40
60
|
it "should construct different client" do
|
41
61
|
bucket = 'rubysdk-bucket'
|
42
62
|
object = 'rubysdk-object'
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Aliyun
|
6
|
+
module STS
|
7
|
+
|
8
|
+
describe Client do
|
9
|
+
|
10
|
+
context "construct" do
|
11
|
+
it "should setup a/k" do
|
12
|
+
client = Client.new(
|
13
|
+
:access_key_id => 'xxx', :access_key_secret => 'yyy')
|
14
|
+
|
15
|
+
config = client.instance_variable_get('@config')
|
16
|
+
expect(config.access_key_id).to eq('xxx')
|
17
|
+
expect(config.access_key_secret).to eq('yyy')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def mock_sts(id, key, token, expiration)
|
22
|
+
Nokogiri::XML::Builder.new do |xml|
|
23
|
+
xml.AssumeRoleResponse {
|
24
|
+
xml.RequestId '0000'
|
25
|
+
xml.AssumedRoleUser {
|
26
|
+
xml.arn 'arn-001'
|
27
|
+
xml.AssumedRoleUserId 'id-001'
|
28
|
+
}
|
29
|
+
xml.Credentials {
|
30
|
+
xml.AccessKeyId id
|
31
|
+
xml.AccessKeySecret key
|
32
|
+
xml.SecurityToken token
|
33
|
+
xml.Expiration expiration.utc.iso8601
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end.to_xml
|
37
|
+
end
|
38
|
+
|
39
|
+
def mock_error(code, message)
|
40
|
+
Nokogiri::XML::Builder.new do |xml|
|
41
|
+
xml.Error {
|
42
|
+
xml.Code code
|
43
|
+
xml.Message message
|
44
|
+
xml.RequestId '0000'
|
45
|
+
}
|
46
|
+
end.to_xml
|
47
|
+
end
|
48
|
+
|
49
|
+
def err(msg, reqid = '0000')
|
50
|
+
"#{msg} RequestId: #{reqid}"
|
51
|
+
end
|
52
|
+
|
53
|
+
before :all do
|
54
|
+
@url = 'https://sts.aliyuncs.com'
|
55
|
+
@client = Client.new(access_key_id: 'xxx', access_key_secret: 'yyy')
|
56
|
+
end
|
57
|
+
|
58
|
+
context "assume role" do
|
59
|
+
it "should assume role" do
|
60
|
+
expiration = Time.parse(Time.now.utc.iso8601)
|
61
|
+
|
62
|
+
stub_request(:post, @url)
|
63
|
+
.to_return(:body => mock_sts(
|
64
|
+
'sts_id', 'sts_key', 'sts_token', expiration))
|
65
|
+
|
66
|
+
token = @client.assume_role('role-1', 'app-1')
|
67
|
+
|
68
|
+
rbody = nil
|
69
|
+
expect(WebMock).to have_requested(:post, @url)
|
70
|
+
.with { |req| rbody = req.body }
|
71
|
+
params = rbody.split('&').reduce({}) { |h, i|
|
72
|
+
v = i.split('=')
|
73
|
+
h.merge({v[0] => v[1]})
|
74
|
+
}
|
75
|
+
expect(params['Action']).to eq('AssumeRole')
|
76
|
+
expect(params['RoleArn']).to eq('role-1')
|
77
|
+
expect(params['RoleSessionName']).to eq('app-1')
|
78
|
+
expect(params['DurationSeconds']).to eq('3600')
|
79
|
+
expect(params['Format']).to eq('XML')
|
80
|
+
expect(params['Version']).to eq('2015-04-01')
|
81
|
+
expect(params['AccessKeyId']).to eq('xxx')
|
82
|
+
expect(params.key?('Signature')).to be true
|
83
|
+
expect(params.key?('SignatureNonce')).to be true
|
84
|
+
expect(params['SignatureMethod']).to eq('HMAC-SHA1')
|
85
|
+
|
86
|
+
expect(token.access_key_id).to eq('sts_id')
|
87
|
+
expect(token.access_key_secret).to eq('sts_key')
|
88
|
+
expect(token.security_token).to eq('sts_token')
|
89
|
+
expect(token.expiration).to eq(expiration)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should raise error" do
|
93
|
+
code = "InvalidParameter"
|
94
|
+
message = "Bla bla bla."
|
95
|
+
|
96
|
+
stub_request(:post, @url)
|
97
|
+
.to_return(:status => 400,
|
98
|
+
:body => mock_error(code, message))
|
99
|
+
|
100
|
+
|
101
|
+
expect {
|
102
|
+
@client.assume_role('role-1', 'app-1')
|
103
|
+
}.to raise_error(ServerError, err(message))
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should set policy and duration" do
|
108
|
+
expiration = Time.parse(Time.now.utc.iso8601)
|
109
|
+
|
110
|
+
stub_request(:post, @url)
|
111
|
+
.to_return(:body => mock_sts(
|
112
|
+
'sts_id', 'sts_key', 'sts_token', expiration))
|
113
|
+
|
114
|
+
policy = Policy.new
|
115
|
+
policy.allow(
|
116
|
+
['oss:Get*', 'oss:PutObject'],
|
117
|
+
['acs:oss:*:*:bucket', 'acs::oss:*:*:bucket/*'])
|
118
|
+
duration = 300
|
119
|
+
token = @client.assume_role('role-1', 'app-1', policy, duration)
|
120
|
+
|
121
|
+
rbody = nil
|
122
|
+
expect(WebMock).to have_requested(:post, @url)
|
123
|
+
.with { |req| rbody = req.body }
|
124
|
+
params = rbody.split('&').reduce({}) { |h, i|
|
125
|
+
v = i.split('=')
|
126
|
+
h.merge({v[0] => CGI.unescape(v[1])})
|
127
|
+
}
|
128
|
+
expect(params['Action']).to eq('AssumeRole')
|
129
|
+
expect(params['RoleArn']).to eq('role-1')
|
130
|
+
expect(params['RoleSessionName']).to eq('app-1')
|
131
|
+
expect(params['DurationSeconds']).to eq('300')
|
132
|
+
expect(params['Format']).to eq('XML')
|
133
|
+
expect(params['Version']).to eq('2015-04-01')
|
134
|
+
expect(params['AccessKeyId']).to eq('xxx')
|
135
|
+
expect(params.key?('Signature')).to be true
|
136
|
+
expect(params.key?('SignatureNonce')).to be true
|
137
|
+
expect(params['SignatureMethod']).to eq('HMAC-SHA1')
|
138
|
+
expect(params['Policy']).to eq(policy.serialize)
|
139
|
+
|
140
|
+
expect(token.access_key_id).to eq('sts_id')
|
141
|
+
expect(token.access_key_secret).to eq('sts_key')
|
142
|
+
expect(token.security_token).to eq('sts_token')
|
143
|
+
expect(token.expiration).to eq(expiration)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end # Client
|
148
|
+
|
149
|
+
end # OSS
|
150
|
+
end # Aliyun
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'yaml'
|
5
|
+
require 'nokogiri'
|
6
|
+
|
7
|
+
module Aliyun
|
8
|
+
module STS
|
9
|
+
|
10
|
+
describe Util do
|
11
|
+
|
12
|
+
it "should get correct signature" do
|
13
|
+
key = 'helloworld'
|
14
|
+
ts = '2015-12-07T07:18:41Z'
|
15
|
+
|
16
|
+
params = {
|
17
|
+
'Action' => 'AssumeRole',
|
18
|
+
'RoleArn' => 'role-1',
|
19
|
+
'RoleSessionName' => 'app-1',
|
20
|
+
'DurationSeconds' => '300',
|
21
|
+
'Format' => 'XML',
|
22
|
+
'Version' => '2015-04-01',
|
23
|
+
'AccessKeyId' => 'xxx',
|
24
|
+
'SignatureMethod' => 'HMAC-SHA1',
|
25
|
+
'SignatureVersion' => '1.0',
|
26
|
+
'SignatureNonce' => '3.14159',
|
27
|
+
'Timestamp' => ts
|
28
|
+
}
|
29
|
+
|
30
|
+
signature = Util.get_signature('POST', params, key)
|
31
|
+
expect(signature).to eq("92ta30QopCT4YTbRCaWtS31kyeg=")
|
32
|
+
|
33
|
+
signature = Util.get_signature('GET', params, key)
|
34
|
+
expect(signature).to eq("nvMmnOSxGrfK+1zf0oFR5RB2M7k=")
|
35
|
+
end
|
36
|
+
|
37
|
+
end # Util
|
38
|
+
end # OSS
|
39
|
+
end # Aliyun
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aliyun-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tianlong Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -124,6 +124,12 @@ files:
|
|
124
124
|
- examples/aliyun/oss/resumable_download.rb
|
125
125
|
- examples/aliyun/oss/resumable_upload.rb
|
126
126
|
- examples/aliyun/oss/streaming.rb
|
127
|
+
- examples/aliyun/oss/using_sts.rb
|
128
|
+
- examples/aliyun/sts/assume_role.rb
|
129
|
+
- lib/aliyun/common.rb
|
130
|
+
- lib/aliyun/common/exception.rb
|
131
|
+
- lib/aliyun/common/logging.rb
|
132
|
+
- lib/aliyun/common/struct.rb
|
127
133
|
- lib/aliyun/oss.rb
|
128
134
|
- lib/aliyun/oss/bucket.rb
|
129
135
|
- lib/aliyun/oss/client.rb
|
@@ -132,14 +138,20 @@ files:
|
|
132
138
|
- lib/aliyun/oss/exception.rb
|
133
139
|
- lib/aliyun/oss/http.rb
|
134
140
|
- lib/aliyun/oss/iterator.rb
|
135
|
-
- lib/aliyun/oss/logging.rb
|
136
141
|
- lib/aliyun/oss/multipart.rb
|
137
142
|
- lib/aliyun/oss/object.rb
|
138
143
|
- lib/aliyun/oss/protocol.rb
|
139
144
|
- lib/aliyun/oss/struct.rb
|
140
145
|
- lib/aliyun/oss/upload.rb
|
141
146
|
- lib/aliyun/oss/util.rb
|
142
|
-
- lib/aliyun/
|
147
|
+
- lib/aliyun/sts.rb
|
148
|
+
- lib/aliyun/sts/client.rb
|
149
|
+
- lib/aliyun/sts/config.rb
|
150
|
+
- lib/aliyun/sts/exception.rb
|
151
|
+
- lib/aliyun/sts/protocol.rb
|
152
|
+
- lib/aliyun/sts/struct.rb
|
153
|
+
- lib/aliyun/sts/util.rb
|
154
|
+
- lib/aliyun/version.rb
|
143
155
|
- spec/aliyun/oss/bucket_spec.rb
|
144
156
|
- spec/aliyun/oss/client/bucket_spec.rb
|
145
157
|
- spec/aliyun/oss/client/client_spec.rb
|
@@ -150,6 +162,8 @@ files:
|
|
150
162
|
- spec/aliyun/oss/object_spec.rb
|
151
163
|
- spec/aliyun/oss/service_spec.rb
|
152
164
|
- spec/aliyun/oss/util_spec.rb
|
165
|
+
- spec/aliyun/sts/client_spec.rb
|
166
|
+
- spec/aliyun/sts/util_spec.rb
|
153
167
|
- tests/test_content_type.rb
|
154
168
|
- tests/test_encoding.rb
|
155
169
|
- tests/test_large_file.rb
|
@@ -191,9 +205,12 @@ test_files:
|
|
191
205
|
- spec/aliyun/oss/object_spec.rb
|
192
206
|
- spec/aliyun/oss/service_spec.rb
|
193
207
|
- spec/aliyun/oss/util_spec.rb
|
208
|
+
- spec/aliyun/sts/client_spec.rb
|
209
|
+
- spec/aliyun/sts/util_spec.rb
|
194
210
|
- tests/test_content_type.rb
|
195
211
|
- tests/test_encoding.rb
|
196
212
|
- tests/test_large_file.rb
|
197
213
|
- tests/test_multipart.rb
|
198
214
|
- tests/test_object_key.rb
|
199
215
|
- tests/test_resumable.rb
|
216
|
+
has_rdoc:
|