chef-vault 2.4.0 → 2.5.0

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/.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'