chef-vault 2.5.0 → 2.6.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 +4 -4
- data/.rubocop_todo.yml +5 -1
- data/.travis.yml +5 -1
- data/Changelog.md +36 -3
- data/KNIFE_EXAMPLES.md +49 -74
- data/README.md +166 -104
- data/THEORY.md +4 -2
- data/bin/chef-vault +2 -2
- data/chef-vault.gemspec +2 -2
- data/features/clean_on_refresh.feature +28 -0
- data/features/isvault.feature +24 -0
- data/features/itemtype.feature +25 -0
- data/features/step_definitions/chef-databag.rb +4 -0
- data/features/step_definitions/chef-vault.rb +21 -0
- data/features/step_definitions/chef_databagitem.rb +9 -0
- data/features/vault_show_vaultname.feature +22 -0
- data/features/vault_update.feature +1 -1
- data/features/verify_id_matches.feature +11 -0
- data/lib/chef-vault/certificate.rb +1 -1
- data/lib/chef-vault/exceptions.rb +3 -0
- data/lib/chef-vault/item.rb +161 -18
- data/lib/chef-vault/user.rb +1 -1
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef/knife/decrypt.rb +1 -1
- data/lib/chef/knife/encrypt_create.rb +1 -1
- data/lib/chef/knife/encrypt_delete.rb +1 -1
- data/lib/chef/knife/encrypt_remove.rb +1 -1
- data/lib/chef/knife/encrypt_rotate_keys.rb +1 -1
- data/lib/chef/knife/encrypt_update.rb +1 -1
- data/lib/chef/knife/vault_base.rb +22 -0
- data/lib/chef/knife/vault_create.rb +0 -1
- data/lib/chef/knife/vault_decrypt.rb +1 -1
- data/lib/chef/knife/vault_isvault.rb +43 -0
- data/lib/chef/knife/vault_itemtype.rb +43 -0
- data/lib/chef/knife/vault_list.rb +7 -18
- data/lib/chef/knife/vault_refresh.rb +6 -12
- data/lib/chef/knife/vault_rotate_all_keys.rb +1 -1
- data/lib/chef/knife/vault_show.rb +15 -1
- data/lib/chef/knife/vault_update.rb +1 -1
- data/spec/chef-vault/certificate_spec.rb +9 -2
- data/spec/chef-vault/item_spec.rb +164 -3
- data/spec/chef-vault/user_spec.rb +9 -2
- metadata +14 -6
data/lib/chef-vault/user.rb
CHANGED
data/lib/chef-vault/version.rb
CHANGED
data/lib/chef/knife/decrypt.rb
CHANGED
@@ -24,7 +24,7 @@ class Chef
|
|
24
24
|
banner "knife decrypt VAULT ITEM [VALUES] (options)"
|
25
25
|
|
26
26
|
def run
|
27
|
-
puts "DEPRECATION WARNING: knife decrypt is deprecated. Please use knife vault decrypt instead."
|
27
|
+
$stdout.puts "DEPRECATION WARNING: knife decrypt is deprecated. Please use knife vault decrypt instead."
|
28
28
|
super
|
29
29
|
end
|
30
30
|
end
|
@@ -43,7 +43,7 @@ class Chef
|
|
43
43
|
:description => 'File to be added to vault item as file-content'
|
44
44
|
|
45
45
|
def run
|
46
|
-
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
46
|
+
$stdout.puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
47
47
|
super
|
48
48
|
end
|
49
49
|
end
|
@@ -24,7 +24,7 @@ class Chef
|
|
24
24
|
banner "knife encrypt delete VAULT ITEM (options)"
|
25
25
|
|
26
26
|
def run
|
27
|
-
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
27
|
+
$stdout.puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
28
28
|
super
|
29
29
|
end
|
30
30
|
end
|
@@ -34,7 +34,7 @@ class Chef
|
|
34
34
|
:description => 'Chef users to be added as admins'
|
35
35
|
|
36
36
|
def run
|
37
|
-
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
37
|
+
$stdout.puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
38
38
|
super
|
39
39
|
end
|
40
40
|
end
|
@@ -24,7 +24,7 @@ class Chef
|
|
24
24
|
banner "knife encrypt rotate keys VAULT ITEM (options)"
|
25
25
|
|
26
26
|
def run
|
27
|
-
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
27
|
+
$stdout.puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
28
28
|
super
|
29
29
|
end
|
30
30
|
end
|
@@ -43,7 +43,7 @@ class Chef
|
|
43
43
|
banner "knife encrypt update VAULT ITEM VALUES (options)"
|
44
44
|
|
45
45
|
def run
|
46
|
-
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
46
|
+
$stdout.puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
47
47
|
super
|
48
48
|
end
|
49
49
|
end
|
@@ -41,6 +41,28 @@ class Chef
|
|
41
41
|
super
|
42
42
|
exit 1
|
43
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def bag_is_vault?(bagname)
|
48
|
+
bag = Chef::DataBag.load(bagname)
|
49
|
+
# vaults have at even number of keys >= 2
|
50
|
+
return false unless bag.keys.size >= 2 && 0 == bag.keys.size % 2
|
51
|
+
# partition into those that end in _keys
|
52
|
+
keylike, notkeylike = split_vault_keys(bag)
|
53
|
+
# there must be an equal number of keyline and not-keylike items
|
54
|
+
return false unless keylike.size == notkeylike.size
|
55
|
+
# strip the _keys suffix and check if the sets match
|
56
|
+
keylike.map! { |k| k.gsub(/_keys$/, '') }
|
57
|
+
return false unless keylike.sort == notkeylike.sort
|
58
|
+
# it's (probably) a vault
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def split_vault_keys(bag)
|
63
|
+
# partition into those that end in _keys
|
64
|
+
bag.keys.partition { |k| k =~ /_keys$/ }
|
65
|
+
end
|
44
66
|
end
|
45
67
|
end
|
46
68
|
end
|
@@ -63,7 +63,6 @@ class Chef
|
|
63
63
|
rescue ChefVault::Exceptions::KeysNotFound,
|
64
64
|
ChefVault::Exceptions::ItemNotFound
|
65
65
|
vault_item = ChefVault::Item.new(vault, item)
|
66
|
-
|
67
66
|
if values || json_file || file
|
68
67
|
merge_values(values, json_file).each do |key, value|
|
69
68
|
vault_item[key] = value
|
@@ -23,7 +23,7 @@ class Chef
|
|
23
23
|
banner "knife vault decrypt VAULT ITEM [VALUES] (options)"
|
24
24
|
|
25
25
|
def run
|
26
|
-
puts "DEPRECATION WARNING: knife vault decrypt is deprecated. Please use knife vault show instead."
|
26
|
+
$stdout.puts "DEPRECATION WARNING: knife vault decrypt is deprecated. Please use knife vault show instead."
|
27
27
|
vault = @name_args[0]
|
28
28
|
item = @name_args[1]
|
29
29
|
values = @name_args[2]
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Description: Chef-Vault VaultIsvault class
|
2
|
+
# Copyright 2013, Nordstrom, Inc.
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Knife
|
20
|
+
class VaultIsvault < Knife
|
21
|
+
include Chef::Knife::VaultBase
|
22
|
+
|
23
|
+
banner "knife vault isvault VAULT ITEM (options)"
|
24
|
+
|
25
|
+
option :mode,
|
26
|
+
:short => '-M MODE',
|
27
|
+
:long => '--mode MODE',
|
28
|
+
:description => 'Chef mode to run in default - solo'
|
29
|
+
|
30
|
+
def run
|
31
|
+
vault = @name_args[0]
|
32
|
+
item = @name_args[1]
|
33
|
+
|
34
|
+
if vault && item
|
35
|
+
set_mode(config[:vault_mode])
|
36
|
+
exit ChefVault::Item.vault?(vault, item) ? 0 : 1
|
37
|
+
else
|
38
|
+
show_usage
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Description: Chef-Vault VaultItemtype class
|
2
|
+
# Copyright 2013, Nordstrom, Inc.
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Knife
|
20
|
+
class VaultItemtype < Knife
|
21
|
+
include Chef::Knife::VaultBase
|
22
|
+
|
23
|
+
banner "knife vault itemtype VAULT ITEM (options)"
|
24
|
+
|
25
|
+
option :mode,
|
26
|
+
:short => '-M MODE',
|
27
|
+
:long => '--mode MODE',
|
28
|
+
:description => 'Chef mode to run in default - solo'
|
29
|
+
|
30
|
+
def run
|
31
|
+
vault = @name_args[0]
|
32
|
+
item = @name_args[1]
|
33
|
+
|
34
|
+
if vault && item
|
35
|
+
set_mode(config[:vault_mode])
|
36
|
+
output ChefVault::Item.data_bag_item_type(vault, item)
|
37
|
+
else
|
38
|
+
show_usage
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Description: Chef-Vault
|
1
|
+
# Description: Chef-Vault VaultList class
|
2
2
|
# Copyright 2013, Nordstrom, Inc.
|
3
3
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -22,7 +22,13 @@ class Chef
|
|
22
22
|
|
23
23
|
banner "knife vault list (options)"
|
24
24
|
|
25
|
+
option :mode,
|
26
|
+
:short => '-M MODE',
|
27
|
+
:long => '--mode MODE',
|
28
|
+
:description => 'Chef mode to run in default - solo'
|
29
|
+
|
25
30
|
def run
|
31
|
+
set_mode(config[:vault_mode])
|
26
32
|
vaultbags = []
|
27
33
|
# iterate over all the data bags
|
28
34
|
bags = Chef::DataBag.list
|
@@ -31,23 +37,6 @@ class Chef
|
|
31
37
|
end
|
32
38
|
output vaultbags.join("\n")
|
33
39
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def bag_is_vault?(bagname)
|
38
|
-
bag = Chef::DataBag.load(bagname)
|
39
|
-
# vaults have at even number of keys >= 2
|
40
|
-
return false unless bag.keys.size >= 2 && 0 == bag.keys.size % 2
|
41
|
-
# partition into those that end in _keys
|
42
|
-
keylike, notkeylike = bag.keys.partition { |k| k =~ /_keys$/ }
|
43
|
-
# there must be an equal number of keyline and not-keylike items
|
44
|
-
return false unless keylike.size == notkeylike.size
|
45
|
-
# strip the _keys suffix and check if the sets match
|
46
|
-
keylike.map! { |k| k.gsub(/_keys$/, '') }
|
47
|
-
return false unless keylike.sort == notkeylike.sort
|
48
|
-
# it's (probably) a vault
|
49
|
-
true
|
50
|
-
end
|
51
40
|
end
|
52
41
|
end
|
53
42
|
end
|
@@ -22,27 +22,21 @@ class Chef
|
|
22
22
|
|
23
23
|
banner "knife vault refresh VAULT ITEM"
|
24
24
|
|
25
|
+
option :clean_unknown_clients,
|
26
|
+
:long => '--clean-unknown-clients',
|
27
|
+
:description => 'Remove unknown clients during refresh'
|
28
|
+
|
25
29
|
def run
|
26
30
|
vault = @name_args[0]
|
27
31
|
item = @name_args[1]
|
32
|
+
clean = config[:clean_unknown_clients]
|
28
33
|
|
29
34
|
set_mode(config[:vault_mode])
|
30
35
|
|
31
36
|
if vault && item
|
32
37
|
begin
|
33
38
|
vault_item = ChefVault::Item.load(vault, item)
|
34
|
-
|
35
|
-
|
36
|
-
unless search
|
37
|
-
raise ChefVault::Exceptions::SearchNotFound,
|
38
|
-
"#{vault}/#{item} does not have a stored search_query, "\
|
39
|
-
"probably because it was created with an older version "\
|
40
|
-
"of chef-vault. Use 'knife vault update' to update the "\
|
41
|
-
"databag with the search query."
|
42
|
-
end
|
43
|
-
|
44
|
-
vault_item.clients(search)
|
45
|
-
vault_item.save
|
39
|
+
vault_item.refresh(clean)
|
46
40
|
rescue ChefVault::Exceptions::KeysNotFound,
|
47
41
|
ChefVault::Exceptions::ItemNotFound
|
48
42
|
|
@@ -52,7 +52,7 @@ class Chef
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def rotate_vault_item_keys(vault, item, clean_unknown_clients)
|
55
|
-
puts "Rotating keys for: #{vault} #{item}"
|
55
|
+
$stdout.puts "Rotating keys for: #{vault} #{item}"
|
56
56
|
ChefVault::Item.load(vault, item).rotate_keys!(clean_unknown_clients)
|
57
57
|
end
|
58
58
|
end
|
@@ -20,7 +20,7 @@ class Chef
|
|
20
20
|
class VaultShow < Knife
|
21
21
|
include Chef::Knife::VaultBase
|
22
22
|
|
23
|
-
banner "knife vault show VAULT ITEM [VALUES] (options)"
|
23
|
+
banner "knife vault show VAULT [ITEM] [VALUES] (options)"
|
24
24
|
|
25
25
|
option :mode,
|
26
26
|
:short => '-M MODE',
|
@@ -40,6 +40,9 @@ class Chef
|
|
40
40
|
if vault && item
|
41
41
|
set_mode(config[:vault_mode])
|
42
42
|
print_values(vault, item, values)
|
43
|
+
elsif vault
|
44
|
+
set_mode(config[:vault_mode])
|
45
|
+
print_keys(vault)
|
43
46
|
else
|
44
47
|
show_usage
|
45
48
|
end
|
@@ -83,6 +86,17 @@ class Chef
|
|
83
86
|
end
|
84
87
|
output(output_data)
|
85
88
|
end
|
89
|
+
|
90
|
+
def print_keys(vault)
|
91
|
+
if bag_is_vault?(vault)
|
92
|
+
bag = Chef::DataBag.load(vault)
|
93
|
+
split_vault_keys(bag)[1].each do |item|
|
94
|
+
output item
|
95
|
+
end
|
96
|
+
else
|
97
|
+
output "data bag #{vault} is not a chef-vault"
|
98
|
+
end
|
99
|
+
end
|
86
100
|
end
|
87
101
|
end
|
88
102
|
end
|
@@ -6,6 +6,12 @@ RSpec.describe ChefVault::Certificate do
|
|
6
6
|
allow(ChefVault::Item).to receive(:load).with("foo", "bar"){ item }
|
7
7
|
allow(item).to receive(:[]).with("id"){ "bar" }
|
8
8
|
allow(item).to receive(:[]).with("contents"){ "baz" }
|
9
|
+
@orig_stdout = $stdout
|
10
|
+
$stdout = File.open(File::NULL, 'w')
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
$stdout = @orig_stdout
|
9
15
|
end
|
10
16
|
|
11
17
|
describe '#new' do
|
@@ -22,8 +28,9 @@ RSpec.describe ChefVault::Certificate do
|
|
22
28
|
|
23
29
|
describe 'decrypt_contents' do
|
24
30
|
it 'echoes warning' do
|
25
|
-
expect
|
26
|
-
|
31
|
+
expect { cert.decrypt_contents }
|
32
|
+
.to output("WARNING: This method is deprecated, please switch to item['value'] calls\n")
|
33
|
+
.to_stdout
|
27
34
|
end
|
28
35
|
|
29
36
|
it 'returns items contents' do
|
@@ -51,9 +51,84 @@ module BorkedNodeWithoutPublicKey
|
|
51
51
|
end
|
52
52
|
|
53
53
|
RSpec.describe ChefVault::Item do
|
54
|
+
before do
|
55
|
+
@orig_stdout = $stdout
|
56
|
+
$stdout = File.open(File::NULL, 'w')
|
57
|
+
end
|
58
|
+
|
59
|
+
after do
|
60
|
+
$stdout = @orig_stdout
|
61
|
+
end
|
62
|
+
|
54
63
|
subject(:item) { ChefVault::Item.new("foo", "bar") }
|
55
64
|
|
56
|
-
describe '
|
65
|
+
describe 'vault probe predicates' do
|
66
|
+
before do
|
67
|
+
# a normal data bag item
|
68
|
+
@db = { 'foo' => '...' }
|
69
|
+
@dbi = Chef::DataBagItem.new
|
70
|
+
@dbi.data_bag('normal')
|
71
|
+
@dbi.raw_data = { 'id' => 'foo', 'foo' => 'bar' }
|
72
|
+
allow(@db).to receive(:load).with('foo').and_return(@dbi)
|
73
|
+
allow(Chef::DataBag).to receive(:load).with('normal').and_return(@db)
|
74
|
+
allow(Chef::DataBagItem).to receive(:load).with('normal', 'foo').and_return(@dbi)
|
75
|
+
|
76
|
+
# an encrypted data bag item (non-vault)
|
77
|
+
@encdb = { 'foo' => '...' }
|
78
|
+
@encdbi = Chef::DataBagItem.new
|
79
|
+
@encdbi.data_bag('encrypted')
|
80
|
+
@encdbi.raw_data = {
|
81
|
+
'id' => 'foo',
|
82
|
+
'foo' => { 'encrypted_data' => '...' }
|
83
|
+
}
|
84
|
+
allow(@encdb).to receive(:load).with('foo').and_return(@encdbi)
|
85
|
+
allow(Chef::DataBag).to receive(:load).with('encrypted').and_return(@encdb)
|
86
|
+
allow(Chef::DataBagItem).to receive(:load).with('encrypted', 'foo').and_return(@encdbi)
|
87
|
+
|
88
|
+
# two items that make up a vault
|
89
|
+
@vaultdb = { 'foo' => '...', 'foo_keys' => '...' }
|
90
|
+
@vaultdbi = Chef::DataBagItem.new
|
91
|
+
@vaultdbi.data_bag('vault')
|
92
|
+
@vaultdbi.raw_data = {
|
93
|
+
'id' => 'foo',
|
94
|
+
'foo' => { 'encrypted_data' => '...' }
|
95
|
+
}
|
96
|
+
allow(@vaultdb).to receive(:load).with('foo').and_return(@vaultdbi)
|
97
|
+
@vaultdbki = Chef::DataBagItem.new
|
98
|
+
@vaultdbki.data_bag('vault')
|
99
|
+
@vaultdbki.raw_data = { 'id' => 'foo_keys' }
|
100
|
+
allow(@vaultdb).to receive(:load).with('foo_keys').and_return(@vaultdbki)
|
101
|
+
allow(Chef::DataBag).to receive(:load).with('vault').and_return(@vaultdb)
|
102
|
+
allow(Chef::DataBagItem).to receive(:load).with('vault', 'foo').and_return(@vaultdbi)
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '::vault?' do
|
106
|
+
it 'should detect a vault item' do
|
107
|
+
expect(ChefVault::Item.vault?('vault', 'foo')).to be_truthy
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should detect non-vault items' do
|
111
|
+
expect(ChefVault::Item.vault?('normal', 'foo')).not_to be_truthy
|
112
|
+
expect(ChefVault::Item.vault?('encrypted', 'foo')).not_to be_truthy
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '::data_bag_item_type' do
|
117
|
+
it 'should detect a vault item' do
|
118
|
+
expect(ChefVault::Item.data_bag_item_type('vault', 'foo')).to eq(:vault)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should detect an encrypted data bag item' do
|
122
|
+
expect(ChefVault::Item.data_bag_item_type('encrypted', 'foo')).to eq(:encrypted)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should detect a normal data bag item' do
|
126
|
+
expect(ChefVault::Item.data_bag_item_type('normal', 'foo')).to eq(:normal)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '::new' do
|
57
132
|
it { should be_an_instance_of ChefVault::Item }
|
58
133
|
|
59
134
|
its(:keys) { should be_an_instance_of ChefVault::ItemKeys }
|
@@ -65,14 +140,80 @@ RSpec.describe ChefVault::Item do
|
|
65
140
|
specify { expect(item.keys['id']).to eq 'bar_keys' }
|
66
141
|
|
67
142
|
specify { expect(item.keys.data_bag).to eq 'foo' }
|
143
|
+
|
144
|
+
it 'defaults the node name' do
|
145
|
+
item = ChefVault::Item.new('foo', 'bar')
|
146
|
+
expect(item.node_name).to eq(Chef::Config[:node_name])
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'defaults the client key path' do
|
150
|
+
item = ChefVault::Item.new('foo', 'bar')
|
151
|
+
expect(item.client_key_path).to eq(Chef::Config[:client_key])
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'allows for a node name override' do
|
155
|
+
item = ChefVault::Item.new('foo', 'bar', node_name: 'baz')
|
156
|
+
expect(item.node_name).to eq('baz')
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'allows for a client key path override' do
|
160
|
+
item = ChefVault::Item.new('foo', 'bar', client_key_path: '/foo/client.pem')
|
161
|
+
expect(item.client_key_path).to eq('/foo/client.pem')
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'allows for both node name and client key overrides' do
|
165
|
+
item = ChefVault::Item.new(
|
166
|
+
'foo', 'bar',
|
167
|
+
node_name: 'baz',
|
168
|
+
client_key_path: '/foo/client.pem'
|
169
|
+
)
|
170
|
+
expect(item.node_name).to eq('baz')
|
171
|
+
expect(item.client_key_path).to eq('/foo/client.pem')
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '::load' do
|
176
|
+
it 'allows for both node name and client key overrides' do
|
177
|
+
keys_db = Chef::DataBagItem.new
|
178
|
+
keys_db.raw_data = {
|
179
|
+
'id' => 'bar_keys',
|
180
|
+
'baz' => '...'
|
181
|
+
}
|
182
|
+
allow(ChefVault::ItemKeys)
|
183
|
+
.to receive(:load)
|
184
|
+
.and_return(keys_db)
|
185
|
+
fh = double 'private key handle'
|
186
|
+
allow(fh).to receive(:read).and_return('...')
|
187
|
+
allow(File).to receive(:open).and_return(fh)
|
188
|
+
privkey = double 'private key contents'
|
189
|
+
allow(privkey).to receive(:private_decrypt).and_return('sekrit')
|
190
|
+
allow(OpenSSL::PKey::RSA).to receive(:new).and_return(privkey)
|
191
|
+
allow(Chef::EncryptedDataBagItem).to receive(:load).and_return(
|
192
|
+
'id' => 'bar',
|
193
|
+
'password' => '12345'
|
194
|
+
)
|
195
|
+
item = ChefVault::Item.load(
|
196
|
+
'foo', 'bar',
|
197
|
+
node_name: 'baz',
|
198
|
+
client_key_path: '/foo/client.pem'
|
199
|
+
)
|
200
|
+
expect(item.node_name).to eq('baz')
|
201
|
+
expect(item.client_key_path).to eq('/foo/client.pem')
|
202
|
+
end
|
68
203
|
end
|
69
204
|
|
70
205
|
describe '#save' do
|
71
206
|
context 'when item["id"] is bar.bar' do
|
72
207
|
let(:item) { ChefVault::Item.new("foo", "bar.bar") }
|
73
|
-
|
74
208
|
specify { expect { item.save }.to raise_error }
|
75
209
|
end
|
210
|
+
|
211
|
+
it 'should validate that the id of the vault matches the id of the keys data bag' do
|
212
|
+
item = ChefVault::Item.new('foo', 'bar')
|
213
|
+
item['id'] = 'baz'
|
214
|
+
item.keys['clients'] = %w(admin)
|
215
|
+
expect { item.save }.to raise_error(ChefVault::Exceptions::IdMismatch)
|
216
|
+
end
|
76
217
|
end
|
77
218
|
|
78
219
|
describe '#clients' do
|
@@ -87,7 +228,19 @@ RSpec.describe ChefVault::Item do
|
|
87
228
|
it 'should emit a warning if search returns a node without a public key' do
|
88
229
|
# it should however emit a warning that you have a borked node
|
89
230
|
expect { @vaultitem.clients('*:*') }
|
90
|
-
.to output(/node 'bar' has no private key; skipping/).
|
231
|
+
.to output(/node 'bar' has no private key; skipping/).to_stdout
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should accept a client object and not perform a search' do
|
235
|
+
client = Chef::ApiClient.new
|
236
|
+
client.name 'foo'
|
237
|
+
privkey = OpenSSL::PKey::RSA.new(1024)
|
238
|
+
pubkey = privkey.public_key
|
239
|
+
client.public_key(pubkey.to_pem)
|
240
|
+
expect(Chef::Search::Query).not_to receive(:new)
|
241
|
+
expect(ChefVault::ChefPatch::User).not_to receive(:load)
|
242
|
+
@vaultitem.clients(client)
|
243
|
+
expect(@vaultitem.clients).to include('foo')
|
91
244
|
end
|
92
245
|
end
|
93
246
|
|
@@ -99,4 +252,12 @@ RSpec.describe ChefVault::Item do
|
|
99
252
|
.to raise_error(ChefVault::Exceptions::AdminNotFound)
|
100
253
|
end
|
101
254
|
end
|
255
|
+
|
256
|
+
describe '#raw_keys' do
|
257
|
+
it 'should return the keys of the underlying data bag item' do
|
258
|
+
item = ChefVault::Item.new('foo', 'bar')
|
259
|
+
item['foo'] = 'bar'
|
260
|
+
expect(item.raw_keys).to eq(%w(id foo))
|
261
|
+
end
|
262
|
+
end
|
102
263
|
end
|