cloudfront-signer 1.0.0 → 2.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.
- data/.rspec +3 -0
- data/cloudfront-signer.gemspec +1 -1
- data/lib/cloudfront-signer.rb +216 -176
- data/lib/cloudfront-signer/version.rb +1 -1
- data/spec/signer_spec.rb +61 -55
- data/spec/spec_helper.rb +6 -6
- metadata +12 -8
data/.rspec
ADDED
data/cloudfront-signer.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["tony@58bits.com"]
|
10
10
|
s.homepage = "http://github.com/58bits/cloudfront-signer"
|
11
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
|
12
|
+
s.description = %q{A fork of Dylan Vaughn's 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
13
|
|
14
14
|
s.rubyforge_project = "cloudfront-signer"
|
15
15
|
|
data/lib/cloudfront-signer.rb
CHANGED
@@ -6,183 +6,223 @@ require 'base64'
|
|
6
6
|
require "cloudfront-signer/version"
|
7
7
|
|
8
8
|
module AWS
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
9
|
+
module CF
|
10
|
+
class Signer
|
11
|
+
# Public non-inheritable class accessors
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Public: Provides a configuration option to set the key_pair_id if it has not
|
15
|
+
# been inferred from the key_path
|
16
|
+
#
|
17
|
+
# Examples
|
18
|
+
#
|
19
|
+
# AWS::CF::Signer.configure do |config|
|
20
|
+
# config.key_pair_id = "XXYYZZ"
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Returns a String value indicating the current setting
|
24
|
+
attr_accessor :key_pair_id
|
25
|
+
|
26
|
+
# Public: Provides a configuration option that sets the key_path
|
27
|
+
#
|
28
|
+
# Examples
|
29
|
+
#
|
30
|
+
# AWS::CF::Signer.configure do |config|
|
31
|
+
# config.key_path = "/path/to/your/keyfile.pem"
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Returns nothing.
|
35
|
+
def key_path=(path)
|
36
|
+
raise ArgumentError.new("The signing key could not be found at #{path}") unless File.exists?(path)
|
37
|
+
@key_path = path
|
38
|
+
@key = OpenSSL::PKey::RSA.new(File.readlines(path).join(""))
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Provides an accessor to the key_path
|
42
|
+
#
|
43
|
+
# Returns a String value indicating the current setting
|
44
|
+
def key_path
|
45
|
+
@key_path
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
# Public: Provides a configuration option that sets the default_expires in milliseconds
|
50
|
+
#
|
51
|
+
# Examples
|
52
|
+
#
|
53
|
+
# AWS::CF::Signer.configure do |config|
|
54
|
+
# config.default_expires = 3600
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# Returns nothing.
|
58
|
+
def default_expires=(value)
|
59
|
+
@default_expires = value
|
60
|
+
end
|
61
|
+
|
62
|
+
# Public: Provides an accessor to the default_expires value
|
63
|
+
#
|
64
|
+
# Returns an Integer value indicating the current setting
|
65
|
+
def default_expires
|
66
|
+
@default_expires ||= 3600
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# Private: Provides an accessor to the RSA key value
|
73
|
+
#
|
74
|
+
# Returns an RSA key pair.
|
75
|
+
def private_key
|
76
|
+
@key
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Public: Provides a simple way to configure the signing class.
|
81
|
+
#
|
82
|
+
# Yields self.
|
83
|
+
#
|
84
|
+
# Examples
|
85
|
+
#
|
86
|
+
# AWS::CF::Signer.configure do |config|
|
87
|
+
# config.key_path = "/path/to/yourkeyfile.pem"
|
88
|
+
# config.key_pair_id = "XXYYZZ"
|
89
|
+
# config.default_expires = 3600
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# Returns nothing.
|
93
|
+
def self.configure
|
94
|
+
|
95
|
+
yield self if block_given?
|
96
|
+
|
97
|
+
raise ArgumentError.new("You must supply the path to a PEM format RSA key pair.") unless self.key_path
|
98
|
+
|
99
|
+
unless @key_pair_id
|
100
|
+
@key_pair_id = extract_key_pair_id(self.key_path)
|
101
|
+
raise ArgumentError.new("The Cloudfront signing key id could not be inferred from #{self.key_path}. Please supply the key pair id as a configuration argument.") unless @key_pair_id
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
# Public: Provides a configuration check method which tests to see
|
107
|
+
# that the key_path, key_pair_id and private key values have all been set.
|
108
|
+
#
|
109
|
+
# Returns a Boolean value indicating that settings are present.
|
110
|
+
def self.is_configured?
|
111
|
+
(self.key_path.nil? || self.key_pair_id.nil? || private_key.nil?) ? false : true
|
112
|
+
end
|
113
|
+
|
114
|
+
# Public: Sign a url - encoding any spaces in the url before signing. CloudFront
|
115
|
+
# stipulates that signed URLs must not contain spaces (as opposed to stream
|
116
|
+
# paths/filenames which CAN contain spaces).
|
117
|
+
#
|
118
|
+
# Returns a String
|
119
|
+
def self.sign_url(subject, policy_options = {})
|
120
|
+
self.sign(subject, {:remove_spaces => true}, policy_options)
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
# Public: Sign a url (as above) and HTML encode the result.
|
126
|
+
#
|
127
|
+
# Returns a String
|
128
|
+
def self.sign_url_safe(subject, policy_options = {})
|
129
|
+
self.sign(subject, {:remove_spaces => true, :html_escape => true}, policy_options)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Public: Sign a stream path part or filename (spaces are allowed in stream paths
|
133
|
+
# and so are not removed).
|
134
|
+
#
|
135
|
+
# Returns a String
|
136
|
+
def self.sign_path(subject, policy_options ={})
|
137
|
+
self.sign(subject, {:remove_spaces => false}, policy_options)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Public: Sign a stream path or filename and HTML encode the result.
|
141
|
+
#
|
142
|
+
# Returns a String
|
143
|
+
def self.sign_path_safe(subject, policy_options ={})
|
144
|
+
self.sign(subject, {:remove_spaces => false, :html_escape => true}, policy_options)
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# Public: Sign a subject url or stream resource name with optional configuration and
|
149
|
+
# policy options
|
150
|
+
#
|
151
|
+
# Returns a String
|
152
|
+
def self.sign(subject, configuration_options = {}, policy_options = {})
|
153
|
+
|
154
|
+
raise "Configure using AWS::CF.Signer.configure! before signing." unless self.is_configured?
|
155
|
+
|
156
|
+
# If the url or stream path already has a query string parameter - append to that.
|
157
|
+
separator = subject =~ /\?/ ? '&' : '?'
|
158
|
+
|
159
|
+
if configuration_options[:remove_spaces]
|
160
|
+
subject.gsub!(/\s/, "%20")
|
161
|
+
end
|
162
|
+
|
163
|
+
if policy_options[:policy_file]
|
164
|
+
policy = IO.read(policy_options[:policy_file])
|
165
|
+
result = "#{subject}#{separator}Policy=#{encode_policy(policy)}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
|
166
|
+
else
|
167
|
+
if policy_options.keys.size <= 1
|
168
|
+
# Canned Policy - shorter URL
|
169
|
+
expires_at = epoch_time(policy_options[:expires] || Time.now + self.default_expires)
|
170
|
+
policy = %({"Statement":[{"Resource":"#{subject}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires_at}}}}]})
|
171
|
+
result = "#{subject}#{separator}Expires=#{expires_at}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
|
172
|
+
else
|
173
|
+
# Custom Policy
|
174
|
+
resource = policy_options[:resource] || subject
|
175
|
+
policy = generate_custom_policy(resource, policy_options)
|
176
|
+
result = "#{subject}#{separator}Policy=#{encode_policy(policy)}&Signature=#{create_signature(policy)}&Key-Pair-Id=#{@key_pair_id}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
if configuration_options[:html_escape]
|
181
|
+
return html_encode(result)
|
182
|
+
else
|
183
|
+
return result
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
# Private helper methods
|
189
|
+
private
|
190
|
+
|
191
|
+
|
192
|
+
def self.generate_custom_policy(resource, options)
|
193
|
+
conditions = ["\"DateLessThan\":{\"AWS:EpochTime\":#{epoch_time(options[:expires])}}"]
|
194
|
+
conditions << "\"DateGreaterThan\":{\"AWS:EpochTime\":#{epoch_time(options[:starting])}}" if options[:starting]
|
195
|
+
conditions << "\"IpAddress\":{\"AWS:SourceIp\":\"#{options[:ip_range]}\"" if options[:ip_range]
|
150
196
|
%({"Statement":[{"Resource":"#{resource}","Condition":{#{conditions.join(',')}}}}]})
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.epoch_time(timelike)
|
200
|
+
case timelike
|
201
|
+
when String then Time.parse(timelike).to_i
|
202
|
+
when Time then timelike.to_i
|
203
|
+
else raise ArgumentError.new("Invalid argument - String or Time required - #{timelike.class} passed.")
|
186
204
|
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.encode_policy(policy)
|
208
|
+
url_encode(Base64.encode64(policy))
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.create_signature(policy)
|
212
|
+
url_encode(Base64.encode64(private_key.sign(OpenSSL::Digest::SHA1.new, (policy))))
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.extract_key_pair_id(key_path)
|
216
|
+
File.basename(key_path) =~ /^pk-(.*).pem$/ ? $1 : nil
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.url_encode(s)
|
220
|
+
s.gsub('+','-').gsub('=','_').gsub('/','~').gsub(/\n/,'').gsub(' ','')
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.html_encode(s)
|
224
|
+
return s.gsub('?', '%3F').gsub('=', '%3D').gsub('&', '%26')
|
225
|
+
end
|
187
226
|
end
|
227
|
+
end
|
188
228
|
end
|
data/spec/signer_spec.rb
CHANGED
@@ -2,73 +2,79 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe AWS::CF::Signer do
|
4
4
|
|
5
|
-
|
5
|
+
let(:key_path) { File.expand_path(File.dirname(__FILE__) + '/keys/pk-APKAIKUROOUNR2BAFUUU.pem') }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
before(:each) do
|
8
|
+
AWS::CF::Signer.configure do |config|
|
9
|
+
config.key_path = key_path
|
10
|
+
#config.key_pair_id = "XXYYZZ"
|
11
|
+
#config.default_expires = 3600
|
9
12
|
end
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
describe "before default use" do
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
it "should be configured" do
|
18
|
+
AWS::CF::Signer.is_configured?.should eql(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should expire urls and paths in one hour by default" do
|
22
|
+
AWS::CF::Signer.default_expires.should eql(3600)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should optionally be configured to expire urls and paths in ten minutes" do
|
26
|
+
AWS::CF::Signer.default_expires = 600
|
27
|
+
AWS::CF::Signer.default_expires.should eql(600)
|
28
|
+
AWS::CF::Signer.default_expires = nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when signing a url" do
|
16
33
|
|
17
|
-
|
18
|
-
|
19
|
-
|
34
|
+
it "should remove spaces from the url" do
|
35
|
+
url = "http://somedomain.com/sign me"
|
36
|
+
result = AWS::CF::Signer.sign_url(url)
|
37
|
+
(result =~ /\s/).should be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not html encode the signed url by default" do
|
41
|
+
url = "http://somedomain.com/someresource?opt1=one&opt2=two"
|
42
|
+
result = AWS::CF::Signer.sign_url(url)
|
43
|
+
(result =~ /\?/).should_not be_nil
|
44
|
+
(result =~ /=/).should_not be_nil
|
45
|
+
(result =~ /&/).should_not be_nil
|
46
|
+
end
|
20
47
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
48
|
+
it "should optionally html encode the signed url" do
|
49
|
+
url = "http://somedomain.com/someresource?opt1=one&opt2=two"
|
50
|
+
result = AWS::CF::Signer.sign_url_safe(url)
|
51
|
+
(result =~ /\?/).should be_nil
|
52
|
+
(result =~ /=/).should be_nil
|
53
|
+
(result =~ /&/).should be_nil
|
25
54
|
end
|
26
55
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
56
|
+
it "should expire in one hour by default" do
|
57
|
+
url = "http://somedomain.com/sign me"
|
58
|
+
result = AWS::CF::Signer.sign_url(url)
|
59
|
+
get_query_value(result, 'Expires').to_i.should eql((Time.now + 3600).to_i)
|
60
|
+
end
|
62
61
|
|
62
|
+
it "should optionally expire in ten minutes" do
|
63
|
+
url = "http://somedomain.com/sign me"
|
64
|
+
result = AWS::CF::Signer.sign_url(url, :expires => Time.now + 600)
|
65
|
+
get_query_value(result, 'Expires').to_i.should eql((Time.now + 600 ).to_i)
|
63
66
|
end
|
64
67
|
|
68
|
+
end
|
69
|
+
|
65
70
|
|
66
|
-
|
71
|
+
describe "when signing a path" do
|
67
72
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
+
it "should not remove spaces from the path" do
|
74
|
+
path = "/someprefix/sign me"
|
75
|
+
result = AWS::CF::Signer.sign_path(path)
|
76
|
+
(result =~ /\s/).should_not be_nil
|
73
77
|
end
|
78
|
+
|
79
|
+
end
|
74
80
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,13 +5,13 @@ require 'rspec'
|
|
5
5
|
require 'cloudfront-signer'
|
6
6
|
|
7
7
|
def get_query_value(url, key)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
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]
|
14
13
|
end
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudfront-signer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
default_executable:
|
12
|
+
date: 2012-05-24 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rspec
|
17
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,8 +21,13 @@ dependencies:
|
|
22
21
|
version: '0'
|
23
22
|
type: :development
|
24
23
|
prerelease: false
|
25
|
-
version_requirements:
|
26
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: A fork of Dylan Vaughn's signing gem - https://github.com/stlondemand/aws_cf_signer.
|
27
31
|
The gem has been rewritten to use class methods and includes specific signing methods
|
28
32
|
for both url and streaming paths, including html 'safe' escpaed versions of each.
|
29
33
|
email:
|
@@ -33,6 +37,7 @@ extensions: []
|
|
33
37
|
extra_rdoc_files: []
|
34
38
|
files:
|
35
39
|
- .gitignore
|
40
|
+
- .rspec
|
36
41
|
- Gemfile
|
37
42
|
- LICENSE
|
38
43
|
- README.markdown
|
@@ -44,7 +49,6 @@ files:
|
|
44
49
|
- spec/keys/rsa-APKAIKUROOUNR2BAFUUU.pem
|
45
50
|
- spec/signer_spec.rb
|
46
51
|
- spec/spec_helper.rb
|
47
|
-
has_rdoc: true
|
48
52
|
homepage: http://github.com/58bits/cloudfront-signer
|
49
53
|
licenses: []
|
50
54
|
post_install_message:
|
@@ -65,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
69
|
version: '0'
|
66
70
|
requirements: []
|
67
71
|
rubyforge_project: cloudfront-signer
|
68
|
-
rubygems_version: 1.
|
72
|
+
rubygems_version: 1.8.23
|
69
73
|
signing_key:
|
70
74
|
specification_version: 3
|
71
75
|
summary: A gem to sign url and stream paths for Amazon CloudFront private content.
|