chef-vault 2.9.2 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -11
  3. data/Changelog.md +1 -6
  4. data/Gemfile +4 -5
  5. data/KNIFE_EXAMPLES.md +66 -14
  6. data/LICENSE +201 -177
  7. data/README.md +74 -4
  8. data/Rakefile +1 -1
  9. data/bin/chef-vault +3 -2
  10. data/chef-vault.gemspec +13 -15
  11. data/features/clean.feature +0 -1
  12. data/features/clean_on_refresh.feature +0 -1
  13. data/features/clean_unknown_clients.feature +0 -1
  14. data/features/detect_and_warn_v1_vault.feature +0 -1
  15. data/features/isvault.feature +0 -1
  16. data/features/itemtype.feature +0 -1
  17. data/features/vault_create.feature +1 -2
  18. data/features/vault_list.feature +0 -1
  19. data/features/vault_show.feature +0 -1
  20. data/features/vault_show_vaultname.feature +0 -1
  21. data/features/vault_update.feature +0 -1
  22. data/features/verify_id_matches.feature +0 -1
  23. data/features/wrong_private_key.feature +0 -1
  24. data/hooks/pre-commit +43 -0
  25. data/lib/chef-vault.rb +10 -2
  26. data/lib/chef-vault/actor.rb +149 -0
  27. data/lib/chef-vault/certificate.rb +1 -1
  28. data/lib/chef-vault/chef_api.rb +39 -0
  29. data/lib/chef-vault/item.rb +57 -71
  30. data/lib/chef-vault/item_keys.rb +14 -9
  31. data/lib/chef-vault/user.rb +1 -1
  32. data/lib/chef-vault/version.rb +1 -1
  33. data/lib/chef/knife/vault_base.rb +5 -2
  34. data/lib/chef/knife/{encrypt_delete.rb → vault_clients.rb} +6 -12
  35. data/lib/chef/knife/vault_create.rb +9 -1
  36. data/lib/chef/knife/vault_remove.rb +9 -1
  37. data/lib/chef/knife/vault_rotate_all_keys.rb +1 -1
  38. data/lib/chef/knife/vault_show.rb +4 -4
  39. data/lib/chef/knife/vault_update.rb +13 -5
  40. data/spec/chef-vault/actor_spec.rb +247 -0
  41. data/spec/chef-vault/certificate_spec.rb +2 -9
  42. data/spec/chef-vault/chef_api_spec.rb +39 -0
  43. data/spec/chef-vault/item_keys_spec.rb +52 -0
  44. data/spec/chef-vault/item_spec.rb +139 -85
  45. data/spec/chef-vault/user_spec.rb +2 -9
  46. data/spec/spec_helper.rb +1 -0
  47. metadata +36 -42
  48. data/CONTRIBUTING.md +0 -118
  49. data/lib/chef-vault/chef_patch/api_client.rb +0 -45
  50. data/lib/chef-vault/chef_patch/user.rb +0 -33
  51. data/lib/chef/knife/decrypt.rb +0 -32
  52. data/lib/chef/knife/encrypt_create.rb +0 -51
  53. data/lib/chef/knife/encrypt_remove.rb +0 -42
  54. data/lib/chef/knife/encrypt_rotate_keys.rb +0 -32
  55. data/lib/chef/knife/encrypt_update.rb +0 -51
  56. data/lib/chef/knife/mixin/compat.rb +0 -33
  57. data/lib/chef/knife/vault_decrypt.rb +0 -58
@@ -1,67 +1,12 @@
1
1
  require "openssl"
