azure-signature 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3e4bf37dea120788f3e4b8b1f1f4ba2cac0da67
4
- data.tar.gz: 804102d0275a2c4a7bb01dfda9636a85e32529dc
3
+ metadata.gz: 88506245b215c239f08a1c85f3970c1ae0b0aa61
4
+ data.tar.gz: 9ebc3da7b6ccd44d3004e44dd3e4d49fa8a71a00
5
5
  SHA512:
6
- metadata.gz: 3593818f612766c12b61de678db9f4766866855e17f936dd88e2fa3367cf7ba33b49557dc4f6b9925e7607bb4ae04e565d3053f4828a6f7e2814b0e79d16688d
7
- data.tar.gz: ad442a9a682c1d1a921a37bd5c1baf073b1555c00bcd6df310d0d44236e4b351e703b3d057c7a19361fe21d7e59398ba3f792fa374f9baf8363d2d7f5fa5dc67
6
+ metadata.gz: 5fdb546f7a4af2496b7e902aedcdd4ee5b0d6bb069f9eef1b99bd75731158de052fb90374d7d3dd10e5d70a9a66e19b003a9701213b5bec48cf80522e1ec48da
7
+ data.tar.gz: b76a9ba3cfa945e8932dba42ec3d00854972fe867b9bc5990d9c58be461f631ce2384db1d0b333108b1f4ce2055d2f0b6e4f7f66a0cee0516bdb33e2baa64669
data/CHANGES CHANGED
@@ -1,2 +1,7 @@
1
+ = 0.2.0 - 13-Oct-2015
2
+ * Added support for other types of signatures (blobs, queues, files).
3
+ * The :auth_string argument no longer returns the word "Authorization".
4
+ * Added an azure-signature file for convenience.
5
+
1
6
  = 0.1.0 - 25-Sep-2015
2
7
  * Initial release
data/README CHANGED
@@ -21,10 +21,6 @@
21
21
  # Or pass some options
22
22
  p sig.signature(:table, :auth_string => true, :date => some_date, :verb => 'PUT')
23
23
 
24
- = Caveats
25
- For the first release only table signatures are supported (because that's
26
- what I happened to need). I'll add blob, file and queue in the future.
27
-
28
24
  = Acknowledgements
29
25
  I borrowed the code to canonicalize resources and headers from the
30
26
  azure-sdk-for-ruby project.
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'azure-signature'
5
- gem.version = '0.1.0'
5
+ gem.version = '0.2.0'
6
6
  gem.author = 'Daniel J. Berger'
7
7
  gem.license = 'Apache 2.0'
8
8
  gem.email = 'djberg96@gmail.com'
@@ -0,0 +1 @@
1
+ require_relative 'azure/signature'
@@ -9,7 +9,7 @@ module Azure
9
9
  # The Signature class encapsulates an canonicalized resource string.
10
10
  class Signature
11
11
  # The version of the azure-signature library.
12
- VERSION = '0.1.0'
12
+ VERSION = '0.2.0'
13
13
 
14
14
  # The resource (URL) passed to the constructor.
15
15
  attr_reader :resource
@@ -29,6 +29,8 @@ module Azure
29
29
  alias url resource
30
30
  alias canonical_url canonical_resource
31
31
 
32
+ attr_reader :canonical_headers
33
+
32
34
  # Creates and returns an Azure::Signature object taking a +resource+ (URL)
33
35
  # as an argument and a storage account key. The +resource+ will typically
34
36
  # be an Azure storage account endpoint.
@@ -60,42 +62,162 @@ module Azure
60
62
  verb = options[:verb] || 'GET'
61
63
  date = options[:date] || Time.now.httpdate
62
64
  auth_string = options[:auth_string] || false
63
- content_md5 = options[:content_md5]
64
- content_type = options[:content_type]
65
+ content_md5 = options[:content_md5] || options['Content-MD5']
66
+ content_type = options[:content_type] || options['Content-Type']
65
67
 
66
68
  unless ['SharedKey', 'SharedKeyLight'].include?(auth_type)
67
69
  raise ArgumentError, "auth type must be SharedKey or SharedKeyLight"
68
70
  end
69
71
 
70
72
  if auth_type == 'SharedKey'
