chef-vault 2.4.0 → 2.5.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +97 -0
  4. data/Changelog.md +34 -0
  5. data/DEMO.md +13 -6
  6. data/README.md +9 -4
  7. data/Rakefile +47 -10
  8. data/THEORY.md +361 -0
  9. data/bin/chef-vault +5 -5
  10. data/chef-vault.gemspec +11 -2
  11. data/features/clean_unknown_clients.feature +28 -3
  12. data/features/step_definitions/chef-databag.rb +5 -0
  13. data/features/step_definitions/chef-repo.rb +46 -8
  14. data/features/step_definitions/chef-vault.rb +69 -15
  15. data/features/support/env.rb +2 -2
  16. data/features/vault_create.feature +54 -0
  17. data/features/vault_list.feature +26 -0
  18. data/features/vault_show.feature +46 -0
  19. data/features/vault_update.feature +17 -0
  20. data/features/wrong_private_key.feature +14 -0
  21. data/lib/chef-vault.rb +0 -1
  22. data/lib/chef-vault/certificate.rb +1 -1
  23. data/lib/chef-vault/chef_patch/api_client.rb +1 -1
  24. data/lib/chef-vault/chef_patch/user.rb +1 -1
  25. data/lib/chef-vault/exceptions.rb +33 -12
  26. data/lib/chef-vault/item.rb +262 -209
  27. data/lib/chef-vault/item_keys.rb +90 -88
  28. data/lib/chef-vault/user.rb +1 -1
  29. data/lib/chef-vault/version.rb +2 -2
  30. data/lib/chef/knife/decrypt.rb +1 -2
  31. data/lib/chef/knife/encrypt_create.rb +1 -2
  32. data/lib/chef/knife/encrypt_delete.rb +1 -2
  33. data/lib/chef/knife/encrypt_remove.rb +1 -2
  34. data/lib/chef/knife/encrypt_rotate_keys.rb +1 -2
  35. data/lib/chef/knife/encrypt_update.rb +1 -2
  36. data/lib/chef/knife/mixin/compat.rb +3 -3
  37. data/lib/chef/knife/mixin/helper.rb +6 -8
  38. data/lib/chef/knife/vault_admins.rb +1 -2
  39. data/lib/chef/knife/vault_base.rb +2 -2
  40. data/lib/chef/knife/vault_create.rb +3 -4
  41. data/lib/chef/knife/vault_decrypt.rb +3 -4
  42. data/lib/chef/knife/vault_delete.rb +2 -4
  43. data/lib/chef/knife/vault_download.rb +1 -2
  44. data/lib/chef/knife/vault_edit.rb +3 -6
  45. data/lib/chef/knife/vault_list.rb +53 -0
  46. data/lib/chef/knife/vault_refresh.rb +1 -2
  47. data/lib/chef/knife/vault_remove.rb +3 -7
  48. data/lib/chef/knife/vault_rotate_all_keys.rb +2 -4
  49. data/lib/chef/knife/vault_rotate_keys.rb +2 -4
  50. data/lib/chef/knife/vault_show.rb +4 -5
  51. data/lib/chef/knife/vault_update.rb +7 -9
  52. data/spec/chef-vault/certificate_spec.rb +0 -2
  53. data/spec/chef-vault/item_spec.rb +77 -1
  54. data/spec/chef-vault/user_spec.rb +0 -2
  55. data/spec/chef-vault_spec.rb +1 -1
  56. data/spec/spec_helper.rb +1 -3
  57. metadata +38 -14
@@ -3,15 +3,15 @@
3
3
  # ./chef-vault - Run chef-vault and decrypt based on parameters
4
4
  #
5
5
  # Author:: Kevin Moser (<kevin.moser@nordstrom.com>)
6
- # Copyright:: Copyright (c) 2013 Nordstrom, Inc.
6
+ # Copyright:: Copyright (c) 2013-15 Nordstrom, Inc.
7
7
  # License:: Apache License, Version 2.0
8
8
  #
9
9
  # Licensed under the Apache License, Version 2.0 (the "License");
10
10
  # you may not use this file except in compliance with the License.