2
- require "rspec/core/shared_context"
3
-
4
- # it turns out that simulating a node that doesn't have a public
5
- # key is not a simple thing
6
- module BorkedNodeWithoutPublicKey
7
- extend RSpec::Core::SharedContext
8
-
9
- before do
10
- # a node 'foo' with a public key
11
- node_foo = double("chef node foo")
12
- allow(node_foo).to receive(:name).and_return("foo")
13
- client_foo = double("chef apiclient foo")
14
- allow(client_foo).to receive(:name).and_return("foo")
15
- privkey = OpenSSL::PKey::RSA.new(1024)
16
- pubkey = privkey.public_key
17
- allow(client_foo).to receive(:public_key).and_return(pubkey.to_pem)
18
- # a node 'bar' without a public key
19
- node_bar = double("chef node bar")
20
- allow(node_bar).to receive(:name).and_return("bar")
21
- # fake out searches to return both of our nodes
22
- query_result = double("chef search results")
23
- allow(query_result)
24
- .to receive(:search)
25
- .with(Symbol, String)
26
- .and_yield(node_foo).and_yield(node_bar)
27
- allow(Chef::Search::Query)
28
- .to receive(:new)
29
- .and_return(query_result)
30
- # create a new vault item
31
- @vaultitem = ChefVault::Item.new("foo", "bar")
32
- @vaultitem["foo"] = "bar"
33
- # make the vault item return the apiclient for foo but raise for bar
34
- allow(@vaultitem).to receive(:load_client).with("foo")
35
- .and_return(client_foo)
36
- allow(@vaultitem).to receive(:load_client).with("bar")
37
- .and_raise(ChefVault::Exceptions::ClientNotFound)
38
- # make the vault item fall back to 'load-admin-as-client' behaviour
39
- http_response = double("http not found")
40
- allow(http_response).to receive(:code).and_return("404")
41
- http_not_found = Net::HTTPServerException.new("not found", http_response)
42
- allow(ChefVault::ChefPatch::User)
43
- .to receive(:load)
44
- .with("foo")
45
- .and_return(client_foo)
46
- allow(ChefVault::ChefPatch::User)
47
- .to receive(:load)
48
- .with("bar")
49
- .and_raise(http_not_found)
50
- end
51
- end
52
2
 
53
3
  RSpec.describe ChefVault::Item do
54
- before do
55
- @orig_stdout = $stdout
56
- $stdout = File.open(File::NULL, "w")
57
- end
4
+ subject(:item) { ChefVault::Item.new("foo", "bar") }
58
5
 
59
- after do
60
- $stdout = @orig_stdout
6
+ before do
7
+ item["foo"] = "bar"
61
8
  end
62
9
 
63
- subject(:item) { ChefVault::Item.new("foo", "bar") }
64
-
65
10
  describe "vault probe predicates" do
66
11
  before do
67
12
  # a normal data bag item
@@ -214,8 +159,7 @@ RSpec.describe ChefVault::Item do
214
159
  context 'when item["id"] is bar.bar' do
215
160
  let(:item) { ChefVault::Item.new("foo", "bar.bar") }
216
161
  it "raises an error on save with an invalid item['id']" do
217
- expect { item.save }.to raise_error
218
-
162
+ expect { item.save }.to raise_error(RuntimeError)
219
163
  end
220
164
  end
221
165
 
@@ -245,10 +189,10 @@ RSpec.describe ChefVault::Item do
245
189
  allow(Chef::Search::Query).to receive(:new).and_return(query)
246
190
  allow(query).to receive(:search).and_yield(node)
247
191
 
248
- client = double("client",
249
- name: "testclient",
250
- public_key: OpenSSL::PKey::RSA.new(1024).public_key)
251
- allow(ChefVault::ChefPatch::ApiClient).to receive(:load).and_return(client)
192
+ client_key = double("client_key",
193
+ name: "testnode",
194
+ public_key: OpenSSL::PKey::RSA.new(1024).public_key)
195
+ allow(item).to receive(:load_actor).with("testnode", "clients").and_return(client_key)
252
196
 
253
197
  expect(item).not_to receive(:save)
254
198
  expect(keys).to receive(:save)
@@ -257,38 +201,148 @@ RSpec.describe ChefVault::Item do
257
201
  end
258
202
 
259
203
  describe "#clients" do
