smart_proxy_vault 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 +7 -0
- data/LICENSE +675 -0
- data/README.md +152 -0
- data/bundler.d/vault.rb +1 -0
- data/lib/smart_proxy_vault/authentication/chef.rb +54 -0
- data/lib/smart_proxy_vault/authentication.rb +33 -0
- data/lib/smart_proxy_vault/helpers.rb +31 -0
- data/lib/smart_proxy_vault/https_config.ru +3 -0
- data/lib/smart_proxy_vault/vault.rb +14 -0
- data/lib/smart_proxy_vault/vault_api.rb +20 -0
- data/lib/smart_proxy_vault/vault_backend.rb +43 -0
- data/lib/smart_proxy_vault/version.rb +3 -0
- data/lib/smart_proxy_vault.rb +11 -0
- data/settings.d/vault.yml.example +16 -0
- data/test/authentication_chef_test.rb +102 -0
- data/test/factories/rsa.rb +11 -0
- data/test/fixtures/authentication/chef/bender.pem +27 -0
- data/test/fixtures/authentication/chef/fry.pem +27 -0
- data/test/request_test.rb +72 -0
- data/test/test_helper.rb +23 -0
- metadata +225 -0
data/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
[](https://travis-ci.org/visioncritical/smart_proxy_vault)
|
|
2
|
+
[](https://codeclimate.com/github/visioncritical/smart_proxy_vault)
|
|
3
|
+
[](https://codeclimate.com/github/visioncritical/smart_proxy_vault/coverage)
|
|
4
|
+
[](https://rubygems.org/gems/smart_proxy_vault/versions)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Smart Proxy - Vault Plugin
|
|
9
|
+
|
|
10
|
+
A Smart Proxy plugin will return a Vault token after authenticating a client.
|
|
11
|
+
|
|
12
|
+
## Design
|
|
13
|
+
|
|
14
|
+
The authentication portion of this plugin has been designed to be modular. Below is a current list of clients this plugin knows how to authenticate:
|
|
15
|
+
|
|
16
|
+
* Chef
|
|
17
|
+
|
|
18
|
+
If you're unable to use one of the above to authenticate your clients, you can always write your own & submit a PR (see [DEVELOPMENT.md](documentation/DEVELOPMENT.md)).
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Add this line to your Smart Proxy bundler.d/vault.rb gemfile:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
gem 'smart_proxy_vault'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
And then execute:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bundle install
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Settings
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
---
|
|
40
|
+
:enabled: true
|
|
41
|
+
:auth_backend: 'chef'
|
|
42
|
+
:vault:
|
|
43
|
+
:address: "https://vault.example.com"
|
|
44
|
+
:token: "UUID"
|
|
45
|
+
:ssl_verify: true
|
|
46
|
+
:add_token_metadata: true
|
|
47
|
+
:token_options:
|
|
48
|
+
:policies: ['policyname']
|
|
49
|
+
:ttl: '72h'
|
|
50
|
+
:chef:
|
|
51
|
+
:endpoint: 'https://chef.example.com'
|
|
52
|
+
:client: 'user'
|
|
53
|
+
:key: '/path/to/client.pem'
|
|
54
|
+
:ssl_verify: true
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### General
|
|
58
|
+
|
|
59
|
+
#####:enabled:
|
|
60
|
+
|
|
61
|
+
Toggles whether or not this plugin is enabled for Smart Proxy.
|
|
62
|
+
|
|
63
|
+
#####:auth_backend:
|
|
64
|
+
|
|
65
|
+
Specifies what authentication module you would like to use to authenticate your clients (must correspond to a filename in [lib/smart_proxy_vault/authentication/](lib/smart_proxy_vault/authentication/))
|
|
66
|
+
|
|
67
|
+
#####:vault:
|
|
68
|
+
|
|
69
|
+
A hash of Vault settings that are used to configure a connection to the Vault server (determined by the [Vault](https://github.com/hashicorp/vault-ruby) gem).
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
# https://github.com/hashicorp/vault-ruby/blob/master/lib/vault/configurable.rb
|
|
73
|
+
:vault:
|
|
74
|
+
:address:
|
|
75
|
+
:token:
|
|
76
|
+
:open_timeout:
|
|
77
|
+
:proxy_address:
|
|
78
|
+
:proxy_password:
|
|
79
|
+
:proxy_port:
|
|
80
|
+
:proxy_username:
|
|
81
|
+
:read_timeout:
|
|
82
|
+
:ssl_ciphers:
|
|
83
|
+
:ssl_pem_file:
|
|
84
|
+
:ssl_pem_passphrase:
|
|
85
|
+
:ssl_ca_cert:
|
|
86
|
+
:ssl_ca_path:
|
|
87
|
+
:ssl_verify:
|
|
88
|
+
:ssl_timeout:
|
|
89
|
+
:timeout:
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#####:add_token_metadata:
|
|
93
|
+
|
|
94
|
+
If set to true, this plugin will add the requesting client's ID (as determined by the auth_backend) in the metadata & display-name fields when requesting a token.
|
|
95
|
+
|
|
96
|
+
#####:token_options:
|
|
97
|
+
|
|
98
|
+
A hash of parameters that will be passed to the token creation call ([/auth/token/create](https://www.vaultproject.io/docs/auth/token.html)).
|
|
99
|
+
|
|
100
|
+
#### Chef Backend
|
|
101
|
+
|
|
102
|
+
Only to be specified when the `:auth_backend:` is `chef`. Refer to the [Chef backend](documentation/CHEF.md) documentation for more information.
|
|
103
|
+
|
|
104
|
+
#####:chef:
|
|
105
|
+
|
|
106
|
+
A hash of settings that are used to configure a connection to the Chef server (used by the [Chef API](https://github.com/sethvargo/chef-api) gem).
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
# https://github.com/sethvargo/chef-api/blob/master/lib/chef-api/configurable.rb
|
|
110
|
+
:chef:
|
|
111
|
+
:endpoint:
|
|
112
|
+
:flavor:
|
|
113
|
+
:client:
|
|
114
|
+
:key:
|
|
115
|
+
:proxy_address:
|
|
116
|
+
:proxy_password:
|
|
117
|
+
:proxy_port:
|
|
118
|
+
:proxy_username:
|
|
119
|
+
:ssl_pem_file:
|
|
120
|
+
:ssl_verify:
|
|
121
|
+
:user_agent:
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Usage
|
|
125
|
+
|
|
126
|
+
To configure this plugin you can use template from [settings.d/vault.yml.example](settings.d/vault.yml.example). You must place the vault.yml config file in your Smart Proxy's `config/settings.d/` directory.
|
|
127
|
+
|
|
128
|
+
### Endpoints
|
|
129
|
+
|
|
130
|
+
#### `/vault/token/issue`
|
|
131
|
+
|
|
132
|
+
##### Parameters
|
|
133
|
+
|
|
134
|
+
`ttl=X[d,h,m,s]`
|
|
135
|
+
|
|
136
|
+
Overrides the token TTL specified in the [`:token_options:`](#token_options) section. This value must be **lower** than the default TTL.
|
|
137
|
+
|
|
138
|
+
Example:
|
|
139
|
+
|
|
140
|
+
`/vault/token/issue?ttl=60s`
|
|
141
|
+
|
|
142
|
+
### Caveats
|
|
143
|
+
|
|
144
|
+
In order to use this plugin effectively, the Ruby installation on your Smart Proxy server should be version 2.0.0 or higher, and be compiled against a version of OpenSSL that supports TLS (=>1.0.1). I recommend using [RVM](https://rvm.io/) & [Passenger](https://www.phusionpassenger.com) to run your Smart Proxy server.
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
$ irb
|
|
148
|
+
2.2.1 :001 > require 'openssl'
|
|
149
|
+
=> true
|
|
150
|
+
2.2.1 :002 > OpenSSL::OPENSSL_VERSION
|
|
151
|
+
=> "OpenSSL 1.0.1e 11 Feb 2013"
|
|
152
|
+
```
|
data/bundler.d/vault.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gem 'smart_proxy_vault'
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'chef-api'
|
|
2
|
+
|
|
3
|
+
module VaultPlugin
|
|
4
|
+
module Authentication
|
|
5
|
+
module Chef
|
|
6
|
+
def vault_client
|
|
7
|
+
request.env['HTTP_X_VAULT_CLIENT']
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def signature
|
|
11
|
+
request.env['HTTP_X_VAULT_SIGNATURE'] || request.env['HTTP_X_VAULT_SIGNATURE'].chomp
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def authorized?
|
|
15
|
+
logger.info('Starting Chef client authentication for smart_proxy_vault')
|
|
16
|
+
request.env.each do |key,value|
|
|
17
|
+
logger.debug("header #{key}: #{value}")
|
|
18
|
+
end if logger.level == 0
|
|
19
|
+
|
|
20
|
+
if vault_client.nil? || signature.nil?
|
|
21
|
+
log_halt 401, "Failed to authenticate Chef client - #{vault_client}. Missing headers."
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
unless authenticate
|
|
25
|
+
log_halt 401, "Failed to authenticate Chef client - #{vault_client}. Verification failed."
|
|
26
|
+
end
|
|
27
|
+
logger.info("Successfully authenticated Chef client - #{vault_client}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def chefapi
|
|
31
|
+
chefapi_settings = ::VaultPlugin::Plugin.settings.chef
|
|
32
|
+
connection = ::ChefAPI::Connection.new(chefapi_settings)
|
|
33
|
+
connection.ssl_verify = chefapi_settings[:ssl_verify] || false
|
|
34
|
+
connection
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def authenticate
|
|
38
|
+
begin
|
|
39
|
+
node = chefapi.clients.fetch vault_client
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
log_halt 401, 'Failed to authenticate to the Chef server: ' + e.message
|
|
42
|
+
end
|
|
43
|
+
log_halt(401, "Could not find Chef client - #{vault_client}") if node.nil?
|
|
44
|
+
|
|
45
|
+
rsa = OpenSSL::PKey::RSA.new node.public_key
|
|
46
|
+
decoded_signature = Base64.decode64(signature)
|
|
47
|
+
# The body should contain the public key of the node
|
|
48
|
+
body = Digest::MD5.hexdigest rsa.public_key.to_s
|
|
49
|
+
|
|
50
|
+
rsa.verify(OpenSSL::Digest::SHA512.new, decoded_signature, body)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require_relative 'authentication/chef'
|
|
2
|
+
|
|
3
|
+
module VaultPlugin
|
|
4
|
+
module Authentication
|
|
5
|
+
def auth_backend
|
|
6
|
+
::VaultPlugin::Plugin.settings.auth_backend.to_sym
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def auth_module
|
|
10
|
+
Object.const_get('::VaultPlugin::Authentication::' + auth_backend.capitalize.to_s)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Creates convenient accessor methods for all keys underneath auth_backend
|
|
14
|
+
def create_setting_accessors
|
|
15
|
+
::VaultPlugin::Plugin.settings[auth_backend].each do |key,value|
|
|
16
|
+
define_singleton_method(key.to_sym) { value }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def authorized?
|
|
21
|
+
create_setting_accessors
|
|
22
|
+
extend auth_module
|
|
23
|
+
authorized?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the human-readable identity for the requesting client
|
|
27
|
+
# Optionally used in a token's metadata & display-name
|
|
28
|
+
def client
|
|
29
|
+
extend auth_module
|
|
30
|
+
client
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module VaultPlugin
|
|
2
|
+
module Helpers
|
|
3
|
+
def settings_ttl
|
|
4
|
+
::VaultPlugin::Plugin.settings.token_options[:ttl]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def to_seconds(string)
|
|
8
|
+
case string.slice(-1)
|
|
9
|
+
when 'd'
|
|
10
|
+
string.tr('d', '').to_i * 30 * 24
|
|
11
|
+
when 'h'
|
|
12
|
+
string.tr('h', '').to_i * 3600
|
|
13
|
+
when 'm'
|
|
14
|
+
string.tr('m', '').to_i * 60
|
|
15
|
+
when 's'
|
|
16
|
+
string.tr('s', '').to_i
|
|
17
|
+
else
|
|
18
|
+
log_halt 400, "Invalid TTL - #{string}. Must end with 'd', 'h', 'm' or 's'."
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Only allow clients to specify a TTL that is shorter than the default
|
|
23
|
+
def valid_ttl?(ttl)
|
|
24
|
+
return true if ttl.nil? || settings_ttl.nil?
|
|
25
|
+
unless (to_seconds(settings_ttl) >= to_seconds(ttl))
|
|
26
|
+
log_halt 400, "Invalid TTL - #{ttl}. Must be shorter or equal to #{settings_ttl}."
|
|
27
|
+
end
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module VaultPlugin
|
|
2
|
+
class Plugin < ::Proxy::Plugin
|
|
3
|
+
plugin 'vault', VaultPlugin::VERSION
|
|
4
|
+
|
|
5
|
+
settings_file 'vault.yml'
|
|
6
|
+
default_settings auth_backend: 'chef',
|
|
7
|
+
vault: {},
|
|
8
|
+
add_token_metadata: false,
|
|
9
|
+
token_options: {},
|
|
10
|
+
chef: {}
|
|
11
|
+
|
|
12
|
+
https_rackup_path File.expand_path('https_config.ru', File.expand_path('../', __FILE__))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module VaultPlugin
|
|
2
|
+
class VaultAPI < ::Sinatra::Base
|
|
3
|
+
include ::Proxy::Log
|
|
4
|
+
include ::VaultPlugin::Authentication
|
|
5
|
+
include ::VaultPlugin::VaultBackend
|
|
6
|
+
helpers ::Proxy::Helpers, ::VaultPlugin::Helpers
|
|
7
|
+
|
|
8
|
+
::Sinatra::Base.register Authentication
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
content_type :json
|
|
12
|
+
authorized?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
get '/token/issue' do
|
|
16
|
+
ttl = params[:ttl]
|
|
17
|
+
issue(ttl) if valid_ttl? ttl
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module VaultPlugin
|
|
2
|
+
module VaultBackend
|
|
3
|
+
class API
|
|
4
|
+
attr_reader :connection
|
|
5
|
+
|
|
6
|
+
def initialize(child, ttl)
|
|
7
|
+
vault_settings = ::VaultPlugin::Plugin.settings.vault
|
|
8
|
+
@connection = ::Vault::Client.new(vault_settings)
|
|
9
|
+
@child = child
|
|
10
|
+
@ttl = ttl
|
|
11
|
+
@token_options = token_options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def issue_token
|
|
15
|
+
@connection.auth_token.create(@token_options).auth.client_token
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
def metadata
|
|
20
|
+
if ::VaultPlugin::Plugin.settings.add_token_metadata == true
|
|
21
|
+
return { meta: { client: @child, smartproxy_generated: true },
|
|
22
|
+
display_name: @child }
|
|
23
|
+
end
|
|
24
|
+
{}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def token_options
|
|
28
|
+
options = metadata.merge ::VaultPlugin::Plugin.settings[:token_options]
|
|
29
|
+
options[:ttl] = @ttl unless @ttl.nil?
|
|
30
|
+
options
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def issue(ttl)
|
|
35
|
+
begin
|
|
36
|
+
vault = API.new client, ttl
|
|
37
|
+
vault.issue_token
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
log_halt 500, 'Failed to generate Vault token ' + e.message
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'sinatra/base'
|
|
2
|
+
require 'vault'
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
|
|
6
|
+
require 'smart_proxy_vault/authentication'
|
|
7
|
+
require 'smart_proxy_vault/helpers'
|
|
8
|
+
require 'smart_proxy_vault/vault_backend'
|
|
9
|
+
require 'smart_proxy_vault/vault_api'
|
|
10
|
+
require 'smart_proxy_vault/version'
|
|
11
|
+
require 'smart_proxy_vault/vault'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
:enabled: true
|
|
3
|
+
:auth_backend: 'chef'
|
|
4
|
+
:vault:
|
|
5
|
+
:address: "https://vault.example.com"
|
|
6
|
+
:token: "UUID"
|
|
7
|
+
:ssl_verify: true
|
|
8
|
+
:add_token_metadata: true
|
|
9
|
+
:token_options:
|
|
10
|
+
:policies: ['policyname']
|
|
11
|
+
:ttl: '72h'
|
|
12
|
+
:chef:
|
|
13
|
+
:endpoint: 'https://chef.example.com'
|
|
14
|
+
:client: 'user'
|
|
15
|
+
:key: '/path/to/client.pem'
|
|
16
|
+
:ssl_verify: true
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'smart_proxy_vault'
|
|
3
|
+
|
|
4
|
+
class AuthenticationChefTest < Test::Unit::TestCase
|
|
5
|
+
include Rack::Test::Methods
|
|
6
|
+
|
|
7
|
+
###
|
|
8
|
+
# Classes
|
|
9
|
+
###
|
|
10
|
+
|
|
11
|
+
class Mock
|
|
12
|
+
include VaultPlugin::Authentication::Chef
|
|
13
|
+
|
|
14
|
+
def logger
|
|
15
|
+
@logger ||= Logger.new(StringIO.new)
|
|
16
|
+
@logger.level = Logger::INFO
|
|
17
|
+
@logger
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def log_halt(*args)
|
|
21
|
+
throw :halt
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
###
|
|
26
|
+
# Helper Methods
|
|
27
|
+
###
|
|
28
|
+
|
|
29
|
+
def sign_request(key_path)
|
|
30
|
+
rsa = OpenSSL::PKey::RSA.new File.read key_path
|
|
31
|
+
body = Digest::MD5.hexdigest rsa.public_key.to_s
|
|
32
|
+
Base64.strict_encode64(rsa.sign(OpenSSL::Digest::SHA512.new, body))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def stub_client(client, signature)
|
|
36
|
+
stub.proxy(AuthenticationChefTest::Mock).new do |obj|
|
|
37
|
+
stub(obj).vault_client { client }
|
|
38
|
+
stub(obj).signature { signature }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def stub_response(client, public_key, status=200)
|
|
43
|
+
response = %({"name": "#{client}", "admin": false, "public_key": "#{public_key.gsub("\n","\\n")}", "private_key": false, "validator": false})
|
|
44
|
+
stub_request(:get, "https://chef.example.com/clients/#{client}").to_return(:status => status, :body => response.to_s, :headers => {'content-type' => 'application/json'} )
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
###
|
|
48
|
+
# Test Methods
|
|
49
|
+
###
|
|
50
|
+
|
|
51
|
+
def setup
|
|
52
|
+
stub.proxy(::VaultPlugin::Plugin.settings).chef {{
|
|
53
|
+
:endpoint => 'https://chef.example.com',
|
|
54
|
+
:client => 'fry',
|
|
55
|
+
:key => 'test/fixtures/authentication/chef/fry.pem',
|
|
56
|
+
:ssl_verify => true
|
|
57
|
+
}}
|
|
58
|
+
|
|
59
|
+
@fry_client = FactoryGirl.create(:rsa, file: 'test/fixtures/authentication/chef/fry.pem' )
|
|
60
|
+
@fry_client_path = 'test/fixtures/authentication/chef/fry.pem'
|
|
61
|
+
@bender_client = FactoryGirl.create(:rsa, file: 'test/fixtures/authentication/chef/bender.pem' )
|
|
62
|
+
@bender_client_path = 'test/fixtures/authentication/chef/bender.pem'
|
|
63
|
+
|
|
64
|
+
@fry_signature = sign_request @fry_client_path
|
|
65
|
+
@bender_signature = sign_request @bender_client_path
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_signature_verification_match
|
|
69
|
+
stub_client 'fry', @fry_signature
|
|
70
|
+
stub_response 'fry', @fry_client.public_key.to_s
|
|
71
|
+
chefauth = Mock.new
|
|
72
|
+
assert_nothing_thrown do
|
|
73
|
+
assert chefauth.authorized?, 'Encoding & Decoding a message with the same key should pass verification'
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_signature_verification_mismatch
|
|
78
|
+
stub_client 'bender', @bender_signature
|
|
79
|
+
stub_response 'bender', @fry_client.public_key.to_s
|
|
80
|
+
chefauth = Mock.new
|
|
81
|
+
assert_throws :halt do
|
|
82
|
+
refute chefauth.authorized?, 'Encoding & Decoding a message with the different key should fail verification'
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_header_requirement
|
|
87
|
+
stub_client(nil, nil)
|
|
88
|
+
chefauth = Mock.new
|
|
89
|
+
assert_throws :halt do
|
|
90
|
+
refute chefauth.authorized?, 'A request without headers should fail'
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_client_not_found
|
|
95
|
+
stub_client('zoidberg', @bender_signature)
|
|
96
|
+
stub_response('zoidberg', @bender_signature, 404)
|
|
97
|
+
chefauth = Mock.new
|
|
98
|
+
assert_throws :halt do
|
|
99
|
+
refute chefauth.authorized?, %(It should fail when a client can't be found on the Chef server)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|