wp-hmac 0.2.2 → 0.2.3
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 +4 -4
- data/.rubocop.yml +9 -0
- data/README.md +2 -2
- data/Rakefile +1 -2
- data/lib/wp/hmac.rb +3 -2
- data/lib/wp/hmac/client.rb +17 -5
- data/lib/wp/hmac/key_cabinet.rb +10 -8
- data/lib/wp/hmac/server.rb +3 -0
- data/lib/wp/hmac/version.rb +1 -1
- data/spec/hmac_spec.rb +44 -19
- data/wp-hmac.gemspec +20 -18
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db868028407a6446871761f00d2344bdaea894f8
|
4
|
+
data.tar.gz: 6ac7ab349d36f90aa6ab398f72b1c53632a23ef4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91a8b8aa1a81fddaf79f577455a43671b0cdc4dbb0da28c55be29c550695917da42e441905724dd8abf08a20dbdd3b9d490f1d208bc747dcdf4b80308b828114
|
7
|
+
data.tar.gz: e2927f2c94c822d9220e41ebb71ae76d09ce7c23e6183880061ec9cadb6979f661cd55066ce0c063bc45fce4e1c1dde8677b20ecaa1c4cc94425acd471af1db0
|
data/.rubocop.yml
ADDED
data/README.md
CHANGED
@@ -64,13 +64,13 @@ use WP::HMAC::Server
|
|
64
64
|
Use like this ...
|
65
65
|
``` ruby
|
66
66
|
WP::HMAC::Client.get('https://www.example.com/api/staff')
|
67
|
-
WP::HMAC::Client.post('https://www.example.com/api/schedules, {'HEADER' => 'foo'},
|
67
|
+
WP::HMAC::Client.post('https://www.example.com/api/schedules, {'HEADER' => 'foo'}, 'data')
|
68
68
|
```
|
69
69
|
... or like this:
|
70
70
|
``` ruby
|
71
71
|
client = WP::HMAC::Client.new('https://www.example.com')
|
72
72
|
client.get('api/staff')
|
73
|
-
client.post('api/schedules', {},
|
73
|
+
client.post('api/schedules', {}, 'data')
|
74
74
|
```
|
75
75
|
See Rack::Client docs for more.
|
76
76
|
|
data/Rakefile
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/wp/hmac.rb
CHANGED
@@ -18,7 +18,7 @@ module WP
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.add_key(id:, auth_key:)
|
21
|
-
KeyCabinet.add_key(
|
21
|
+
KeyCabinet.add_key(id: id, auth_key: auth_key)
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.add_hmac_enabled_route(route_regex)
|
@@ -30,7 +30,8 @@ module WP
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.auth_id
|
33
|
-
|
33
|
+
msg = 'Set get_auth_id_for_request in the initializer'
|
34
|
+
fail MissingConfiguration, msg unless @callable
|
34
35
|
@callable.call
|
35
36
|
end
|
36
37
|
|
data/lib/wp/hmac/client.rb
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
module WP
|
2
2
|
module HMAC
|
3
|
+
# = HMAC Client
|
4
|
+
# This client uses EY::ApiHMAC to hash a request with a secret key in order
|
5
|
+
# to authenticate the client.
|
6
|
+
#
|
7
|
+
# See here for the implementation details:
|
8
|
+
# https://github.com/engineyard/ey_api_hmac
|
3
9
|
class Client
|
4
10
|
class UnsuccessfulResponse < StandardError; end
|
5
11
|
|
6
|
-
|
7
|
-
|
12
|
+
@rack_app = Rack::Client::Handler::NetHTTP
|
13
|
+
# Enable injection of another Rack app for testing
|
14
|
+
class << self
|
15
|
+
attr_accessor :rack_app
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(url = nil)
|
19
|
+
build_rack_client(url)
|
8
20
|
end
|
9
21
|
|
10
|
-
def build_rack_client(url
|
22
|
+
def build_rack_client(url)
|
11
23
|
id = key_cabinet.id
|
12
24
|
auth_key = key_cabinet.auth_key
|
13
25
|
|
@@ -16,7 +28,7 @@ module WP
|
|
16
28
|
env['HTTP_DATE'] = Time.now.httpdate
|
17
29
|
end
|
18
30
|
use EY::ApiHMAC::ApiAuth::Client, id, auth_key
|
19
|
-
run
|
31
|
+
run Client.rack_app
|
20
32
|
end
|
21
33
|
@client
|
22
34
|
end
|
@@ -31,7 +43,7 @@ module WP
|
|
31
43
|
%i(delete get head options post put patch).each do |method|
|
32
44
|
define_method(method) do |*args|
|
33
45
|
response = @client.send(method, *args)
|
34
|
-
|
46
|
+
fail UnsuccessfulResponse unless /2\d\d/.match("#{response.status}")
|
35
47
|
response
|
36
48
|
end
|
37
49
|
end
|
data/lib/wp/hmac/key_cabinet.rb
CHANGED
@@ -1,31 +1,33 @@
|
|
1
1
|
module WP
|
2
2
|
module HMAC
|
3
|
+
# = Key Cabinet
|
4
|
+
#
|
5
|
+
# Stores the secret keys used in the hash function.
|
3
6
|
class KeyCabinet
|
4
7
|
class KeyNotFound < Exception; end
|
5
8
|
|
6
9
|
class << self
|
7
10
|
attr_accessor :keys
|
11
|
+
attr_writer :lookup_block
|
8
12
|
|
9
13
|
def add_key(id:, auth_key:)
|
10
14
|
@keys ||= {}
|
11
15
|
@keys[id] = { id: id, auth_key: auth_key }
|
12
16
|
end
|
13
17
|
|
18
|
+
# This method will be called by EY::ApiHMAC. It must return
|
19
|
+
# an object that responds to +id+ and +auth_key+
|
14
20
|
def find_by_auth_id(id)
|
15
21
|
hash = lookup(id) || @keys[id]
|
16
|
-
|
22
|
+
msg = 'Ensure secret keys are loaded with `HMAC::KeyCabinet.add_key`'
|
23
|
+
fail KeyNotFound, msg if hash.nil?
|
17
24
|
OpenStruct.new(hash)
|
18
25
|
end
|
19
26
|
|
20
27
|
def lookup(id)
|
21
28
|
return unless @lookup_block
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def lookup_block=(block)
|
28
|
-
@lookup_block = block
|
29
|
+
key = @lookup_block.call(id)
|
30
|
+
return { id: id, auth_key: key } if key
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/wp/hmac/server.rb
CHANGED
data/lib/wp/hmac/version.rb
CHANGED
data/spec/hmac_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
ENV[
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
2
|
require File.expand_path('../../lib/wp/hmac', __FILE__)
|
3
3
|
require File.expand_path('../app/config/environment', __FILE__)
|
4
4
|
require 'pry'
|
@@ -8,30 +8,37 @@ RSpec.configure do |config|
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class DummyController < ActionController::Base
|
11
|
-
def show
|
12
|
-
render inline: 'Hello, world!'
|
13
|
-
end
|
14
|
-
|
15
11
|
def create
|
16
12
|
head :bad_request
|
17
13
|
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
render inline: 'Hello, updated world!'
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
render inline: 'Hello, world!'
|
21
|
+
end
|
18
22
|
end
|
19
23
|
|
20
24
|
RSpec.describe WP::HMAC, type: :request do
|
25
|
+
let(:app) { App::Application }
|
26
|
+
|
21
27
|
before(:example) do
|
22
28
|
WP::HMAC.configure do
|
23
|
-
add_key(
|
29
|
+
add_key(id: 'esso', auth_key: 'secret_key')
|
24
30
|
add_hmac_enabled_route %r{^/dummy/}
|
25
31
|
get_auth_id_for_request -> { 'esso' }
|
26
32
|
end
|
33
|
+
|
34
|
+
WP::HMAC::Client.rack_app = app
|
27
35
|
end
|
28
36
|
|
29
37
|
after(:example) do
|
30
38
|
WP::HMAC.reset
|
31
39
|
end
|
32
40
|
|
33
|
-
let(:
|
34
|
-
let(:hmac_client) { WP::HMAC::Client.new(nil, app) }
|
41
|
+
let(:hmac_client) { WP::HMAC::Client.new(nil) }
|
35
42
|
|
36
43
|
before do
|
37
44
|
Rails.application.routes.draw do
|
@@ -50,9 +57,9 @@ RSpec.describe WP::HMAC, type: :request do
|
|
50
57
|
|
51
58
|
context 'when hmac is enabled for the route' do
|
52
59
|
it 'raises an exception' do
|
53
|
-
expect
|
60
|
+
expect do
|
54
61
|
get 'http://esso.example.com/dummy/1'
|
55
|
-
|
62
|
+
end.to raise_error(WP::HMAC::KeyCabinet::KeyNotFound)
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
@@ -68,14 +75,18 @@ RSpec.describe WP::HMAC, type: :request do
|
|
68
75
|
context 'with a key cabinet' do
|
69
76
|
it 'fails when a request is not signed' do
|
70
77
|
get 'http://esso.example.org/dummy/1'
|
71
|
-
|
78
|
+
|
79
|
+
expect(last_response.body)
|
80
|
+
.to eql('Authentication failure: no authorization header')
|
72
81
|
end
|
73
82
|
|
74
83
|
it 'fails when a request is signed with a duff hash' do
|
75
84
|
header 'Authorization', 'AuthHMAC esso:1234'
|
76
85
|
header 'Date', Time.now.httpdate
|
77
86
|
get 'http://esso.example.org/dummy/1'
|
78
|
-
|
87
|
+
|
88
|
+
expect(last_response.body)
|
89
|
+
.to include('Authentication failure: signature mismatch')
|
79
90
|
end
|
80
91
|
|
81
92
|
it 'succeeds when the request is correctly signed' do
|
@@ -84,29 +95,43 @@ RSpec.describe WP::HMAC, type: :request do
|
|
84
95
|
end
|
85
96
|
|
86
97
|
it 'succeeds when the request is correctly signed (alt syntax)' do
|
87
|
-
pending 'Need to work out how to test this'
|
88
98
|
rack_response = WP::HMAC::Client.get('http://esso.example.org/dummy/1')
|
89
99
|
expect(rack_response.body).to include('Hello, world!')
|
90
100
|
end
|
91
101
|
|
92
102
|
it 'raises UnsuccessfulResponse when server reponds 400' do
|
93
|
-
expect
|
103
|
+
expect do
|
94
104
|
hmac_client.post('http://esso.example.org/dummy')
|
95
|
-
|
105
|
+
end.to raise_error(WP::HMAC::Client::UnsuccessfulResponse)
|
96
106
|
end
|
97
107
|
|
98
108
|
it 'raises UnsuccessfulResponse when server reponds 400 (alt syntax)' do
|
99
|
-
|
100
|
-
expect {
|
109
|
+
expect do
|
101
110
|
WP::HMAC::Client.post('http://esso.example.org/dummy')
|
102
|
-
|
111
|
+
end.to raise_error(WP::HMAC::Client::UnsuccessfulResponse)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'succeeds when the request body resonds to #read' do
|
115
|
+
rack_response = hmac_client.put('http://esso.example.org/dummy/1',
|
116
|
+
{},
|
117
|
+
StringIO.new('hi'))
|
118
|
+
|
119
|
+
expect(rack_response.body).to include('Hello, updated world!')
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'succeeds when the request body is a string' do
|
123
|
+
rack_response = hmac_client.put('http://esso.example.org/dummy/1',
|
124
|
+
{},
|
125
|
+
'hi')
|
126
|
+
|
127
|
+
expect(rack_response.body).to include('Hello, updated world!')
|
103
128
|
end
|
104
129
|
end
|
105
130
|
|
106
131
|
context 'with a key configured via a block' do
|
107
132
|
before do
|
108
133
|
WP::HMAC.configure do
|
109
|
-
lookup_auth_key_with { |id| id == 'account2' ?
|
134
|
+
lookup_auth_key_with { |id| id == 'account2' ? 'mykey' : nil }
|
110
135
|
end
|
111
136
|
end
|
112
137
|
|
data/wp-hmac.gemspec
CHANGED
@@ -4,27 +4,29 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'wp/hmac/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'wp-hmac'
|
8
8
|
spec.version = Wp::Hmac::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
|
14
|
-
spec.
|
9
|
+
spec.authors = ['Andrew Nagi']
|
10
|
+
spec.email = ['andrew.nagi@gmail.com']
|
11
|
+
spec.summary = 'HMAC for Rack Apps'
|
12
|
+
spec.description =
|
13
|
+
'Enable different HMAC keys on different routes / subdomains.'
|
14
|
+
spec.homepage = 'https://github.com/workplacesystems/wp-hmac'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = spec.files.grep(
|
18
|
-
spec.test_files = spec.files.grep(
|
19
|
-
spec.require_paths = [
|
18
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_dependency
|
22
|
+
spec.add_dependency 'ey_api_hmac', '0.4.12'
|
22
23
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_development_dependency 'rails', '4.1.4'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.29'
|
29
|
+
spec.add_development_dependency 'fuubar', '~> 2.0'
|
30
|
+
spec.add_development_dependency 'pry'
|
31
|
+
spec.add_development_dependency 'sqlite3'
|
30
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wp-hmac
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Nagi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ey_api_hmac
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.29'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.29'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: fuubar
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,6 +144,7 @@ extensions: []
|
|
130
144
|
extra_rdoc_files: []
|
131
145
|
files:
|
132
146
|
- ".gitignore"
|
147
|
+
- ".rubocop.yml"
|
133
148
|
- Gemfile
|
134
149
|
- LICENSE.txt
|
135
150
|
- README.md
|
@@ -217,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
232
|
version: '0'
|
218
233
|
requirements: []
|
219
234
|
rubyforge_project:
|
220
|
-
rubygems_version: 2.
|
235
|
+
rubygems_version: 2.4.5
|
221
236
|
signing_key:
|
222
237
|
specification_version: 4
|
223
238
|
summary: HMAC for Rack Apps
|
@@ -279,4 +294,3 @@ test_files:
|
|
279
294
|
- spec/app/vendor/assets/javascripts/.keep
|
280
295
|
- spec/app/vendor/assets/stylesheets/.keep
|
281
296
|
- spec/hmac_spec.rb
|
282
|
-
has_rdoc:
|