260
- include BorkedNodeWithoutPublicKey
204
+ context "when search returns a node with a valid client backing it and one without a valid client" do
205
+ let(:node_with_valid_client) { double("chef node valid") }
206
+ let(:node_without_valid_client) { double("chef node no valid client") }
207
+ let(:query_result) { double("chef search results") }
208
+ let(:client_key) { double("chef key") }
209
+
210
+ before do
211
+ # node with valid client proper loads client key
212
+ allow(node_with_valid_client).to receive(:name).and_return("foo")
213
+ allow(item).to receive(:load_actor).with("foo", "clients").and_return(client_key)
214
+ privkey = OpenSSL::PKey::RSA.new(1024)
215
+ pubkey = privkey.public_key
216
+ allow(client_key).to receive(:key).and_return(pubkey.to_pem)
217
+ allow(client_key).to receive(:name).and_return("foo")
218
+ allow(client_key).to receive(:type).and_return("clients")
219
+
220
+ # node without client throws relevant error on key load
221
+ allow(node_without_valid_client).to receive(:name).and_return("bar")
222
+ allow(item).to receive(:load_actor).with("bar", "clients").and_raise(ChefVault::Exceptions::ClientNotFound)
223
+
224
+ allow(query_result)
225
+ .to receive(:search)
226
+ .with(Symbol, String)
227
+ .and_yield(node_with_valid_client).and_yield(node_without_valid_client)
228
+ allow(Chef::Search::Query)
229
+ .to receive(:new)
230
+ .and_return(query_result)
231
+ end
232
+
233
+ it "should not blow up when search returns a node without a public key" do
234
+ # try to set clients when we know a node is missing a public key
235
+ # this should not die as of v2.4.1
236
+ expect { item.clients("*:*") }.not_to raise_error
237
+ end
261
238
 
262
- it "should not blow up when search returns a node without a public key" do
263
- # try to set clients when we know a node is missing a public key
264
- # this should not die as of v2.4.1
265
- expect { @vaultitem.clients("*:*") }.not_to raise_error
239
+ it "should emit a warning if search returns a node without a public key" do
240
+ # it should however emit a warning that you have a borked node
241
+ expect(ChefVault::Log).to receive(:warn).with(/node 'bar' has no private key; skipping/)
242
+ item.clients("*:*")
243
+ end
266
244
  end
267
245
 
268
- it "should emit a warning if search returns a node without a public key" do
269
- # it should however emit a warning that you have a borked node
270
- expect { @vaultitem.clients("*:*") }
271
- .to output(/node 'bar' has no private key; skipping/).to_stdout
246
+ context "when a Chef::ApiClient is passed" do
247
+ let(:client) { Chef::ApiClient.new }
248
+ let(:client_name) { "foo" }
249
+ let(:client_key) { double("chef key") }
250
+
251
+ before do
252
+ client.name client_name
253
+ privkey = OpenSSL::PKey::RSA.new(1024)
254
+ pubkey = privkey.public_key
255
+ allow(item).to receive(:load_actor).with(client_name, "clients").and_return(client_key)
256
+ allow(client_key).to receive(:key).and_return(pubkey.to_pem)
257
+ allow(client_key).to receive(:name).and_return(client_name)
258
+ allow(client_key).to receive(:type).and_return("clients")
259
+ end
260
+
261
+ context "when no action is passed" do
262
+ it "default to add and properly add the client" do
263
+ item.clients(client)
264
+ expect(item.get_clients).to include(client_name)
265
+ end
266
+
267
+ it "does not perform a query" do
268
+ expect(Chef::Search::Query).not_to receive(:new)
269
+ item.clients(client)
270
+ end
271
+ end
272
+
273
+ context "when the delete action is passed on an existing client" do
274
+ before do
275
+ # add the client
276
+ item.clients(client)
277
+ end
278
+
279
+ it "properly deletes the client" do
280
+ item.clients(client, :delete)
281
+ expect(item.get_clients).to_not include(client_name)
282
+ end
283
+
284
+ it "does not perform a query" do
285
+ expect(Chef::Search::Query).not_to receive(:new)
286
+ item.clients(client, :delete)
287
+ end
288
+ end
272
289
  end
273
290
 
