aws-url 0.1.1 → 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.
- data/README.md +3 -11
- data/aws-url.gemspec +3 -3
- data/lib/aws/url.rb +43 -36
- data/lib/aws/url/signature.rb +31 -0
- data/lib/aws/url/version.rb +1 -1
- data/spec/aws/url_spec.rb +25 -18
- metadata +19 -8
data/README.md
CHANGED
@@ -2,18 +2,10 @@
|
|
2
2
|
|
3
3
|
[![travis][status]][travis]
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
![bezos][bezos]
|
8
|
-
|
9
|
-
[Vacuum][vacuum] and [Peddler][peddler] use AWS URL.
|
10
|
-
|
11
|
-
[Fog][fog] doesn't.
|
5
|
+
AWS URL is a minimum-viable URL builder for [Amazon Web Services (AWS)][aws]
|
6
|
+
API queries. It signs requests with [Signature Version 2][sign].
|
12
7
|
|
13
8
|
[status]: https://secure.travis-ci.org/hakanensari/aws-url.png
|
14
9
|
[travis]: http://travis-ci.org/hakanensari/aws-url
|
15
10
|
[aws]: http://aws.amazon.com/
|
16
|
-
[
|
17
|
-
[peddler]: https://github.com/hakanensari/peddler
|
18
|
-
[fog]: https://github.com/fog/fog
|
19
|
-
[bezos]: http://www.wired.com/images/article/magazine/1605/mf_amazon_f.jpg
|
11
|
+
[sign]: http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html
|
data/aws-url.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.authors = ['Hakan Ensari']
|
7
7
|
gem.email = ['hakan.ensari@papercavalier.com']
|
8
8
|
gem.description = %q{A minimum-viable URL builder for Amazon Web Services (AWS)}
|
9
|
-
gem.summary = %q{
|
9
|
+
gem.summary = %q{Signs an Amazon Web Services URL}
|
10
10
|
gem.homepage = 'https://github.com/hakanensari/aws-url'
|
11
11
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
@@ -16,6 +16,6 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
gem.version = AWS::URL::VERSION
|
18
18
|
|
19
|
-
gem.add_development_dependency 'rake',
|
20
|
-
gem.add_development_dependency 'rspec',
|
19
|
+
gem.add_development_dependency 'rake', '~> 0.9'
|
20
|
+
gem.add_development_dependency 'rspec', '~> 2.9'
|
21
21
|
end
|
data/lib/aws/url.rb
CHANGED
@@ -1,63 +1,57 @@
|
|
1
|
+
# Standard library dependencies.
|
1
2
|
require 'base64'
|
2
3
|
require 'openssl'
|
3
4
|
require 'time'
|
4
5
|
require 'uri'
|
5
6
|
|
7
|
+
# Internal dependencies.
|
8
|
+
require 'aws/url/signature'
|
9
|
+
|
6
10
|
module AWS
|
7
11
|
# A Signed Amazon Web Services (AWS) URL.
|
8
12
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# Note to self: Do not touch this code unless you have a compelling reason.
|
13
|
+
# Supports Signature Version 2.
|
12
14
|
class URL
|
13
|
-
|
14
|
-
SHA256 = OpenSSL::Digest::SHA256.new
|
15
|
+
UNRESERVED = /([^\w.~-]+)/
|
15
16
|
|
16
17
|
# Initializes a new URL.
|
17
18
|
#
|
18
19
|
# base_url - The String base URL, including scheme, host and path, of the
|
19
20
|
# AWS endpoint.
|
21
|
+
# action - The String-like HTTP action.
|
20
22
|
# key - The String AWS access key id.
|
21
23
|
# secret - The String AWS secret key.
|
22
|
-
def initialize(base_url, key, secret)
|
24
|
+
def initialize(base_url, action, key, secret)
|
23
25
|
@base_url = URI base_url
|
26
|
+
@action = action.to_s.upcase
|
24
27
|
@key = key
|
25
28
|
@secret = secret
|
26
29
|
@params = {}
|
27
30
|
end
|
28
31
|
|
29
|
-
# Builds a signed URL for specified HTTP method.
|
30
|
-
#
|
31
|
-
# method - A String-like HTTP method.
|
32
|
-
#
|
33
|
-
# Returns a String URL.
|
34
|
-
def build(method)
|
35
|
-
# Build an unsigned query string.
|
36
|
-
query = params.sort.map { |k, v| "#{k}=#{ percent_encode v }" }.join '&'
|
37
|
-
|
38
|
-
# Build the signature.
|
39
|
-
string_to_sign = [
|
40
|
-
method.to_s.upcase,
|
41
|
-
@base_url.host,
|
42
|
-
@base_url.path,
|
43
|
-
query
|
44
|
-
].join "\n"
|
45
|
-
signature = sign string_to_sign
|
46
|
-
|
47
|
-
"#{@base_url}?#{query}&Signature=#{percent_encode signature}"
|
48
|
-
end
|
49
|
-
|
50
32
|
# Returns the Hash AWS parameters.
|
51
33
|
def params
|
52
34
|
default_params.merge @params
|
53
35
|
end
|
54
36
|
|
37
|
+
# Returns the signed query String.
|
38
|
+
def query
|
39
|
+
"#{unsigned_query}&Signature=#{escape signature}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the signed URL String.
|
43
|
+
def to_s
|
44
|
+
"#{@base_url}?#{query}"
|
45
|
+
end
|
46
|
+
|
55
47
|
# Updates the AWS parameters.
|
56
48
|
#
|
57
49
|
# hash - A Hash.
|
58
50
|
#
|
59
51
|
# Returns self.
|
60
52
|
def update(hash)
|
53
|
+
@unsigned_query = nil
|
54
|
+
|
61
55
|
hash.each do |key, val|
|
62
56
|
# Syntactic sugar: Camelize symbol keys.
|
63
57
|
if key.is_a? Symbol
|
@@ -71,12 +65,6 @@ module AWS
|
|
71
65
|
|
72
66
|
private
|
73
67
|
|
74
|
-
def percent_encode(value)
|
75
|
-
value.to_s.gsub(/([^\w.~-]+)/) do
|
76
|
-
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
68
|
def default_params
|
81
69
|
{
|
82
70
|
'AWSAccessKeyId' => @key,
|
@@ -86,9 +74,28 @@ module AWS
|
|
86
74
|
}
|
87
75
|
end
|
88
76
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
77
|
+
def escape(value)
|
78
|
+
value.to_s.gsub(UNRESERVED) do
|
79
|
+
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def signature
|
84
|
+
Signature.build @secret, string_to_sign
|
85
|
+
end
|
86
|
+
|
87
|
+
def string_to_sign
|
88
|
+
[
|
89
|
+
@action,
|
90
|
+
@base_url.host,
|
91
|
+
@base_url.path,
|
92
|
+
unsigned_query
|
93
|
+
].join "\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
def unsigned_query
|
97
|
+
@unsigned_query ||=
|
98
|
+
params.map { |k, v| "#{k}=#{ escape v }" }.sort.join '&'
|
92
99
|
end
|
93
100
|
end
|
94
101
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module AWS
|
2
|
+
class URL
|
3
|
+
# Internal: A signature builder.
|
4
|
+
class Signature
|
5
|
+
SHA256 = OpenSSL::Digest::SHA256.new
|
6
|
+
|
7
|
+
# Builds a signature.
|
8
|
+
#
|
9
|
+
# secret - A String AWS secret key.
|
10
|
+
# message - The String to sign.
|
11
|
+
#
|
12
|
+
# Returns a String signature.
|
13
|
+
def self.build(secret, message)
|
14
|
+
new(secret, message).build
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(secret, message)
|
18
|
+
@secret = secret
|
19
|
+
@message = message
|
20
|
+
end
|
21
|
+
|
22
|
+
def build
|
23
|
+
Base64.encode64(digest).chomp
|
24
|
+
end
|
25
|
+
|
26
|
+
def digest
|
27
|
+
OpenSSL::HMAC.digest SHA256, @secret, @message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/aws/url/version.rb
CHANGED
data/spec/aws/url_spec.rb
CHANGED
@@ -2,41 +2,48 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module AWS
|
4
4
|
describe URL do
|
5
|
-
|
6
5
|
before do
|
7
6
|
@base_url = 'http://example.com/path'
|
8
|
-
@url = URL.new @base_url, 'key', 'secret'
|
9
|
-
end
|
10
|
-
|
11
|
-
describe '#build' do
|
12
|
-
subject { @url.build :get }
|
13
|
-
|
14
|
-
it 'includes the base URL' do
|
15
|
-
should { include @base_url }
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'is signed' do
|
19
|
-
should { match /Signature=[^&]+$/ }
|
20
|
-
end
|
7
|
+
@url = URL.new @base_url, :get, 'key', 'secret'
|
21
8
|
end
|
22
9
|
|
23
10
|
describe '#params' do
|
24
11
|
subject { @url.params }
|
25
12
|
|
26
13
|
it 'includes a key' do
|
27
|
-
should
|
14
|
+
should include 'AWSAccessKeyId'
|
28
15
|
end
|
29
16
|
|
30
17
|
it 'includes a signature version' do
|
31
|
-
should
|
18
|
+
should include 'SignatureVersion'
|
32
19
|
end
|
33
20
|
|
34
21
|
it 'includes a signature method' do
|
35
|
-
should
|
22
|
+
should include 'SignatureMethod'
|
36
23
|
end
|
37
24
|
|
38
25
|
it 'includes a timestamp' do
|
39
|
-
should
|
26
|
+
should include 'Timestamp'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#query' do
|
31
|
+
subject { @url.query }
|
32
|
+
|
33
|
+
it 'is signed' do
|
34
|
+
should match /Signature=[^&]+$/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#to_s' do
|
39
|
+
subject { @url.to_s }
|
40
|
+
|
41
|
+
it 'includes the base URL' do
|
42
|
+
should include @base_url
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'includes the signed query' do
|
46
|
+
should include @url.query
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-url
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0.9'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.9'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rspec
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: '2.9'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.9'
|
36
46
|
description: A minimum-viable URL builder for Amazon Web Services (AWS)
|
37
47
|
email:
|
38
48
|
- hakan.ensari@papercavalier.com
|
@@ -49,6 +59,7 @@ files:
|
|
49
59
|
- aws-url.gemspec
|
50
60
|
- lib/aws-url.rb
|
51
61
|
- lib/aws/url.rb
|
62
|
+
- lib/aws/url/signature.rb
|
52
63
|
- lib/aws/url/version.rb
|
53
64
|
- spec/aws/url_spec.rb
|
54
65
|
- spec/spec_helper.rb
|
@@ -72,10 +83,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
83
|
version: '0'
|
73
84
|
requirements: []
|
74
85
|
rubyforge_project:
|
75
|
-
rubygems_version: 1.8.
|
86
|
+
rubygems_version: 1.8.23
|
76
87
|
signing_key:
|
77
88
|
specification_version: 3
|
78
|
-
summary:
|
89
|
+
summary: Signs an Amazon Web Services URL
|
79
90
|
test_files:
|
80
91
|
- spec/aws/url_spec.rb
|
81
92
|
- spec/spec_helper.rb
|