chef-vault 2.9.2 → 3.0.0.rc1
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/.travis.yml +2 -11
- data/Changelog.md +1 -6
- data/Gemfile +4 -5
- data/KNIFE_EXAMPLES.md +66 -14
- data/LICENSE +201 -177
- data/README.md +74 -4
- data/Rakefile +1 -1
- data/bin/chef-vault +3 -2
- data/chef-vault.gemspec +13 -15
- data/features/clean.feature +0 -1
- data/features/clean_on_refresh.feature +0 -1
- data/features/clean_unknown_clients.feature +0 -1
- data/features/detect_and_warn_v1_vault.feature +0 -1
- data/features/isvault.feature +0 -1
- data/features/itemtype.feature +0 -1
- data/features/vault_create.feature +1 -2
- data/features/vault_list.feature +0 -1
- data/features/vault_show.feature +0 -1
- data/features/vault_show_vaultname.feature +0 -1
- data/features/vault_update.feature +0 -1
- data/features/verify_id_matches.feature +0 -1
- data/features/wrong_private_key.feature +0 -1
- data/hooks/pre-commit +43 -0
- data/lib/chef-vault.rb +10 -2
- data/lib/chef-vault/actor.rb +149 -0
- data/lib/chef-vault/certificate.rb +1 -1
- data/lib/chef-vault/chef_api.rb +39 -0
- data/lib/chef-vault/item.rb +57 -71
- data/lib/chef-vault/item_keys.rb +14 -9
- data/lib/chef-vault/user.rb +1 -1
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef/knife/vault_base.rb +5 -2
- data/lib/chef/knife/{encrypt_delete.rb → vault_clients.rb} +6 -12
- data/lib/chef/knife/vault_create.rb +9 -1
- data/lib/chef/knife/vault_remove.rb +9 -1
- data/lib/chef/knife/vault_rotate_all_keys.rb +1 -1
- data/lib/chef/knife/vault_show.rb +4 -4
- data/lib/chef/knife/vault_update.rb +13 -5
- data/spec/chef-vault/actor_spec.rb +247 -0
- data/spec/chef-vault/certificate_spec.rb +2 -9
- data/spec/chef-vault/chef_api_spec.rb +39 -0
- data/spec/chef-vault/item_keys_spec.rb +52 -0
- data/spec/chef-vault/item_spec.rb +139 -85
- data/spec/chef-vault/user_spec.rb +2 -9
- data/spec/spec_helper.rb +1 -0
- metadata +36 -42
- data/CONTRIBUTING.md +0 -118
- data/lib/chef-vault/chef_patch/api_client.rb +0 -45
- data/lib/chef-vault/chef_patch/user.rb +0 -33
- data/lib/chef/knife/decrypt.rb +0 -32
- data/lib/chef/knife/encrypt_create.rb +0 -51
- data/lib/chef/knife/encrypt_remove.rb +0 -42
- data/lib/chef/knife/encrypt_rotate_keys.rb +0 -32
- data/lib/chef/knife/encrypt_update.rb +0 -51
- data/lib/chef/knife/mixin/compat.rb +0 -33
- data/lib/chef/knife/vault_decrypt.rb +0 -58
@@ -14,11 +14,13 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
16
|
require "chef/knife/vault_base"
|
17
|
+
require "chef/knife/vault_clients"
|
17
18
|
|
18
19
|
class Chef
|
19
20
|
class Knife
|
20
21
|
class VaultRemove < Knife
|
21
22
|
include Chef::Knife::VaultBase
|
23
|
+
include Chef::Knife::VaultClients
|
22
24
|
|
23
25
|
banner "knife vault remove VAULT ITEM VALUES (options)"
|
24
26
|
|
@@ -27,6 +29,11 @@ class Chef
|
|
27
29
|
:long => "--search SEARCH",
|
28
30
|
:description => "Chef SOLR search for clients"
|
29
31
|
|
32
|
+
option :clients,
|
33
|
+
:short => "-C CLIENTS",
|
34
|
+
:long => "--clients CLIENTS",
|
35
|
+
:description => "Chef clients to be added as clients"
|
36
|
+
|
30
37
|
option :admins,
|
31
38
|
:short => "-A ADMINS",
|
32
39
|
:long => "--admins ADMINS",
|
@@ -47,7 +54,7 @@ class Chef
|
|
47
54
|
|
48
55
|
set_mode(config[:vault_mode])
|
49
56
|
|
50
|
-
if vault && item && ((values || json_file) || (search || admins))
|
57
|
+
if vault && item && ((values || json_file) || (search || clients || admins))
|
51
58
|
begin
|
52
59
|
vault_item = ChefVault::Item.load(vault, item)
|
53
60
|
remove_items = []
|
@@ -69,6 +76,7 @@ class Chef
|
|
69
76
|
end
|
70
77
|
|
71
78
|
vault_item.clients(search, :delete) if search
|
79
|
+
vault_item.clients(clients, :delete) if clients
|
72
80
|
vault_item.admins(admins, :delete) if admins
|
73
81
|
|
74
82
|
vault_item.rotate_keys!(clean_unknown_clients)
|
@@ -52,7 +52,7 @@ class Chef
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def rotate_vault_item_keys(vault, item, clean_unknown_clients)
|
55
|
-
|
55
|
+
ui.info "Rotating keys for: #{vault} #{item}"
|
56
56
|
ChefVault::Item.load(vault, item).rotate_keys!(clean_unknown_clients)
|
57
57
|
end
|
58
58
|
end
|
@@ -58,13 +58,13 @@ class Chef
|
|
58
58
|
when "search"
|
59
59
|
extra_data["search_query"] = vault_item.search
|
60
60
|
when "admins"
|
61
|
-
extra_data["admins"] = vault_item.
|
61
|
+
extra_data["admins"] = vault_item.get_admins
|
62
62
|
when "clients"
|
63
|
-
extra_data["clients"] = vault_item.
|
63
|
+
extra_data["clients"] = vault_item.get_clients
|
64
64
|
when "all"
|
65
65
|
extra_data["search_query"] = vault_item.search
|
66
|
-
extra_data["admins"] = vault_item.
|
67
|
-
extra_data["clients"] = vault_item.
|
66
|
+
extra_data["admins"] = vault_item.get_admins
|
67
|
+
extra_data["clients"] = vault_item.get_clients
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -15,12 +15,14 @@
|
|
15
15
|
|
16
16
|
require "chef/knife/vault_base"
|
17
17
|
require "chef/knife/vault_admins"
|
18
|
+
require "chef/knife/vault_clients"
|
18
19
|
|
19
20
|
class Chef
|
20
21
|
class Knife
|
21
22
|
class VaultUpdate < Knife
|
22
23
|
include Chef::Knife::VaultBase
|
23
24
|
include Chef::Knife::VaultAdmins
|
25
|
+
include Chef::Knife::VaultClients
|
24
26
|
|
25
27
|
banner "knife vault update VAULT ITEM VALUES (options)"
|
26
28
|
|
@@ -29,6 +31,11 @@ class Chef
|
|
29
31
|
:long => "--search SEARCH",
|
30
32
|
:description => "Chef SOLR search for clients"
|
31
33
|
|
34
|
+
option :clients,
|
35
|
+
:short => "-C CLIENTS",
|
36
|
+
:long => "--clients CLIENTS",
|
37
|
+
:description => "Chef clients to be added as clients"
|
38
|
+
|
32
39
|
option :admins,
|
33
40
|
:short => "-A ADMINS",
|
34
41
|
:long => "--admins ADMINS",
|
@@ -58,21 +65,22 @@ class Chef
|
|
58
65
|
|
59
66
|
set_mode(config[:vault_mode])
|
60
67
|
|
61
|
-
if vault && item && ((values || json_file || file) || (search || admins))
|
68
|
+
if vault && item && ((values || json_file || file) || (search || clients || admins))
|
62
69
|
begin
|
63
70
|
vault_item = ChefVault::Item.load(vault, item)
|
64
71
|
|
65
72
|
# Keys management first
|
66
73
|
if clean
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
vault_item.
|
74
|
+
vault_clients = vault_item.get_clients.clone().sort()
|
75
|
+
vault_clients.each do |client|
|
76
|
+
ui.info "Deleting #{client}"
|
77
|
+
vault_item.delete_client(client)
|
71
78
|
end
|
72
79
|
end
|
73
80
|
|
74
81
|
vault_item.search(search) if search
|
75
82
|
vault_item.clients(search) if search
|
83
|
+
vault_item.clients(clients) if clients
|
76
84
|
vault_item.admins(admins) if admins
|
77
85
|
|
78
86
|
# Save only the keys if no value is provided, otherwise save the item
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe ChefVault::Actor do
|
4
|
+
let(:actor_name) { "actor" }
|
5
|
+
let(:public_key_string) do
|
6
|
+
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:key_response) do
|
10
|
+
{
|
11
|
+
"name" => "default",
|
12
|
+
"public_key" => "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n",
|
13
|
+
"expiration_date" => "infinity",
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:http_response_code) do
|
18
|
+
"404"
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:http_error) do
|
22
|
+
http_response = double("http error")
|
23
|
+
allow(http_response).to receive(:code).and_return(http_response_code)
|
24
|
+
Net::HTTPServerException.new("http error message", http_response)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:api) { double("api") }
|
28
|
+
|
29
|
+
subject(:chef_key) { described_class.new(actor_type, actor_name) }
|
30
|
+
|
31
|
+
describe "#new" do
|
32
|
+
context "when something besides 'clients' or 'users' is passed" do
|
33
|
+
let(:actor_type) { "charmander" }
|
34
|
+
it "throws an error" do
|
35
|
+
expect { described_class.new("charmander", actor_name) }.to raise_error(RuntimeError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when 'clients' is passed" do
|
40
|
+
it "requests a client key" do
|
41
|
+
expect_any_instance_of(described_class).to receive(:get_client_key)
|
42
|
+
described_class.new("clients", actor_name).key
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when 'admins' is passed" do
|
47
|
+
it "requests a admin key" do
|
48
|
+
expect_any_instance_of(described_class).to receive(:get_admin_key)
|
49
|
+
described_class.new("admins", actor_name).key
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
shared_examples_for "get_key_handling" do
|
55
|
+
context "when the default key exists for the requested client" do
|
56
|
+
it "sets up a valid key" do
|
57
|
+
expect(chef_key).to receive(:get_key).with(request_actor_type).and_return(public_key_string)
|
58
|
+
expect(chef_key.send(method)).to eq(public_key_string)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when get_key returns an http error" do
|
63
|
+
before do
|
64
|
+
allow(chef_key).to receive(:get_key).with(request_actor_type).and_raise(http_error)
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when the error code is not 404 or 403" do
|
68
|
+
let(:http_response_code) { "500" }
|
69
|
+
|
70
|
+
it "raises the original error" do
|
71
|
+
expect { chef_key.send(method) }.to raise_error(http_error)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when the error code is 403" do
|
76
|
+
let(:http_response_code) { "403" }
|
77
|
+
|
78
|
+
it "prints information for the user to resolve the issue and raises the original error" do
|
79
|
+
expect(chef_key).to receive(:print_forbidden_error)
|
80
|
+
expect { chef_key.send(method) }.to raise_error(http_error)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#get_client_key" do
|
87
|
+
let(:request_actor_type) { "clients" }
|
88
|
+
let(:actor_type) { "clients" }
|
89
|
+
let(:method) { :get_client_key }
|
90
|
+
|
91
|
+
it_should_behave_like "get_key_handling"
|
92
|
+
|
93
|
+
context "when get_key returns an http error" do
|
94
|
+
before do
|
95
|
+
allow(chef_key).to receive(:get_key).with(actor_type).and_raise(http_error)
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when the error code is 404" do
|
99
|
+
let(:http_response_code) { "404" }
|
100
|
+
|
101
|
+
it "raises ChefVault::Exceptions::ClientNotFound" do
|
102
|
+
expect { chef_key.get_client_key }.to raise_error(ChefVault::Exceptions::ClientNotFound)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end # get_client_key
|
107
|
+
|
108
|
+
describe "#get_admin_key" do
|
109
|
+
let(:request_actor_type) { "users" }
|
110
|
+
let(:actor_type) { "admins" }
|
111
|
+
let(:method) { :get_admin_key }
|
112
|
+
|
113
|
+
it_should_behave_like "get_key_handling"
|
114
|
+
|
115
|
+
context "when the first get_key for users returns an http error" do
|
116
|
+
before do
|
117
|
+
allow(chef_key).to receive(:get_key).with(request_actor_type).and_raise(http_error)
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when the error code from the users get is a 404" do
|
121
|
+
let(:http_response_code) { "404" }
|
122
|
+
|
123
|
+
context "when the second get_key for clients returns an http error" do
|
124
|
+
|
125
|
+
let(:http_error_2) do
|
126
|
+
http_response = double("http error")
|
127
|
+
allow(http_response).to receive(:code).and_return(http_response_code_2)
|
128
|
+
Net::HTTPServerException.new("http error message", http_response)
|
129
|
+
end
|
130
|
+
|
131
|
+
before do
|
132
|
+
allow(chef_key).to receive(:get_key).with("clients").and_raise(http_error_2)
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when it is a 404" do
|
136
|
+
let(:http_response_code_2) { "404" }
|
137
|
+
|
138
|
+
it "rasies ChefVault::Exceptions::AdminNotFound" do
|
139
|
+
expect { chef_key.get_admin_key }.to raise_error(ChefVault::Exceptions::AdminNotFound)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when it is a 403" do
|
144
|
+
let(:http_response_code_2) { "403" }
|
145
|
+
|
146
|
+
it "raises the original error" do
|
147
|
+
expect { chef_key.get_admin_key }.to raise_error(http_error_2)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "when it is not a 404" do
|
152
|
+
let(:http_response_code_2) { "500" }
|
153
|
+
|
154
|
+
it "raises the original error" do
|
155
|
+
expect { chef_key.get_admin_key }.to raise_error(http_error_2)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end # when the second get_key for clients returns an http error
|
159
|
+
|
160
|
+
context "when the second get_key for clients exists with the same name as the admin requested" do
|
161
|
+
it "strangely returns the client key as an admin key" do
|
162
|
+
expect(chef_key).to receive(:get_key).with(request_actor_type).and_return(public_key_string)
|
163
|
+
expect(chef_key.send(method)).to eq(public_key_string)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end # when the first get_key for users returns an http erro
|
167
|
+
end
|
168
|
+
end # get_admin_key
|
169
|
+
|
170
|
+
describe "#get_key" do
|
171
|
+
|
172
|
+
shared_examples_for "a properly retrieved and error handled key fetch" do
|
173
|
+
# mock out the API
|
174
|
+
before do
|
175
|
+
allow(chef_key).to receive(:api).and_return(api)
|
176
|
+
[:rest_v0, :rest_v1, :org_scoped_rest_v0, :org_scoped_rest_v1].each do |method|
|
177
|
+
allow(api).to receive(method)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "when keys/default returns 200 for org scoped endpoint" do
|
182
|
+
before do
|
183
|
+
allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_return(key_response)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "returns the public_key" do
|
187
|
+
expect(chef_key.get_key(request_actor_type)).to eql(public_key_string)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "hits the proper endpoint" do
|
191
|
+
expect(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default")
|
192
|
+
chef_key.get_key(request_actor_type)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when a 500 is returned" do
|
197
|
+
let(:http_response_code) { "500" }
|
198
|
+
before do
|
199
|
+
allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_raise(http_error)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "raises the http error" do
|
203
|
+
expect { chef_key.get_key(request_actor_type) }.to raise_error(http_error)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "when keys/default returns 404" do
|
208
|
+
let(:http_response_code) { "404" }
|
209
|
+
let(:chef_object) { double("chef object") }
|
210
|
+
|
211
|
+
before do
|
212
|
+
allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_raise(http_error)
|
213
|
+
allow(chef_object_type).to receive(:load).with(actor_name).and_return(chef_object)
|
214
|
+
allow(chef_object).to receive(:public_key).and_return(public_key_string)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "tries to load the object via Chef::<object>_v1" do
|
218
|
+
expect(chef_object_type).to receive(:load).with(actor_name)
|
219
|
+
chef_key.get_key(request_actor_type)
|
220
|
+
end
|
221
|
+
|
222
|
+
context "when the Chef::<object>_v1 object loads properly" do
|
223
|
+
it "returns the public key" do
|
224
|
+
expect(chef_key.get_key(request_actor_type)).to eql(public_key_string)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end # shared_examples_for
|
229
|
+
|
230
|
+
context "when a client is passed" do
|
231
|
+
let(:request_actor_type) { "clients" }
|
232
|
+
let(:actor_type) { "clients" }
|
233
|
+
let(:chef_object_type) { Chef::ApiClient }
|
234
|
+
|
235
|
+
it_behaves_like "a properly retrieved and error handled key fetch"
|
236
|
+
end
|
237
|
+
|
238
|
+
context "when an admin is passed" do
|
239
|
+
let(:request_actor_type) { "users" }
|
240
|
+
let(:actor_type) { "admins" }
|
241
|
+
let(:chef_object_type) { Chef::User }
|
242
|
+
|
243
|
+
it_behaves_like "a properly retrieved and error handled key fetch"
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
@@ -6,12 +6,6 @@ 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
|
15
9
|
end
|
16
10
|
|
17
11
|
describe "#new" do
|
@@ -30,9 +24,8 @@ RSpec.describe ChefVault::Certificate do
|
|
30
24
|
|
31
25
|
describe "decrypt_contents" do
|
32
26
|
it "echoes warning" do
|
33
|
-
expect
|
34
|
-
|
35
|
-
.to_stdout
|
27
|
+
expect(ChefVault::Log).to receive(:warn).with("This method is deprecated, please switch to item['value'] calls")
|
28
|
+
cert.decrypt_contents
|
36
29
|
end
|
37
30
|
|
38
31
|
it "returns items contents" do
|
@@ -0,0 +1,39 @@
|
|
1
|
+
RSpec.describe ChefVault::ChefApi do
|
2
|
+
let(:root_url) { "https://localhost" }
|
3
|
+
let(:scoped_url) { "https://localhost/organizations/fakeorg" }
|
4
|
+
let(:api_v0_hash) { { :api_version => "0" } }
|
5
|
+
let(:api_v1_hash) { { :api_version => "1" } }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Chef::Config[:chef_server_root] = root_url
|
9
|
+
Chef::Config[:chef_server_url] = scoped_url
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#rest_v0" do
|
13
|
+
it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
|
14
|
+
expect(Chef::ServerAPI).to receive(:new).with(root_url, api_v0_hash)
|
15
|
+
subject.rest_v0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#rest_v1" do
|
20
|
+
it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
|
21
|
+
expect(Chef::ServerAPI).to receive(:new).with(root_url, api_v1_hash)
|
22
|
+
subject.rest_v1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#org_scoped_rest_v0" do
|
27
|
+
it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
|
28
|
+
expect(Chef::ServerAPI).to receive(:new).with(scoped_url, api_v0_hash)
|
29
|
+
subject.org_scoped_rest_v0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#org_scoped_rest_v1" do
|
34
|
+
it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
|
35
|
+
expect(Chef::ServerAPI).to receive(:new).with(scoped_url, api_v1_hash)
|
36
|
+
subject.org_scoped_rest_v1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
RSpec.describe ChefVault::ItemKeys do
|
2
2
|
describe "#new" do
|
3
3
|
let(:keys) { ChefVault::ItemKeys.new("foo", "bar") }
|
4
|
+
let(:shared_secret) { "super_secret" }
|
4
5
|
|
5
6
|
it "'foo' is assigned to @data_bag" do
|
6
7
|
expect(keys.data_bag).to eq "foo"
|
@@ -18,6 +19,57 @@ RSpec.describe ChefVault::ItemKeys do
|
|
18
19
|
expect(keys["admins"]).to eq []
|
19
20
|
end
|
20
21
|
|
22
|
+
describe "key mgmt operations" do
|
23
|
+
let(:public_key_string) do
|
24
|
+
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
shared_examples_for "proper key management" do
|
28
|
+
let(:chef_key) { ChefVault::Actor.new(type, name) }
|
29
|
+
before do
|
30
|
+
allow(chef_key).to receive(:key) { public_key_string }
|
31
|
+
keys.add(chef_key, shared_secret)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#add" do
|
35
|
+
after do
|
36
|
+
keys.delete(chef_key)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "stores the encoded key in the data bag item under the actor's name and the name in the raw data" do
|
40
|
+
expect(described_class).to receive(:encode_key).with(public_key_string, shared_secret).and_return("encrypted_result")
|
41
|
+
keys.add(chef_key, shared_secret)
|
42
|
+
expect(keys[name]).to eq("encrypted_result")
|
43
|
+
expect(keys[type].include?(name)).to eq(true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#delete" do
|
48
|
+
before do
|
49
|
+
keys.add(chef_key, shared_secret)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "removes the actor's name from the data bag and from the array for the actor's type" do
|
53
|
+
keys.delete(chef_key)
|
54
|
+
expect(keys.has_key?(chef_key.name)).to eq(false)
|
55
|
+
expect(keys[type].include?(name)).to eq(false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when a client is added" do
|
61
|
+
let(:name) { "client_name" }
|
62
|
+
let(:type) { "clients" }
|
63
|
+
it_should_behave_like "proper key management"
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when a admin is added" do
|
67
|
+
let(:name) { "admin_name" }
|
68
|
+
let(:type) { "admins" }
|
69
|
+
it_should_behave_like "proper key management"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
21
73
|
context "when running with chef-solo" do
|
22
74
|
describe "#find_solo_path" do
|
23
75
|
context "when data_bag_path is an array" do
|