71
- body = [verb, content_md5, content_type, date, canonical_resource].join("\n")
73
+ body = [verb, content_md5, content_type, date, canonical_resource].join("\n").encode('UTF-8')
74
+ else
75
+ body = [date, canonical_resource].join("\n").encode('UTF-8')
76
+ end
77
+
78
+ if auth_string
79
+ "#{auth_type} #{account_name}:" + sign(body)
72
80
  else
73
- body = [date, canonical_resource].join("\n")
81
+ sign(body)
82
+ end
83
+ end
84
+
85
+ # Generate a signature for use with the blob service. Use the +headers+
86
+ # hash to pass optional information. The following additional keys are
87
+ # supported:
88
+ #
89
+ # - :auth_type. Either 'SharedKey' (the default) or 'SharedKeyLight'.
90
+ # - :verb. The http verb used for SharedKey auth. The default is 'GET'.
91
+ # - :x_ms_date. The x-ms-date used. The default is Time.now.httpdate.
92
+ # - :x_ms_version. The x-ms-version used. The default is '2015-02-21'.
93
+ # - :auth_string. If true, prepends the auth_type + account name to the
94
+ # result and returns a string. The default is false.
95
+ #
96
+ # The other headers of potential significance are below. Note that you
97
+ # are not required to set any of them.
98
+ #
99
+ # - 'Content-Encoding'
100
+ # - 'Content-Language'
101
+ # - 'Content-Length'
102
+ # - 'Content-MD5'
103
+ # - 'Content-Type'
104
+ # - 'Date'
105
+ # - 'If-Modified-Since'
106
+ # - 'If-Match'
107
+ # - 'If-None-Match'
108
+ # - 'If-Unmodified-Since'
109
+ # - 'Range'
110
+ #
111
+ # The result is a digest string that you can use as an authorization header
112
+ # for future http requests to (presumably) Azure storage endpoints.
113
+ #
114
+ # Example:
115
+ #
116
+ # require 'azure-signature'
117
+ # require 'rest-client'
118
+ #
119
+ # url = "https://yourstuff.blob.core.windows.net/system?restype=container&comp=list&include=snapshots"
120
+ # key = "xyzabcwhatever"
121
+ #
122
+ # sig = Signature.new(url, key)
123
+ # date = Time.now.httpdate
124
+ # vers = '2015-02-21'
125
+ #
126
+ # headers = {
127
+ # 'x-ms-date' => date,
128
+ # 'x-ms-version' => vers,
129
+ # 'Accept' => 'application/xml',
130
+ # :auth_string => true,
131
+ # }
132
+ #
133
+ # sig = sig.blob_signature(headers)
134
+ # headers['Authorization'] = sig
135
+ #
136
+ # req = RestClient::Request.new(
137
+ # :method => 'get',
138
+ # :url => url,
139
+ # :headers => headers
140
+ # )
141
+ #
142
+ # response = req.execute
143
+ # p response.body
144
+ #
145
+ def blob_signature(headers = {})
146
+ auth_string = headers.delete(:auth_string) || false
147
+ auth_type = headers.delete(:auth_type) || 'SharedKey'
148
+ verb = headers.delete(:verb) || 'GET'
149
+
150
+ unless ['SharedKey', 'SharedKeyLight'].include?(auth_type)
151
+ raise ArgumentError, "auth type must be SharedKey or SharedKeyLight"
74
152
  end
75
153
 
154
+ headers['x-ms-date'] ||= headers.delete(:x_ms_date) || Time.now.httpdate
155
+ headers['x-ms-version'] ||= headers.delete(:x_ms_version) || '2015-02-21'
156
+
157
+ if auth_type == 'SharedKeyLight'
158
+ headers['Date'] ||= headers['x-ms-date'] || headers[:date] || Time.now.httpdate
159
+ end
160
+
161
+ body = generate_string(verb, headers, auth_type).encode('UTF-8')
162
+
76
163
  if auth_string
77
- "Authorization: #{auth_type} #{account_name}:" + sign(body)
164
+ "SharedKey #{account_name}:" + sign(body)
78
165
  else
79
166
  sign(body)
80
167
  end
81
168
  end
82
169
 
170
+ alias file_signature blob_signature
171
+ alias queue_signature blob_signature
172
+
83
173
  # Generic wrapper method for getting a signature, where +type+ can be
84
174
  # :table, :blob, :queue, or :file.
