cloudfront-signer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aws-cf-signer.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 Anthony Bouch
2
+ Portions Copyright (c) 2011 Dylan Vaughn
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,103 @@
1
+ cloudfront-signer
2
+ =================
3
+
4
+ A fork of Dylan Vaughn's [excellent signing gem](https://github.com/stlondemand/aws_cf_signer).
5
+
6
+ See Amazon docs for [Using a Signed URL to Serve Private Content](http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?PrivateContent.html)
7
+
8
+ This version uses all class methods and a configure method to initialize options.
9
+
10
+ Seperate helper methods exist for safe signing of urls and stream paths, each of which has slightly different requirements. For example, urls must not contain any spaces, whereas a stream path can. Also we might not want to html escape a url or path if it is being supplied to a JavaScript block or Flash object.
11
+
12
+ Installation
13
+ ------------
14
+
15
+ The original gem was published as `aws_cf_signer`. Use `gem install aws_cf_signer` to install that version.
16
+
17
+ This gem has been publised as `cloudfront-signer`. Use `gem install cloudfront-signer` to install this gem.
18
+
19
+ Alternatively, place a copy of cloudfront-signer.rb (and the cloundfront-signer sub directory) in your lib directory.
20
+
21
+ In either case the signing class must be configured - supplying the path to a signing key.
22
+
23
+ In a Rails app this can be done by creating an initializer script in the /config/initializers directory.
24
+
25
+ e.g.
26
+
27
+ require 'cloudfront-signer'
28
+
29
+ AWS::CF::Signer.configure! "#{Rails.root}/keys/pk-APKAIKURNAUNR2BDSFDMA.pem"
30
+
31
+
32
+ Usage
33
+ -----
34
+
35
+ Call the class `sign_url` or `sign_path` method with optional policy settings.
36
+
37
+ AWS::CF::Signer.sign_url 'http://mydomain/path/to/my/content'
38
+
39
+ or
40
+
41
+ AWS::CF::Signer.sign_url 'http://mydomain/path/to/my/content', :expires => Time.now + 600
42
+
43
+ Streaming paths can be signed with the `sign_path` method.
44
+
45
+ AWS::CF::Signer.sign_path 'path/to/my/content'
46
+
47
+ or
48
+
49
+ AWS::CF::Signer.sign_path 'path/to/my/content', :expires => Time.now + 600
50
+
51
+
52
+ Both `sign_url` and `sign_path` have _safe_ versions that HTML encode the result allowing signed paths or urls to be placed in HTML markup. The 'non'-safe versions can be used for placing signed urls or paths in JavaScript blocks or Flash params.
53
+
54
+
55
+ ### Custom Policies
56
+
57
+ See Example Custom Policy 1 at above AWS doc link
58
+
59
+ url = AWS::CF::Signer.sign_url('http://d604721fxaaqy9.cloudfront.net/training/orientation.avi',
60
+ :expires => 'Sat, 14 Nov 2009 22:20:00 GMT',
61
+ :resource => 'http://d604721fxaaqy9.cloudfront.net/training/*',
62
+ :ip_range => '145.168.143.0/24'
63
+ )
64
+
65
+ See Example Custom Policy 2 at above AWS doc link
66
+
67
+ url = AWS::CF::Signer.sign_url('http://d84l721fxaaqy9.cloudfront.net/downloads/pictures.tgz',
68
+ :starting => 'Thu, 30 Apr 2009 06:43:10 GMT',
69
+ :expires => 'Fri, 16 Oct 2009 06:31:56 GMT',
70
+ :resource => 'http://*',
71
+ :ip_range => '216.98.35.1/32'
72
+ )
73
+
74
+ You can also pass in a path to a policy file. This will supersede any other policy options
75
+
76
+ url = AWS::CF::Signer.sign_url('http://d84l721fxaaqy9.cloudfront.net/downloads/pictures.tgz', :policy_file => '/path/to/policy/file.txt')
77
+
78
+
79
+ Note on Patches/Pull Requests (verbatum from Dylan's original repository)
80
+ -------------------------------------------------------------------------
81
+
82
+ * Fork the project.
83
+ * Make your feature addition or bug fix.
84
+ * Add tests for it. This is important so I don't break it in a
85
+ future version unintentionally.
86
+ * Commit, do not mess with rakefile, version, or history.
87
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
88
+ * Send me a pull request. Bonus points for topic branches.
89
+
90
+ Attributions
91
+ ------------
92
+
93
+ Parts of signing code taken from a question on Stack Overflow asked by Ben Wiseley, and answered by Blaz Lipuscek and Manual M:
94
+
95
+ * [http://stackoverflow.com/questions/2632457/create-signed-urls-for-cloudfront-with-ruby](http://stackoverflow.com/questions/2632457/create-signed-urls-for-cloudfront-with-ruby)
96
+ * [http://stackoverflow.com/users/315829/ben-wiseley](http://stackoverflow.com/users/315829/ben-wiseley)
97
+ * [http://stackoverflow.com/users/267804/blaz-lipuscek](http://stackoverflow.com/users/267804/blaz-lipuscek)
98
+ * [http://stackoverflow.com/users/327914/manuel-m](http://stackoverflow.com/users/327914/manuel-m)
99
+
100
+ License
101
+ -------
102
+
103
+ cloudfront-signer is distributed under the MIT License, portions copyright © 2011 Dylan Vaughn, STL, Anthony Bouch
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ t.rspec_opts = ["--colour", "--format", "nested"]
8
+ end
9
+
10
+ task :default => :spec
11
+
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cloudfront-signer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cloudfront-signer"
7
+ s.version = AWS::CF::VERSION
8
+ s.authors = ["Anthony Bouch"]
9
+ s.email = ["tony@58bits.com"]
10
+ s.homepage = "http://github.com/58bits/cloudfront-signer"
11
+ s.summary = %q{A gem to sign url and stream paths for Amazon CloudFront private content.}
12
+ s.description = %q{A fork of Dylan Vaughn's excellent signing gem - https://github.com/stlondemand/aws_cf_signer. The gem has been rewritten to use class methods and includes specific signing methods for both url and streaming paths, including html 'safe' escpaed versions of each.}
13
+
14
+ s.rubyforge_project = "cloudfront-signer"
15
+
16
+ s.add_development_dependency "rspec"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,188 @@
1
+ # A re-write of https://github.com/stlondemand/aws_cf_signer
2
+ #
3
+ require 'openssl'
4
+ require 'time'
5
+ require 'base64'
6
+ require "cloudfront-signer/version"
7
+
8
+ module AWS
9
+ module CF
10
+ class Signer
11
+ # Public non-inheritable class accessors
12
+ #----------------------------------------------------------------------------
13
+ class << self
14
+ attr_accessor :key_pair_id
15
+
16
+ def key_path
17
+ @key_path
18
+ end
19
+
20
+ def key_path=(path)
21
+ raise ArgumentError.new("The signing key could not be found at #{path}") unless File.exists?(path)
22
+ @key_path = path
23
+ @key = OpenSSL::PKey::RSA.new(File.readlines(path).join(""))
24
+ end
25
+
26
+ def default_expires
27
+ @default_expires ||= 3600
28
+ end
29
+
30
+ def default_expires=(value)
31
+ raise ArgumentError.new("The default expires value must be an integer") unless value.is_a?(Integer)
32
+ @default_expires = value
33
+ end
34
+
35
+ private
36
+
37
+ # Private key
38
+ #----------------------------------------------------------------------------
39
+ def private_key
40
+ @key
41
+ end
42
+ end
43
+
44
+ #----------------------------------------------------------------------------
45
+ def self.is_configured?
46
+ if self.key_path && self.key_pair_id && private_key
47
+ return true
48
+ else
49
+ return false
50
+ end
51
+ end
52
+
53
+
54
+ # Configure the signing class.
55
+ #----------------------------------------------------------------------------
56
+ def self.configure!(key_path, options = {})
57
+
58
+ raise ArgumentError.new("You must supply the path to a PEM format private RSA key.") if key_path.nil?
59
+ self.key_path = key_path
60
+
61
+ @key_pair_id = options[:key_pair_id] || extract_key_pair_id(key_path)
62
+ unless @key_pair_id
63
+ raise ArgumentError.new("The Cloudfront signing key id could not be inferred from #{key_path}. Please supply the key pair id as a configuration arguemet.")
64
+ end
65
+
66
+ @default_expires = options[:default_expires] ? options[:default_expires] : 3600
67
+ end
68
+
69
+
70
+ # Signing methods
71
+ #----------------------------------------------------------------------------
72
+
73
+ # Sign a url - encoding any spaces in the url before signing. CloudFront
74
+ # stipulates that signed URLs must not contain spaces (as opposed to stream
75
+ # paths/filenames which CAN contain spaces).
76
+ #----------------------------------------------------------------------------
77
+ def self.sign_url(subject, policy_options = {})
78
+ self.sign(subject, {:remove_spaces => true}, policy_options)
79
+ end
80
+
81
+ # Sign a url (as above) and HTML encode the result.
82
+ #----------------------------------------------------------------------------
83
+ def self.sign_url_safe(subject, policy_options = {})
84
+ self.sign(subject, {:remove_spaces => true, :html_escape => true}, policy_options)
85
+ end
86
+
87
+ # Sign a stream path part or filename (spaces are allowed in stream paths
88
+ # and so are not removed).
89
+ #----------------------------------------------------------------------------
90
+ def self.sign_path(subject, policy_options ={})
91
+ self.sign(subject, {:remove_spaces => false}, policy_options)
92
+ end
93
+
94
+ # Sign a stream path or filename and HTML encode the result.
95
+ #----------------------------------------------------------------------------
96
+ def self.sign_path_safe(subject, policy_options ={})
97
+ self.sign(subject, {:remove_spaces => false, :html_escape => true}, policy_options)
98
+ end
99
+
100
+
101
+ # Sign a subject url or stream resource name with optional configuration and
102
+ # policy options
103
+ #----------------------------------------------------------------------------
104
+ def self.sign(subject, configuration_options = {}, policy_options = {})
105
+
106
+ raise "Configure using AWS::CF.Signer.configure! before signing." unless self.is_configured?
107
+
108
+ # If the url or stream path already has a query string parameter - append to that.
109
+ separator = subject =~ /\?/ ? '&' : '?'
110
+
111
+ if configuration_options[:remove_spaces]
112
+ subject.gsub!(/\s/, "%20")
113
+ end
114
+
115
+ if policy_options[:policy_file]
116
+ policy = IO.read(policy_options[:policy_file])
117
+ result = "#{subject}#{separator}Policy=#{encode_policy(policy)}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
118
+ else
119
+ if policy_options.keys.size <= 1
120
+ # Canned Policy - shorter URL
121
+ expires_at = epoch_time(policy_options[:expires] || Time.now + self.default_expires)
122
+ policy = %({"Statement":[{"Resource":"#{subject}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires_at}}}}]})
123
+ result = "#{subject}#{separator}Expires=#{expires_at}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
124
+ else
125
+ # Custom Policy
126
+ resource = policy_options[:resource] || subject
127
+ policy = generate_custom_policy(resource, policy_options)
128
+ result = "#{subject}#{separator}Policy=#{encode_policy(policy)}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
129
+ end
130
+ end
131
+
132
+ if configuration_options[:html_escape]
133
+ return html_encode(result)
134
+ else
135
+ return result
136
+ end
137
+ end
138
+
139
+
140
+ # Private helper methods
141
+ #----------------------------------------------------------------------------
142
+ private
143
+
144
+
145
+ #----------------------------------------------------------------------------
146
+ def self.generate_custom_policy(resource, options)
147
+ conditions = ["\"DateLessThan\":{\"AWS:EpochTime\":#{epoch_time(options[:expires])}}"]
148
+ conditions << "\"DateGreaterThan\":{\"AWS:EpochTime\":#{epoch_time(options[:starting])}}" if options[:starting]
149
+ conditions << "\"IpAddress\":{\"AWS:SourceIp\":\"#{options[:ip_range]}\"" if options[:ip_range]
150
+ %({"Statement":[{"Resource":"#{resource}","Condition":{#{conditions.join(',')}}}}]})
151
+ end
152
+
153
+ #----------------------------------------------------------------------------
154
+ def self.epoch_time(timelike)
155
+ case timelike
156
+ when String then Time.parse(timelike).to_i
157
+ when Time then timelike.to_i
158
+ else raise ArgumentError.new("Invalid argument - String or Time required - #{timelike.class} passed.")
159
+ end
160
+ end
161
+
162
+ #----------------------------------------------------------------------------
163
+ def self.encode_policy(policy)
164
+ url_encode(Base64.encode64(policy))
165
+ end
166
+
167
+ #----------------------------------------------------------------------------
168
+ def self.create_signature(policy)
169
+ url_encode(Base64.encode64(private_key.sign(OpenSSL::Digest::SHA1.new, (policy))))
170
+ end
171
+
172
+ #----------------------------------------------------------------------------
173
+ def self.extract_key_pair_id(key_path)
174
+ File.basename(key_path) =~ /^pk-(.*).pem$/ ? $1 : nil
175
+ end
176
+
177
+ #----------------------------------------------------------------------------
178
+ def self.url_encode(s)
179
+ s.gsub('+','-').gsub('=','_').gsub('/','~').gsub(/\n/,'').gsub(' ','')
180
+ end
181
+
182
+ #----------------------------------------------------------------------------
183
+ def self.html_encode(s)
184
+ return s.gsub('?', '%3F').gsub('=', '%3D').gsub('&', '%26')
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,5 @@
1
+ module AWS
2
+ module CF
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXgIBAAKBgQCp280I7v8JBVJBN7Kdfl4eD+noyqzbLAsz9mIr07hZQ3PjVa5g
3
+ 3j5Q8oXioU2ycxzXephfPr83l/FTAtPSZQ94Jh6u/CdoEYXfEtFbJYQ2lHXrra36
4
+ yVcyyxQ6tAKgUHdWnZ/vbItUhLnhCSqwelTNpgRzf6AKdVOtQPaZ+bnkQQIDAQAB
5
+ AoGAXWSPTbQq4gjc+yLmwJW0pg7V67tUY4XJ+x4jSDm3CM1/sKVxpa1M0jEm0D8k
6
+ e1Ozrf6oPOZBOQ4AEEZjtTD/2Yi8U0bwG97fg9NlZddGNN2jj8pEOWY53/iVWcfb
7
+ VGXVDlhUA0uIZhKK3Sl2SW9t/8p7affjJmGKn2nGLieRKIkCQQDQmExXqRnVNtCz
8
+ qjTPt81MU4cIrzXr/tUC9s6An8OcgiTDjiIOnY3XB/F19lpMQIMEzrB7f04GrpkQ
9
+ 0w6p/3NXAkEA0HXjiSyZaEoXoR2e/dTZrKw8npnjjW0CpKeSf8PK8qpFPK0UJOk7
10
+ aU0rStQmoAmygcHiw3hJ7slyVS8f9zn+JwJBAMMVbHCfadWKSm19RZ7um0ZC6Asr
11
+ MhbgYX9AK6kHwf3hiViK2TcqCrmMaDqWh6TAwMgCNfOKAAMnz2d4vEIo8kkCQQCl
12
+ qnq4gkQsWG2s8jBvg1+2VW8bkCsCMvbdyfqoJP69mUnK7bXLm7tGdTiJkE5d8zb0
13
+ 3hQLyiXfaiK9xeS+gk0TAkEAtuFcd+taoBnjhVL6q0OhNuA1T1+qYr5fyzQWKKKC
14
+ +WMRi2/JCJCL/SX12q5hMq759VnzfnbgqwAq6MlPUZKEBQ==
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,6 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp280I7v8JBVJBN7Kdfl4eD+no
3
+ yqzbLAsz9mIr07hZQ3PjVa5g3j5Q8oXioU2ycxzXephfPr83l/FTAtPSZQ94Jh6u
4
+ /CdoEYXfEtFbJYQ2lHXrra36yVcyyxQ6tAKgUHdWnZ/vbItUhLnhCSqwelTNpgRz
5
+ f6AKdVOtQPaZ+bnkQQIDAQAB
6
+ -----END PUBLIC KEY-----
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe AWS::CF::Signer do
4
+
5
+ let(:key_path) { File.expand_path(File.dirname(__FILE__) + '/keys/pk-APKAIKUROOUNR2BAFUUU.pem') }
6
+
7
+ before(:each) do
8
+ AWS::CF::Signer.configure!(key_path)
9
+ end
10
+
11
+ describe "before default use" do
12
+
13
+ it "should be configured" do
14
+ AWS::CF::Signer.is_configured?.should eql(true)
15
+ end
16
+
17
+ it "should expire urls and paths in one hour by default" do
18
+ AWS::CF::Signer.default_expires.should eql(3600)
19
+ end
20
+
21
+ it "should optionally be configured to expire urls and paths in ten minutes" do
22
+ AWS::CF::Signer.configure!(key_path, :default_expires => 600)
23
+ AWS::CF::Signer.default_expires.should eql(600)
24
+ end
25
+ end
26
+
27
+ describe "when signing a url" do
28
+
29
+ it "should remove spaces from the url" do
30
+ url = "http://somedomain.com/sign me"
31
+ result = AWS::CF::Signer.sign_url(url)
32
+ (result =~ /\s/).should be_nil
33
+ end
34
+
35
+ it "should not html encode the signed url by default" do
36
+ url = "http://somedomain.com/someresource?opt1=one&opt2=two"
37
+ result = AWS::CF::Signer.sign_url(url)
38
+ (result =~ /\?/).should_not be_nil
39
+ (result =~ /=/).should_not be_nil
40
+ (result =~ /&/).should_not be_nil
41
+ end
42
+
43
+ it "should optionally html encode the signed url" do
44
+ url = "http://somedomain.com/someresource?opt1=one&opt2=two"
45
+ result = AWS::CF::Signer.sign_url_safe(url)
46
+ (result =~ /\?/).should be_nil
47
+ (result =~ /=/).should be_nil
48
+ (result =~ /&/).should be_nil
49
+ end
50
+
51
+ it "should expire in one hour by default" do
52
+ url = "http://somedomain.com/sign me"
53
+ result = AWS::CF::Signer.sign_url(url)
54
+ get_query_value(result, 'Expires').to_i.should eql((Time.now + 3600).to_i)
55
+ end
56
+
57
+ it "should optionally expire in ten minutes" do
58
+ url = "http://somedomain.com/sign me"
59
+ result = AWS::CF::Signer.sign_url(url, :expires => Time.now + 600)
60
+ get_query_value(result, 'Expires').to_i.should eql((Time.now + 600 ).to_i)
61
+ end
62
+
63
+ end
64
+
65
+
66
+ describe "when signing a path" do
67
+
68
+ it "should not remove spaces from the path" do
69
+ path = "/someprefix/sign me"
70
+ result = AWS::CF::Signer.sign_path(path)
71
+ (result =~ /\s/).should_not be_nil
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rspec'
5
+ require 'cloudfront-signer'
6
+
7
+ def get_query_value(url, key)
8
+ query_string = url.slice((url =~ /\?/) + 1..-1)
9
+ pairs = query_string.split('&')
10
+ pairs.each do |item|
11
+ if item.start_with?(key)
12
+ return item.split('=')[1]
13
+ end
14
+ end
15
+ end
16
+
17
+
18
+ RSpec.configure do |config|
19
+
20
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloudfront-signer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Anthony Bouch
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-08 00:00:00.000000000 +07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &2151692620 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *2151692620
26
+ description: A fork of Dylan Vaughn's excellent signing gem - https://github.com/stlondemand/aws_cf_signer.
27
+ The gem has been rewritten to use class methods and includes specific signing methods
28
+ for both url and streaming paths, including html 'safe' escpaed versions of each.
29
+ email:
30
+ - tony@58bits.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - .gitignore
36
+ - Gemfile
37
+ - LICENSE
38
+ - README.markdown
39
+ - Rakefile
40
+ - cloudfront-signer.gemspec
41
+ - lib/cloudfront-signer.rb
42
+ - lib/cloudfront-signer/version.rb
43
+ - spec/keys/pk-APKAIKUROOUNR2BAFUUU.pem
44
+ - spec/keys/rsa-APKAIKUROOUNR2BAFUUU.pem
45
+ - spec/signer_spec.rb
46
+ - spec/spec_helper.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/58bits/cloudfront-signer
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project: cloudfront-signer
68
+ rubygems_version: 1.6.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A gem to sign url and stream paths for Amazon CloudFront private content.
72
+ test_files:
73
+ - spec/keys/pk-APKAIKUROOUNR2BAFUUU.pem
74
+ - spec/keys/rsa-APKAIKUROOUNR2BAFUUU.pem
75
+ - spec/signer_spec.rb
76
+ - spec/spec_helper.rb