274
- it "should accept a client object and not perform a search" do
275
- client = Chef::ApiClient.new
276
- client.name "foo"
277
- privkey = OpenSSL::PKey::RSA.new(1024)
278
- pubkey = privkey.public_key
279
- client.public_key(pubkey.to_pem)
280
- expect(Chef::Search::Query).not_to receive(:new)
281
- expect(ChefVault::ChefPatch::User).not_to receive(:load)
282
- @vaultitem.clients(client)
283
- expect(@vaultitem.clients).to include("foo")
291
+ context "when an Array with named clients is passed" do
292
+ let(:client) { Chef::ApiClient.new }
293
+ let(:clients) { Array.new }
294
+ let(:client_name) { "foo" }
295
+ let(:client_key) { double("chef key") }
296
+
297
+ before do
298
+ clients << client_name
299
+ client.name client_name
300
+ privkey = OpenSSL::PKey::RSA.new(1024)
301
+ pubkey = privkey.public_key
302
+ allow(item).to receive(:load_actor).with(client_name, "clients").and_return(client_key)
303
+ allow(client_key).to receive(:key).and_return(pubkey.to_pem)
304
+ allow(client_key).to receive(:name).and_return(client_name)
305
+ allow(client_key).to receive(:type).and_return("clients")
306
+ end
307
+
308
+ context "when no action is passed" do
309
+ it "default to add and properly add the client" do
310
+ item.clients(clients)
311
+ expect(item.get_clients).to include(client_name)
312
+ end
313
+
314
+ it "does not perform a query" do
315
+ expect(Chef::Search::Query).not_to receive(:new)
316
+ item.clients(clients)
317
+ end
318
+ end
319
+
320
+ context "when the delete action is passed on an existing client" do
321
+ before do
322
+ # add the client
323
+ item.clients(clients)
324
+ end
325
+
326
+ it "properly deletes the client" do
327
+ item.clients(clients, :delete)
328
+ expect(item.get_clients).to_not include(client_name)
329
+ end
330
+
331
+ it "does not perform a query" do
332
+ expect(Chef::Search::Query).not_to receive(:new)
333
+ item.clients(clients, :delete)
334
+ end
335
+ end
284
336
  end
285
337
  end
286
338
 
287
339
  describe "#admins" do
288
- include BorkedNodeWithoutPublicKey
340
+ before do
341
+ allow(item).to receive(:load_actor).with("foo", "admins").and_raise(ChefVault::Exceptions::AdminNotFound)
342
+ end
289
343
 
290
344
  it "should blow up if you try to use a node without a public key as an admin" do
291
- expect { @vaultitem.admins("foo,bar") }
345
+ expect { item.admins("foo,bar") }
292
346
  .to raise_error(ChefVault::Exceptions::AdminNotFound)
293
347
  end
294
348
  end
