awsraw 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # awsraw
2
+
3
+ A client for [Amazon Web Services](http://www.amazonaws.com/) in the style of
4
+ [FlickRaw](http://hanklords.github.com/flickraw/)
5
+
6
+ ## Background
7
+
8
+ AWSRaw helps you make authenticated requests to AWS's various services. It
9
+ doesn't provide any higher-level concepts like, for example, "delete this
10
+ file from S3". Instead, you should understand S3's http API and know that
11
+ sending a `DELETE` request to the bucket/key URL will result in the file
12
+ being deleted.
13
+
14
+ While these higher-level concepts can be useful (see, e.g.,
15
+ [fog](https://github.com/fog/fog)), they can also get in the way. Being
16
+ able to use a new AWS feature by simply following the AWS docs' examples
17
+ directly is very nice, instead of having to dig deep into a higher-level
18
+ library to figure out how they've mapped that new feature into their
19
+ terminology and API.
20
+
21
+ ## Usage
22
+
23
+ ### S3
24
+
25
+ Standard requests:
26
+
27
+ ```ruby
28
+ require 'awsraw/s3/client'
29
+
30
+ s3 = AWSRaw::S3::Client.new(
31
+ ENV['AWS_ACCESS_KEY_ID'],
32
+ ENV['AWS_SECRET_ACCESS_KEY'])
33
+
34
+ s3.request(:method => "PUT",
35
+ :bucket => "mah-sekret-buckit",
36
+ :key => "reaction.gif",
37
+ :content => File.read("reaction.gif"),
38
+ :headers => { "Content-Type" => "image/gif" })
39
+ ```
40
+
41
+ Signed query-string requests, to allow authorized clients to get protected
42
+ resources:
43
+
44
+ ```ruby
45
+ require 'awsraw/s3/query_string_signer'
46
+
47
+ signer = AWSRaw::S3::QueryStringSigner.new(
48
+ ENV['AWS_ACCESS_KEY_ID'],
49
+ ENV['AWS_SECRET_ACCESS_KEY'])
50
+
51
+ url = "http://s3.amazonaws.com/mah-sekret-bucket/reaction.gif"
52
+ expiry = Time.now.utc + 60 # 1 minute from now
53
+ temporary_url = signer.sign_with_query_string(url, expiry.to_i)
54
+ puts temporary_url
55
+ # => "http://s3.amazonaws.com/mah-sekret-bucket/reaction.gif?Signature=..."
56
+ ```
data/awsraw.gemspec CHANGED
@@ -5,8 +5,8 @@ require "awsraw/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "awsraw"
7
7
  s.version = Awsraw::VERSION
8
- s.authors = ["Pete Yandell"]
9
- s.email = ["pete@notahat.com"]
8
+ s.authors = ["Pete Yandell", "David Goodlad"]
9
+ s.email = ["pete@notahat.com", "david@goodlad.net"]
10
10
  s.homepage = "http://github.com/envato/awsraw"
11
11
  s.summary = %q{Minimal AWS client}
12
12
  s.description = %q{A client for Amazon Web Services in the style of FlickRaw}
@@ -0,0 +1,53 @@
1
+ require 'awsraw/s3/signer'
2
+ require 'cgi'
3
+
4
+ module AWSRaw
5
+ module S3
6
+
7
+ # Generates a signed query string to make an authenticated S3 GET request
8
+ #
9
+ # See http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
10
+ #
11
+ # The Authorization header method is usually preferable, as implemented in
12
+ # AWSRaw::S3::Signer. However, you may have occasions where you need a
13
+ # simple "download URL", without having to tell your user-agent (browser,
14
+ # curl, wget, etc) about all the special AWS headers. The query string
15
+ # authentication method is useful in those cases.
16
+ class QueryStringSigner < Signer
17
+ def sign_with_query_string(url, expires)
18
+ query_string_hash = query_string_hash(url, expires)
19
+
20
+ uri = URI.parse(url)
21
+ uri.query = query_string_hash.map { |k,v| "#{k}=#{v}" }.join("&")
22
+ uri.to_s
23
+ end
24
+
25
+ def query_string_hash(url, expires)
26
+ string_to_sign = string_to_sign(url, expires)
27
+ signature = encoded_signature(string_to_sign)
28
+
29
+ {
30
+ "AWSAccessKeyId" => @access_key_id,
31
+ "Expires" => expires.to_s,
32
+ "Signature" => CGI.escape(signature)
33
+ }
34
+ end
35
+
36
+ def string_to_sign(url, expires)
37
+ [
38
+ "GET",
39
+ # Assume user-agent won't send Content-MD5 header
40
+ "",
41
+ # Assume user-agent won't send Content-Type header
42
+ "",
43
+ expires.to_s,
44
+ # Assume user-agent won't send any amz headers
45
+ canonicalized_amz_headers({}),
46
+ canonicalized_resource(URI.parse(url))
47
+ ].flatten.join("\n")
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -16,14 +16,20 @@ module AWSRaw
16
16
  @secret_access_key = secret_access_key
17
17
  end
18
18
 
19
- def signature(request)
19
+ def authorization_header_value(request)
20
20
  string_to_sign = string_to_sign(request)
21
+ signature = encoded_signature(string_to_sign)
21
22
 
23
+ "AWS #{@access_key_id}:#{signature}"
24
+ end
25
+
26
+ # Backwards compatibility
27
+ alias_method :signature, :authorization_header_value
28
+
29
+ def encoded_signature(string_to_sign)
22
30
  digest = OpenSSL::Digest::Digest.new("sha1")
23
31
  sha = OpenSSL::HMAC.digest(digest, @secret_access_key, string_to_sign)
24
32
  signature = Base64.encode64(sha).strip
25
-
26
- "AWS #{@access_key_id}:#{signature}"
27
33
  end
28
34
 
29
35
  def string_to_sign(request)
@@ -1,3 +1,3 @@
1
1
  module Awsraw
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,29 @@
1
+ require 'awsraw/s3/query_string_signer'
2
+
3
+ describe AWSRaw::S3::QueryStringSigner do
4
+ let(:access_key_id) { "AKIAIOSFODNN7EXAMPLE" }
5
+ let(:secret_access_key) { "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" }
6
+
7
+ subject { AWSRaw::S3::QueryStringSigner.new(access_key_id, secret_access_key) }
8
+
9
+ context "examples from Amazon docs" do
10
+ it "signs a get request correctly" do
11
+ url = "http://s3.amazonaws.com/johnsmith/photos/puppy.jpg"
12
+ expiry = 1175139620
13
+
14
+ subject.string_to_sign(url, expiry).should ==
15
+ "GET\n\n\n#{expiry}\n/johnsmith/photos/puppy.jpg"
16
+
17
+ subject.query_string_hash(url, expiry).should == {
18
+ "AWSAccessKeyId" => access_key_id,
19
+ "Expires" => expiry.to_s,
20
+ "Signature" => "NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D"
21
+ }
22
+
23
+ subject.sign_with_query_string(url, expiry).to_s.should ==
24
+ "http://s3.amazonaws.com/johnsmith/photos/puppy.jpg?AWSAccessKeyId=#{access_key_id}&Expires=#{expiry}&Signature=NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D"
25
+ end
26
+
27
+ end
28
+ end
29
+
@@ -1,8 +1,8 @@
1
1
  require 'awsraw/s3/signer'
2
2
 
3
3
  describe AWSRaw::S3::Signer do
4
- let(:access_key_id) { "0PN5J17HBGZHT7JJ3X82" }
5
- let(:secret_access_key) { "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o" }
4
+ let(:access_key_id) { "AKIAIOSFODNN7EXAMPLE" }
5
+ let(:secret_access_key) { "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" }
6
6
 
7
7
  subject { AWSRaw::S3::Signer.new(access_key_id, secret_access_key) }
8
8
 
@@ -17,7 +17,7 @@ describe AWSRaw::S3::Signer do
17
17
  subject.string_to_sign(request).should ==
18
18
  "GET\n\n\nTue, 27 Mar 2007 19:36:42 +0000\n/johnsmith/photos/puppy.jpg"
19
19
 
20
- subject.signature(request).should == "AWS #{access_key_id}:xXjDGYUmKxnwqr5KXNPGldn5LbA="
20
+ subject.signature(request).should == "AWS #{access_key_id}:bWq2s1WEIj+Ydj0vQ697zp+IXMU="
21
21
  end
22
22
 
23
23
  it "signs an upload correctly" do
@@ -42,7 +42,7 @@ describe AWSRaw::S3::Signer do
42
42
  subject.string_to_sign(request).should ==
43
43
  "PUT\n4gJE4saaMU4BqNR0kLY+lw==\napplication/x-download\nTue, 27 Mar 2007 21:06:08 +0000\nx-amz-acl:public-read\nx-amz-meta-checksumalgorithm:crc32\nx-amz-meta-filechecksum:0x02661779\nx-amz-meta-reviewedby:joe@johnsmith.net,jane@johnsmith.net\n/static.johnsmith.net/db-backup.dat.gz"
44
44
 
45
- subject.signature(request).should == "AWS #{access_key_id}:C0FlOtU8Ylb9KDTpZqYkZPX91iI="
45
+ subject.signature(request).should == "AWS #{access_key_id}:ilyl83RwaSoYIEdixDQcA4OnAnc="
46
46
  end
47
47
 
48
48
  end
metadata CHANGED
@@ -1,107 +1,103 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: awsraw
3
- version: !ruby/object:Gem::Version
4
- hash: 27
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 2
10
- version: 0.0.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Pete Yandell
9
+ - David Goodlad
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2012-02-12 00:00:00 +11:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-11-22 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
26
  none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
34
- requirement: *id001
35
- - !ruby/object:Gem::Dependency
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
36
32
  name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
37
39
  type: :development
38
40
  prerelease: false
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
40
42
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
48
- requirement: *id002
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
49
47
  description: A client for Amazon Web Services in the style of FlickRaw
50
- email:
48
+ email:
51
49
  - pete@notahat.com
50
+ - david@goodlad.net
52
51
  executables: []
53
-
54
52
  extensions: []
55
-
56
53
  extra_rdoc_files: []
57
-
58
- files:
54
+ files:
59
55
  - .gitignore
60
56
  - Gemfile
57
+ - README.md
61
58
  - Rakefile
62
59
  - awsraw.gemspec
63
60
  - lib/awsraw.rb
64
61
  - lib/awsraw/s3/client.rb
62
+ - lib/awsraw/s3/query_string_signer.rb
65
63
  - lib/awsraw/s3/request.rb
66
64
  - lib/awsraw/s3/response.rb
67
65
  - lib/awsraw/s3/signer.rb
68
66
  - lib/awsraw/version.rb
69
67
  - spec/s3/client_spec.rb
68
+ - spec/s3/query_string_signer_spec.rb
70
69
  - spec/s3/signer_spec.rb
71
- has_rdoc: true
72
70
  homepage: http://github.com/envato/awsraw
73
71
  licenses: []
74
-
75
72
  post_install_message:
76
73
  rdoc_options: []
77
-
78
- require_paths:
74
+ require_paths:
79
75
  - lib
80
- required_ruby_version: !ruby/object:Gem::Requirement
76
+ required_ruby_version: !ruby/object:Gem::Requirement
81
77
  none: false
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- hash: 3
86
- segments:
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ segments:
87
83
  - 0
88
- version: "0"
89
- required_rubygems_version: !ruby/object:Gem::Requirement
84
+ hash: 2614771455796597765
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
86
  none: false
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- hash: 3
95
- segments:
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
96
92
  - 0
97
- version: "0"
93
+ hash: 2614771455796597765
98
94
  requirements: []
99
-
100
95
  rubyforge_project: awsraw
101
- rubygems_version: 1.6.2
96
+ rubygems_version: 1.8.23
102
97
  signing_key:
103
98
  specification_version: 3
104
99
  summary: Minimal AWS client
105
- test_files:
100
+ test_files:
106
101
  - spec/s3/client_spec.rb
102
+ - spec/s3/query_string_signer_spec.rb
107
103
  - spec/s3/signer_spec.rb