11
11
  # You may obtain a copy of the License at
12
- #
12
+ #
13
13
  # http://www.apache.org/licenses/LICENSE-2.0
14
- #
14
+ #
15
15
  # Unless required by applicable law or agreed to in writing, software
16
16
  # distributed under the License is distributed on an "AS IS" BASIS,
17
17
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -34,7 +34,7 @@ options_config = {
34
34
  description: "Vault to look in",
35
35
  default: nil,
36
36
  optional: false
37
- },
37
+ },
38
38
  item: {
39
39
  short: "i",
40
40
  long: "item",
@@ -57,7 +57,7 @@ options_config.each do |option, config|
57
57
  banner << "[--#{config[:long]} #{config[:long].upcase}] "
58
58
  else
59
59
  banner << "--#{config[:long]} #{config[:long].upcase} "
60
- end
60
+ end
61
61
  end
62
62
 
63
63
  options = {}
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Chef-Vault Gemspec file
3
- # Copyright 2013, Nordstrom, Inc.
3
+ # Copyright 2013-15, Nordstrom, Inc.
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -38,7 +38,16 @@ Gem::Specification.new do |s|
38
38
  s.add_development_dependency 'rspec', '~> 3.1'
39
39
  s.add_development_dependency 'rspec-its', '~> 1.1'
40
40
  s.add_development_dependency 'aruba', '~> 0.6'
41
- s.add_development_dependency 'chef', '>= 0.10.10'
42
41
  s.add_development_dependency 'simplecov', '~> 0.9'
43
42
  s.add_development_dependency 'simplecov-console', '~> 0.2'
43
+ s.add_development_dependency 'rubocop', '~> 0.29'
44
+ # Chef 12 and higher pull in Ohai 8, which needs Ruby v2
45
+ # so only in the case of a CI build on ruby v1, we constrain
46
+ # chef to 11 or lower so that we can maintain CI test coverage
47
+ # of older versions
48
+ if ENV.key?('TRAVIS_BUILD') && RUBY_VERSION =~ /^1/
49
+ s.add_development_dependency 'chef', '~> 11.18'
50
+ else
51
+ s.add_development_dependency 'chef', '>= 0.10.10'
52
+ end
44
53
  end
@@ -14,7 +14,11 @@ Feature: clean unknown clients on key rotation
14
14
  Then the vault item 'test/item' should be encrypted for 'one,two,three'
15
15
  And I delete client 'one' from the Chef server
16
16
  And I remove client 'two' from vault item 'test/item' with the 'clean-unknown-clients' option
17
- Then the vault item 'test/item' should be encrypted for 'three'
17
+ Then the output should contain "Removing unknown client 'one'"
18
+ And the vault item 'test/item' should be encrypted for 'three'
19
+ And the vault item 'test/item' should not be encrypted for 'one,two'
20
+ And 'three' should be a client for the vault item 'test/item'
21
+ And 'one,two' should not be a client for the vault item 'test/item'
18
22
 
19
23
  Scenario: Prune clients when rotating keys
20
24
  Given a local mode chef repo with nodes 'one,two,three'
@@ -22,7 +26,11 @@ Feature: clean unknown clients on key rotation
22
26
  Then the vault item 'test/item' should be encrypted for 'one,two,three'
23
27
  And I delete client 'one' from the Chef server
24
28
  And I rotate the keys for vault item 'test/item' with the 'clean-unknown-clients' option
25
- Then the vault item 'test/item' should be encrypted for 'two,three'
29
+ Then the output should contain "Removing unknown client 'one'"
30
+ And the vault item 'test/item' should be encrypted for 'two,three'
31
+ And the vault item 'test/item' should not be encrypted for 'one'
32
+ And 'two,three' should be a client for the vault item 'test/item'
33
+ And 'one' should not be a client for the vault item 'test/item'
26
34
 
27
35
  Scenario: Prune clients when rotating all keys
28
36
  Given a local mode chef repo with nodes 'one,two,three'
@@ -30,4 +38,21 @@ Feature: clean unknown clients on key rotation
30
38
  Then the vault item 'test/item' should be encrypted for 'one,two,three'
31
39
  And I delete clients 'one,two' from the Chef server
32
40
  And I rotate all keys with the 'clean-unknown-clients' option
33
- Then the vault item 'test/item' should be encrypted for 'three'
41
+ Then the output should contain "Removing unknown client 'one'"
42
+ And the output should contain "Removing unknown client 'two'"
43
+ And the vault item 'test/item' should be encrypted for 'three'
44
+ And the vault item 'test/item' should not be encrypted for 'one,two'
45
+ And 'three' should be a client for the vault item 'test/item'
46
+ And 'one,two' should not be a client for the vault item 'test/item'
47
+
48
+ Scenario: Prune clients when node gone but client exists
49
+ Given a local mode chef repo with nodes 'one,two,three'
50
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
51
+ Then the vault item 'test/item' should be encrypted for 'one,two,three'
52
+ And I delete node 'one' from the Chef server
53
+ And I rotate the keys for vault item 'test/item' with the 'clean-unknown-clients' option
54
+ Then the output should contain "Removing unknown client 'one'"
55
+ And the vault item 'test/item' should be encrypted for 'two,three'
56
+ And the vault item 'test/item' should not be encrypted for 'one'
57
+ And 'two,three' should be a client for the vault item 'test/item'
58
+ And 'one' should not be a client for the vault item 'test/item'
@@ -0,0 +1,5 @@
1
+ When /^I create a data bag '(.+)' containing the JSON '(.+)'$/ do |bag, json|
2
+ write_file 'item.json', json
3
+ run_simple "knife data bag create #{bag} -z -c knife.rb -d"
4
+ run_simple "knife data bag from_file #{bag} -z -c knife.rb item.json"
5
+ end
@@ -1,4 +1,4 @@
1
- Given /^a local mode chef repo with nodes '(.+)'$/ do |nodelist|
1
+ Given(/^a local mode chef repo with nodes '(.+?)'(?: with admins '(.+?)')?$/) do |nodelist, adminlist|
2
2
  # create the repo directory hierarchy
3
3
  %w(cookbooks clients nodes data_bags).each do |dir|
4
4
  create_dir dir
@@ -9,9 +9,13 @@ local_mode true
9
9
  chef_repo_path '.'
10
10
  chef_zero.enabled true
11
11
  EOF
12
- # create the admin user and capture its private key
13
- in_current_dir do
14
- system 'knife client create admin -z -d -a -c knife.rb > admin.pem'
12
+ # create the admin users and capture their private key we
13
+ # always create an admin called 'admin' because otherwise subsequent
14
+ # steps become annoying to determine who the admin is
15
+ admins = %w(admin)
16
+ admins.push(adminlist.split(/,/)) if adminlist
17
+ admins.flatten.each do |admin|
18
+ create_admin(admin)
15
19
  end
16
20
  # add the admin key to the knife configuration
17
21
  append_to_file 'knife.rb', <<EOF
@@ -20,14 +24,48 @@ client_key 'admin.pem'
20
24
  EOF
21
25
  # create the requested nodes
22
26
  nodelist.split(/,/).each do |node|
23
- run_simple "knife client create #{node} -z -d -c knife.rb"
24
- run_simple "knife node create #{node} -z -d -c knife.rb"
27
+ create_client(node)
28
+ create_node(node)
25
29
  end
26
30
  end
27
31
 
28
- When /^I delete clients? '(.+)' from the Chef server$/ do |nodelist|
32
+ Given(/^I create an admin named '(.+)'$/) do |admin|
33
+ create_admin(admin)
34
+ end
35
+
36
+ Given(/^I delete clients? '(.+)' from the Chef server$/) do |nodelist|
29
37
  nodelist.split(/,/).each do |node|
30
- run_simple "knife client delete #{node} -z -d -y -c knife.rb"
38
+ delete_client(node)
31
39
  end
32
40
  end
33
41
 
42
+ Given(/^I regenerate the client key for the node '(.+)'$/) do |node|
43
+ delete_client(node)
44
+ create_client(node)
45
+ end
46
+
47
+ Given(/^I delete nodes? '(.+)' from the Chef server$/) do |nodelist|
48
+ nodelist.split(/,/).each { |node| delete_node(node) }
49
+ end
50
+
51
+ def create_node(name)
52
+ run_simple "knife node create #{name} -z -d -c knife.rb"
53
+ end
54
+
55
+ def create_admin(admin)
56
+ create_client(admin, '-a')
57
+ end
58
+
59
+ def create_client(name, args = nil)
60
+ command = "knife client create #{name} -z -d -c knife.rb #{args} >#{name}.pem"
61
+ run_simple command
62
+ write_file("#{name}.pem", stdout_from(command))
63
+ end
64
+
65
+ def delete_client(name)
66
+ run_simple "knife client delete #{name} -y -z -c knife.rb"
67
+ end
68
+
69
+ def delete_node(name)
70
+ run_simple "knife node delete #{name} -y -z -c knife.rb"
71
+ end
@@ -1,41 +1,95 @@
1
1
  require 'json'
2
2
 
3
- When /^I create a vault item '(.+)\/(.+)' containing the JSON '(.+)' encrypted for '(.+)'$/ do |vault, item, json, nodelist|
3
+ Given(/^I create a vault item '(.+)\/(.+)' containing the JSON '(.+)' encrypted for '(.+)'(?: with '(.+)' as admins?)?$/) do |vault, item, json, nodelist, admins|
4
4
  write_file 'item.json', json
5
5
  query = nodelist.split(/,/).map{|e| "name:#{e}"}.join(' OR ')
6
- run_simple "knife vault create #{vault} #{item} -z -c knife.rb -A admin -S '#{query}' -J item.json"
6
+ adminarg = admins.nil? ? '-A admin' : "-A #{admins}"
7
+ run_simple "knife vault create #{vault} #{item} -z -c knife.rb #{adminarg} -S '#{query}' -J item.json", false
7
8
  end
8
9
 
9
- When /^I update the vault item '(.+)\/(.+)' to be encrypted for '(.+)'( with the clean option)?$/ do |vault, item, nodelist, cleanopt|
10
+ Given(/^I update the vault item '(.+)\/(.+)' to be encrypted for '(.+)'( with the clean option)?$/) do |vault, item, nodelist, cleanopt|
10
11
  query = nodelist.split(/,/).map{|e| "name:#{e}"}.join(' OR ')
11
- run_simple "knife vault update #{vault} #{item} -S '#{query}' #{cleanopt ? '--clean' : ''}"
12
+ run_simple "knife vault update #{vault} #{item} -z -c knife.rb -S '#{query}' #{cleanopt ? '--clean' : ''}"
12
13
  end
13
14
 
14
- When /^I remove clients? '(.+)' from vault item '(.+)\/(.+)' with the '(.+)' options?$/ do |nodelist, vault, item, optionlist|
15
+ Given(/^I remove clients? '(.+)' from vault item '(.+)\/(.+)' with the '(.+)' options?$/) do |nodelist, vault, item, optionlist|
15
16
  query = nodelist.split(/,/).map{|e| "name:#{e}"}.join(' OR ')
16
17
  options = optionlist.split(/,/).map{|o| "--#{o}"}.join(' ')
17
- run_simple "knife vault remove #{vault} #{item} -S '#{query}' #{options}"
18
+ run_simple "knife vault remove #{vault} #{item} -z -c knife.rb -S '#{query}' #{options}"
18
19
  end
19
20
 
20
- When /^I rotate the keys for vault item '(.+)\/(.+)' with the '(.+)' options?$/ do |vault, item, optionlist|
21
+ Given(/^I rotate the keys for vault item '(.+)\/(.+)' with the '(.+)' options?$/) do |vault, item, optionlist|
21
22
  options = optionlist.split(/,/).map{|o| "--#{o}"}.join(' ')
22
- run_simple "knife vault rotate keys #{vault} #{item} #{options}"
23
+ run_simple "knife vault rotate keys #{vault} #{item} -c knife.rb -z #{options}"
23
24
  end
24
25
 
25
- When /^I rotate all keys with the '(.+)' options?$/ do |optionlist|
26
+ Given(/^I rotate all keys with the '(.+)' options?$/) do |optionlist|
26
27
  options = optionlist.split(/,/).map{|o| "--#{o}"}.join(' ')
27
- run_simple "knife vault rotate all keys #{options}"
28
+ run_simple "knife vault rotate all keys -z -c knife.rb #{options}"
28
29
  end
29
30
 
30
- Then /^the vault item '(.+)\/(.+)' should( not)? be encrypted for '(.+)'$/ do |vault, item, neg, nodelist|
31
+ Given(/^I try to decrypt the vault item '(.+)\/(.+)' as '(.+)'$/) do |vault, item, node|
32
+ run_simple "knife vault show #{vault} #{item} -z -c knife.rb -u #{node} -k #{node}.pem", false
33
+ end
34
+
35
+ Then(/^the vault item '(.+)\/(.+)' should( not)? be encrypted for '(.+)'$/) do |vault, item, neg, nodelist|
31
36
  nodes = nodelist.split(/,/)
32
- run_simple("knife vault show #{vault} #{item} -z -c knife.rb -p clients -F json")
33
- output = output_from("knife vault show #{vault} #{item} -z -c knife.rb -p clients -F json")
37
+ command = "knife data bag show #{vault} #{item}_keys -z -c knife.rb -F json"
38
+ run_simple(command)
39
+ output = stdout_from(command)
40
+ data = JSON.parse(output)
34
41
  nodes.each do |node|
35
42
  if neg
36
- assert_no_partial_output(node, output)
43
+ expect(data).not_to include(node)
37
44
  else
38
- assert_partial_output(node, output)
45
+ expect(data).to include(node)
39
46
  end
40
47
  end
41
48
  end
49
+
50
+ Given(/^'(.+)' should( not)? be a client for the vault item '(.+)\/(.+)'$/) do |nodelist, neg, vault, item|
51
+ nodes = nodelist.split(/,/)
52
+ command = "knife data bag show #{vault} #{item}_keys -z -c knife.rb -F json"
53
+ run_simple(command)
54
+ output = stdout_from(command)
55
+ data = JSON.parse(output)
56
+ nodes.each do |node|
57
+ if neg
58
+ expect(data['clients']).not_to include(node)
59
+ else
60
+ expect(data['clients']).to include(node)
61
+ end
62
+ end
63
+ end
64
+
65
+ Given(/^'(.+)' should( not)? be an admin for the vault item '(.+)\/(.+)'$/) do |nodelist, neg, vault, item|
66
+ nodes = nodelist.split(/,/)
67
+ command = "knife data bag show #{vault} #{item}_keys -z -c knife.rb -F json"
68
+ run_simple(command)
69
+ output = stdout_from(command)
70
+ data = JSON.parse(output)
71
+ nodes.each do |node|
72
+ if neg
73
+ expect(data['admins']).not_to include(node)
74
+ else
75
+ expect(data['admins']).to include(node)
76
+ end
77
+ end
78
+ end
79
+
80
+ Given(/^I list the vaults$/) do
81
+ run_simple('knife vault list')
82
+ end
83
+
84
+ Given(/^I can('t)? decrypt the vault item '(.+)\/(.+)' as '(.+)'$/) do |neg, vault, item, client|
85
+ run_simple "knife vault show #{vault} #{item} -c knife.rb -z -u #{client} -k #{client}.pem", false
86
+ if neg
87
+ assert_not_exit_status(0)
88
+ else
89
+ assert_exit_status(0)
90
+ end
91
+ end
92
+
93
+ Given(/^I add '(.+)' as an admin for the vault item '(.+)\/(.+)'$/) do |newadmin, vault, item|
94
+ run_simple "knife vault update #{vault} #{item} -c knife.rb -z -A #{newadmin}"
95
+ end
@@ -7,8 +7,8 @@ require 'aruba/cucumber'
7
7
  # Travis runs tests in a limited environment which takes a long time to invoke
8
8
  # the knife command. Up the timeout when we're in a travis build based on the
9
9
  # environment variable set in .travis.yml
10
- if ENV['TRAVIS_BUILD']
10
+ #if ENV['TRAVIS_BUILD']
11
11
  Before do
12
12
  @aruba_timeout_seconds = 15
13
13
  end
14
- end
14
+ #end
@@ -0,0 +1,54 @@
1
+ Feature: knife vault create
2
+
3
+ 'knife vault create' creates two Chef data bag items: an
4
+ encrypted data bag item encrypted with a randomized shared
5
+ secret, and a side-along data bag item suffixed with _keys
6
+ that contains an set of asymmetrically encrypted copies of
7
+ the shared secret using the public keys of a set of admins
8
+ and/or clients
9
+
10
+ Scenario: create vault with all known clients
11
+ Given a local mode chef repo with nodes 'one,two,three'
12
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
13
+ Then the vault item 'test/item' should be encrypted for 'one,two,three'
14
+ And 'one,two,three' should be a client for the vault item 'test/item'
15
+
16
+ Scenario: create vault with all unknown clients
17
+ Given a local mode chef repo with nodes 'two,three'
18
+ And I delete clients 'two,three' from the Chef server
19
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'two,three'
20
+ Then the vault item 'test/item' should not be encrypted for 'one,two,three'
21
+ And the output should contain "node 'two' has no private key; skipping"
22
+ And the output should contain "node 'three' has no private key; skipping"
23
+ And 'two,three' should not be a client for the vault item 'test/item'
24
+
25
+ Scenario: create vault with mix of known and unknown clients
26
+ Given a local mode chef repo with nodes 'one,two,three'
27
+ And I delete client 'three' from the Chef server
28
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
29
+ Then the vault item 'test/item' should be encrypted for 'one,two'
30
+ And the output should contain "node 'three' has no private key; skipping"
31
+ And 'one,two' should be a client for the vault item 'test/item'
32
+ And 'three' should not be a client for the vault item 'test/item'
33
+
34
+ Scenario: create vault with mix of known and unknown nodes
35
+ Given a local mode chef repo with nodes 'one,two'
36
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
37
+ Then the vault item 'test/item' should be encrypted for 'one,two'
38
+ And 'one,two' should be a client for the vault item 'test/item'
39
+ And 'three' should not be a client for the vault item 'test/item'
40
+
41
+ Scenario: create vault with several admins
42
+ Given a local mode chef repo with nodes 'one,two' with admins 'alice,bob'
43
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
44
+ Then the vault item 'test/item' should be encrypted for 'one,two'
45
+ And 'one,two' should be a client for the vault item 'test/item'
46
+ And 'three' should not be a client for the vault item 'test/item'
47
+ And 'alice' should be an admin for the vault item 'test/item'
48
+ And 'bob' should not be an admin for the vault item 'test/item'
49
+
50
+ Scenario: create vault with an unknown admin
51
+ Given a local mode chef repo with nodes 'one,two'
52
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
53
+ Then the exit status should not be 0
54
+ And the output should contain "FATAL: Could not find alice in users or clients!"
@@ -0,0 +1,26 @@
1
+ Feature: list data bags that are vaults
2
+
3
+ knife vault list should list all data bags that appear to
4
+ be vaults. This is not an exact science; we assume that
5
+ any data bag containing an even number of items and for
6
+ which all items are pairs of thing/thing_keys is a vault
7
+
8
+ Scenario: List bags that are vaults
9
+ Given a local mode chef repo with nodes 'one,two,three'
10
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
11
+ And I list the vaults
12
+ Then the output should match /(?m:^test$)/
13
+
14
+ Scenario: Skip data bags that are not vaults
15
+ Given a local mode chef repo with nodes 'one,two,three'
16
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
17
+ And I create a data bag 'lessthantwokeys' containing the JSON '{"id": "item", "foo": "bar"}'
18
+ And I create a data bag 'oddnumberofkeys' containing the JSON '{"id": "item", "one": 1, "two": 2, "three":3}'
19
+ And I create a data bag 'unbalanced' containing the JSON '{"id": "item", "one": 1, "one_keys": 1, "two_keys": 1, "three_keys": 1}'
20
+ And I create a data bag 'mismatched' containing the JSON '{"id": "item", "one": 1, "one_keys": 1, "two_keys": 1, "three": 1}'
21
+ And I list the vaults
22
+ Then the output should match /(?m:^test$)/
23
+ And the output should not match /(?m:^lessthantwokeys$)/
24
+ And the output should not match /(?m:^oddnumberofkeys$)/
25
+ And the output should not match /(?m:^unbalanced$)/
26
+ And the output should not match /(?m:^mismatched$)/
@@ -0,0 +1,46 @@
1
+ Feature: knife vault show
2
+
3
+ 'knife vault show' displays the contents of a Chef encrypted
4
+ data bag by fetching the asymmetrically encrypted shared
5
+ secret and decrypting it using the private key of the user
6
+ or node
7
+
8
+ Scenario: successful decrypt as admin
9
+ Given a local mode chef repo with nodes 'one,two,three' with admins 'alice,bob'
10
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
11
+ Then the vault item 'test/item' should be encrypted for 'one,two,three,alice'
12
+ And 'one,two,three' should be a client for the vault item 'test/item'
13
+ And 'alice' should be an admin for the vault item 'test/item'
14
+ And 'bob' should not be an admin for the vault item 'test/item'
15
+ And I can decrypt the vault item 'test/item' as 'alice'
16
+ And the output should match /^foo: bar$/
17
+
18
+ Scenario: successful decrypt as node
19
+ Given a local mode chef repo with nodes 'one,two,three' with admins 'alice,bob'
20
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
21
+ Then the vault item 'test/item' should be encrypted for 'one,two,three,alice'
22
+ And 'one,two,three' should be a client for the vault item 'test/item'
23
+ And 'alice' should be an admin for the vault item 'test/item'
24
+ And 'bob' should not be an admin for the vault item 'test/item'
25
+ And I can decrypt the vault item 'test/item' as 'two'
26
+ And the output should match /^foo: bar$/
27
+
28
+ Scenario: failed decrypt as admin
29
+ Given a local mode chef repo with nodes 'one,two,three' with admins 'alice,bob'
30
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
31
+ Then the vault item 'test/item' should be encrypted for 'one,two,three,alice'
32
+ And 'one,two,three' should be a client for the vault item 'test/item'
33
+ And 'alice' should be an admin for the vault item 'test/item'
34
+ And 'bob' should not be an admin for the vault item 'test/item'
35
+ And I can't decrypt the vault item 'test/item' as 'bob'
36
+ And the output should contain "test/item is not encrypted with your public key"
37
+
38
+ Scenario: failed decrypt as node
39
+ Given a local mode chef repo with nodes 'one,two,three' with admins 'alice,bob'
40
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two' with 'alice' as admin
41
+ Then the vault item 'test/item' should be encrypted for 'one,two,alice'
42
+ And 'one,two' should be a client for the vault item 'test/item'
43
+ And 'alice' should be an admin for the vault item 'test/item'
44
+ And 'bob' should not be an admin for the vault item 'test/item'
45
+ And I can't decrypt the vault item 'test/item' as 'three'
46
+ And the output should contain "test/item is not encrypted with your public key"
@@ -0,0 +1,17 @@
1
+ Feature: knife vault create
2
+
3
+ 'knife vault update' is used to add clients, or administrators
4
+ and to re-run the search query
5
+
6
+ Scenario: add admin to a vault
7
+ Given a local mode chef repo with nodes 'one,two,three' with admins 'alice,bob'
8
+ And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
9
+ Then the vault item 'test/item' should be encrypted for 'one,two,three'
10
+ And 'one,two,three' should be a client for the vault item 'test/item'
11
+ And 'alice' should be an admin for the vault item 'test/item'
12
+ And I can decrypt the vault item 'test/item' as 'alice'
13
+ And I can't decrypt the vault item 'test/item' as 'bob'
14
+ And I add 'bob' as an admin for the vault item 'test/item'
15
+ Then 'alice,bob' should be an admin for the vault item 'test/item'
16
+ And I can decrypt the vault item 'test/item' as 'alice'
17
+ And I can decrypt the vault item 'test/item' as 'bob'