@@ -6,12 +6,6 @@ RSpec.describe ChefVault::User 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("password") { "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::User do
30
24
 
31
25
  describe "decrypt_password" do
32
26
  it "echoes warning" do
33
- expect { user.decrypt_password }
34
- .to output("WARNING: This method is deprecated, please switch to item['value'] calls\n")
35
- .to_stdout
27
+ expect(ChefVault::Log).to receive(:warn).with("This method is deprecated, please switch to item['value'] calls")
28
+ user.decrypt_password
36
29
  end
37
30
 
38
31
  it "returns items password" do
@@ -39,6 +39,7 @@ RSpec.configure do |config|
39
39
  # a real object. This is generally recommended, and will default to
40
40
  # `true` in RSpec 4.
41
41
  mocks.verify_partial_doubles = true
42
+ mocks.allow_message_expectations_on_nil = true
42
43
  end
43
44
 
44
45
  # The settings below are suggested to provide a good initial experience
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-vault
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.2
4
+ version: 3.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
- - Kevin Moser
8
- - James FitzGibbon
7
+ - Thom May
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2017-06-21 00:00:00.000000000 Z
11
+ date: 2016-10-21 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
@@ -17,28 +16,42 @@ dependencies:
17
16
  requirements:
18
17
  - - "~>"
19
18
  - !ruby/object:Gem::Version
20
- version: '10.4'
19
+ version: '11.0'
21
20
  type: :development
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
24
  - - "~>"
26
25
  - !ruby/object:Gem::Version
27
- version: '10.4'
26
+ version: '11.0'
28
27
  - !ruby/object:Gem::Dependency
29
28
  name: rspec
30
29
  requirement: !ruby/object:Gem::Requirement
31
30
  requirements:
32
31
  - - "~>"
33
32
  - !ruby/object:Gem::Version
34
- version: '3.2'
33
+ version: '3.4'
35
34
  type: :development
36
35
  prerelease: false
37
36
  version_requirements: !ruby/object:Gem::Requirement
38
37
  requirements:
39
38
  - - "~>"
40
39
  - !ruby/object:Gem::Version
41
- version: '3.2'
40
+ version: '3.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mutant-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
42
55
  - !ruby/object:Gem::Dependency
43
56
  name: aruba
44
57
  requirement: !ruby/object:Gem::Requirement
@@ -82,36 +95,22 @@ dependencies:
82
95
  - !ruby/object:Gem::Version
83
96
  version: '0.2'
84
97
  - !ruby/object:Gem::Dependency
85
- name: rubocop
98
+ name: chef
86
99
  requirement: !ruby/object:Gem::Requirement
87
100
  requirements:
88
101
  - - "~>"
89
102
  - !ruby/object:Gem::Version
90
- version: '0.30'
91
- type: :development
103
+ version: '12'
104
+ type: :runtime
92
105
  prerelease: false
93
106
  version_requirements: !ruby/object:Gem::Requirement
94
107
  requirements:
95
108
  - - "~>"
96
109
  - !ruby/object:Gem::Version
97
- version: '0.30'
98
- - !ruby/object:Gem::Dependency
99
- name: chef
100
- requirement: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- version: 0.10.10
105
- type: :development
106
- prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - ">="
110
- - !ruby/object:Gem::Version
111
- version: 0.10.10
110
+ version: '12'
112
111
  description: Data encryption support for Chef using data bags
113
112
  email:
114
- - techcheftm@nordstrom.com
113
+ - thom@chef.io
115
114
  executables:
116
115
  - chef-vault
117
116
  extensions: []
@@ -122,7 +121,6 @@ files:
122
121
  - ".rubocop.yml"
123
122
  - ".simplecov"
124
123
  - ".travis.yml"
125
- - CONTRIBUTING.md
126
124
  - Changelog.md
127
125
  - DEMO.md
128
126
  - Gemfile
@@ -152,28 +150,22 @@ files:
152
150
  - features/vault_update.feature
153
151
  - features/verify_id_matches.feature
154
152
  - features/wrong_private_key.feature
153
+ - hooks/pre-commit
155
154
  - lib/chef-vault.rb
155
+ - lib/chef-vault/actor.rb
156
156
  - lib/chef-vault/certificate.rb
157
- - lib/chef-vault/chef_patch/api_client.rb
158
- - lib/chef-vault/chef_patch/user.rb
157
+ - lib/chef-vault/chef_api.rb
159
158
  - lib/chef-vault/exceptions.rb
160
159
  - lib/chef-vault/item.rb
161
160
  - lib/chef-vault/item_keys.rb
162
161
  - lib/chef-vault/mixins.rb
163
162
  - lib/chef-vault/user.rb
164
163
  - lib/chef-vault/version.rb
165
- - lib/chef/knife/decrypt.rb
166
- - lib/chef/knife/encrypt_create.rb
167
- - lib/chef/knife/encrypt_delete.rb
168
- - lib/chef/knife/encrypt_remove.rb
169
- - lib/chef/knife/encrypt_rotate_keys.rb
170
- - lib/chef/knife/encrypt_update.rb
171
- - lib/chef/knife/mixin/compat.rb
172
164
  - lib/chef/knife/mixin/helper.rb
173
165
  - lib/chef/knife/vault_admins.rb
174
166
  - lib/chef/knife/vault_base.rb
167
+ - lib/chef/knife/vault_clients.rb
175
168
  - lib/chef/knife/vault_create.rb
176
- - lib/chef/knife/vault_decrypt.rb
177
169
  - lib/chef/knife/vault_delete.rb
178
170
  - lib/chef/knife/vault_download.rb
179
171
  - lib/chef/knife/vault_edit.rb
@@ -186,7 +178,9 @@ files:
186
178
  - lib/chef/knife/vault_rotate_keys.rb
187
179
  - lib/chef/knife/vault_show.rb
188
180
  - lib/chef/knife/vault_update.rb
181
+ - spec/chef-vault/actor_spec.rb
189
182
  - spec/chef-vault/certificate_spec.rb
183
+ - spec/chef-vault/chef_api_spec.rb
190
184
  - spec/chef-vault/item_keys_spec.rb
191
185
  - spec/chef-vault/item_spec.rb
192
186
  - spec/chef-vault/user_spec.rb
@@ -205,15 +199,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
199
  requirements:
206
200
  - - ">="
207
201
  - !ruby/object:Gem::Version
208
- version: '0'
202
+ version: 2.2.0
209
203
  required_rubygems_version: !ruby/object:Gem::Requirement
210
204
  requirements:
211
- - - ">="
205
+ - - ">"
212
206
  - !ruby/object:Gem::Version
213
- version: '0'
207
+ version: 1.3.1
214
208
  requirements: []
215
209
  rubyforge_project:
216
- rubygems_version: 2.6.11
210
+ rubygems_version: 2.5.1
217
211
  signing_key:
218
212
  specification_version: 4
219
213
  summary: Data encryption support for Chef using data bags