85
175
  #
86
- # At the moment only :table is supported.
87
- #--
88
- # TODO: Add support for other types.
89
- #
90
176
  def signature(type, args = {})
91
177
  case type.to_s.downcase
92
178
  when 'table'
93
179
  table_signature(args)
180
+ when 'blob', 'file', 'queue'
181
+ blob_signature(args)
182
+ else
183
+ raise ArgumentError, "invalid signature type '#{type}'"
94
184
  end
95
185
  end
96
186
 
97
187
  private
98
188
 
189
+ def generate_string(verb, headers, auth_type)
190
+ canonical_headers = canonicalize_headers(headers)
191
+
192
+ if auth_type == 'SharedKeyLight'
193
+ [
194
+ verb.to_s.upcase,
195
+ headers['Content-MD5'],
196
+ headers['Content-Type'],
197
+ headers['Date'],
198
+ canonical_headers,
199
+ canonical_resource
200
+ ].join("\n")
201
+ else
202
+ [
203
+ verb.to_s.upcase,
204
+ headers['Content-Encoding'],
205
+ headers['Content-Language'],
206
+ headers['Content-Length'],
207
+ headers['Content-MD5'],
208
+ headers['Content-Type'],
209
+ headers['Date'],
210
+ headers['If-Modified-Since'],
211
+ headers['If-Match'],
212
+ headers['If-None-Match'],
213
+ headers['If-Unmodified-Since'],
214
+ headers['Range'],
215
+ canonical_headers,
216
+ canonical_resource,
217
+ ].join("\n")
218
+ end
219
+ end
220
+
99
221
  # Generate a canonical URL from an endpoint.
100
222
  #--
101
223
  # Borrowed from azure-sdk-for-ruby. I had my own, but this was nicer.
@@ -112,8 +234,8 @@ module Azure
112
234
  #--
113
235
  # Borrowed from azure-sdk-for-ruby.
114
236
  #
115
- def canonicalized_headers(headers)
116
- headers = headers.map { |k,v| [k.to_s.downcase, v] }
237
+ def canonicalize_headers(headers)
238
+ headers = headers.map { |k,v| [k.to_s.gsub('_', '-').downcase, v] }
117
239
  headers.select! { |k,v| k =~ /^x-ms-/ }
118
240
  headers.sort_by! { |k,v| k }
119
241
  headers.map! { |k,v| '%s:%s' % [k, v] }
@@ -9,7 +9,7 @@ class TC_Azure_Signature < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  test "version constant is set to expected value" do
12
- assert_equal("0.1.0", Azure::Signature::VERSION)
12
+ assert_equal("0.2.0", Azure::Signature::VERSION)
13
13
  end
14
14
 
15
15
  test "key method basic functionality" do
@@ -82,6 +82,19 @@ class TC_Azure_Signature < Test::Unit::TestCase
82
82
  assert_raise(ArgumentError){ Azure::Signature.new('http://foo/bar') }
83
83
  end
84
84
 
85
+ test "table_signature basic functionality" do
86
+ assert_respond_to(@sig, :table_signature)
87
+ end
88
+
89
+ test "blob_signature basic functionality" do
90
+ assert_respond_to(@sig, :blob_signature)
91
+ end
92
+
93
+ test "file_signature and queue_signature are aliases for blob_signature" do
94
+ assert_alias_method(@sig, :blob_signature, :file_signature)
95
+ assert_alias_method(@sig, :blob_signature, :queue_signature)
96
+ end
97
+
85
98
  def teardown
86
99
  @key = nil
87
100
  @url = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azure-signature
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-25 00:00:00.000000000 Z
11
+ date: 2015-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -41,6 +41,7 @@ files:
41
41
  - README
42
42
  - Rakefile
43
43
  - azure-signature.gemspec
44
+ - lib/azure-signature.rb
44
45
  - lib/azure/signature.rb
45
46
  - test/test_signature.rb
46
47
  homepage: http://github.com/djberg96/azure-signature
@@ -63,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
64
  version: '0'
64
65
  requirements: []
65
66
  rubyforge_project:
66
- rubygems_version: 2.4.5
67
+ rubygems_version: 2.4.5.1
67
68
  signing_key:
68
69
  specification_version: 4
69
70
  summary: Generate authentication signatures for Azure