chef-vault 3.0.0.rc2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +34 -2
- data/Gemfile +1 -1
- data/features/isvault.feature +6 -0
- data/features/step_definitions/chef-vault.rb +19 -8
- data/features/vault_create.feature +10 -0
- data/features/vault_list.feature +6 -0
- data/lib/chef-vault/actor.rb +10 -12
- data/lib/chef-vault/item_keys.rb +14 -5
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef/knife/vault_base.rb +15 -4
- data/lib/chef/knife/vault_create.rb +7 -0
- data/spec/chef-vault/item_keys_spec.rb +53 -5
- data/tasks/github_changelog_generator.rb +3 -4
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52a4a35874db5011ab58dc856935a50d9f5bd0b1
|
4
|
+
data.tar.gz: 3515ba7b52b188fe1851cd2a7d2585b8268f8a9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dda2609409ba281e63da7dacf34063c9efc65e5ad50a0652f11a75d4f97a56346b32e5580cc853d64933e01ec3edddbe2e67b8b48690e6fecd08a7af9cafca6c
|
7
|
+
data.tar.gz: ce93841b5ecbd3176a1cc7b5c4ce04735fddcc6a7b7b70cb9739b61e53a40a84c884676dea5a75bb33930d8d50250da2e5d11caa784b80466c649c3b9a639f3d
|
data/Changelog.md
CHANGED
@@ -1,7 +1,39 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [
|
4
|
-
[Full Changelog](https://github.com/chef/chef-vault/compare/v2.
|
3
|
+
## [v3.0.0](https://github.com/chef/chef-vault/tree/v3.0.0) (2017-04-10)
|
4
|
+
[Full Changelog](https://github.com/chef/chef-vault/compare/v2.9.1...v3.0.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Vault creation, list, and destruction in sparse mode [\#252](https://github.com/chef/chef-vault/pull/252) ([rveznaver](https://github.com/rveznaver))
|
9
|
+
|
10
|
+
## [v3.0.0.rc2](https://github.com/chef/chef-vault/tree/v3.0.0.rc2) (2016-12-05)
|
11
|
+
[Full Changelog](https://github.com/chef/chef-vault/compare/v3.0.0.rc1...v3.0.0.rc2)
|
12
|
+
|
13
|
+
**Implemented enhancements:**
|
14
|
+
|
15
|
+
- Add feature to save each key in different data bag item [\#246](https://github.com/chef/chef-vault/pull/246) ([rveznaver](https://github.com/rveznaver))
|
16
|
+
- Enable testing with Chef Zero [\#244](https://github.com/chef/chef-vault/pull/244) ([rveznaver](https://github.com/rveznaver))
|
17
|
+
- Minimize the number of searches [\#243](https://github.com/chef/chef-vault/pull/243) ([thommay](https://github.com/thommay))
|
18
|
+
- Optimise queries when finding nodes [\#240](https://github.com/chef/chef-vault/pull/240) ([thommay](https://github.com/thommay))
|
19
|
+
|
20
|
+
**Fixed bugs:**
|
21
|
+
|
22
|
+
- Use solo\_legacy\_mode fully [\#242](https://github.com/chef/chef-vault/pull/242) ([thommay](https://github.com/thommay))
|
23
|
+
- Use legacy solo mode [\#241](https://github.com/chef/chef-vault/pull/241) ([thommay](https://github.com/thommay))
|
24
|
+
|
25
|
+
## [v3.0.0.rc1](https://github.com/chef/chef-vault/tree/v3.0.0.rc1) (2016-10-21)
|
26
|
+
[Full Changelog](https://github.com/chef/chef-vault/compare/v2.9.0...v3.0.0.rc1)
|
27
|
+
|
28
|
+
**Implemented enhancements:**
|
29
|
+
|
30
|
+
- Removed deprecated knife commands [\#236](https://github.com/chef/chef-vault/pull/236) ([thommay](https://github.com/thommay))
|
31
|
+
- rename ChefKey to Actor [\#234](https://github.com/chef/chef-vault/pull/234) ([thommay](https://github.com/thommay))
|
32
|
+
- Move to using a logger for all user output [\#232](https://github.com/chef/chef-vault/pull/232) ([thommay](https://github.com/thommay))
|
33
|
+
- Add support for clients [\#227](https://github.com/chef/chef-vault/pull/227) ([svanharmelen](https://github.com/svanharmelen))
|
34
|
+
|
35
|
+
## [v2.9.0](https://github.com/chef/chef-vault/tree/v2.9.0) (2016-04-08)
|
36
|
+
[Full Changelog](https://github.com/chef/chef-vault/compare/v2.8.0...v2.9.0)
|
5
37
|
|
6
38
|
**Implemented enhancements:**
|
7
39
|
|
data/Gemfile
CHANGED
data/features/isvault.feature
CHANGED
@@ -8,6 +8,12 @@ Feature: determine if a data bag item is a vault
|
|
8
8
|
And I check if the data bag item 'test/item' is a vault
|
9
9
|
Then the exit status should be 0
|
10
10
|
|
11
|
+
Scenario: detect vault item with keys in sparse mode
|
12
|
+
Given a local mode chef repo with nodes 'one,two,three'
|
13
|
+
And I create a vault item 'test/item' with keys in sparse mode containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
14
|
+
And I check if the data bag item 'test/item' is a vault
|
15
|
+
Then the exit status should be 0
|
16
|
+
|
11
17
|
Scenario: detect non-vault item (encrypted data bag)
|
12
18
|
Given a local mode chef repo with nodes 'one,two,three'
|
13
19
|
And I create an empty data bag 'test'
|
@@ -1,10 +1,11 @@
|
|
1
1
|
require "json"
|
2
2
|
|
3
|
-
Given(/^I create a vault item '(.+)\/(.+)' containing the JSON '(.+)' encrypted for '(.+)'(?: with '(.+)' as admins?)?$/) do |vault, item, json, nodelist, admins|
|
3
|
+
Given(/^I create a vault item '(.+)\/(.+)'( with keys in sparse mode)? containing the JSON '(.+)' encrypted for '(.+)'(?: with '(.+)' as admins?)?$/) do |vault, item, sparse, json, nodelist, admins|
|
4
4
|
write_file "item.json", json
|
5
5
|
query = nodelist.split(/,/).map { |e| "name:#{e}" }.join(" OR ")
|
6
6
|
adminarg = admins.nil? ? "-A admin" : "-A #{admins}"
|
7
|
-
|
7
|
+
sparseopt = sparse.nil? ? "" : "-K sparse"
|
8
|
+
run_simple "knife vault create #{vault} #{item} -z -c knife.rb #{adminarg} #{sparseopt} -S '#{query}' -J item.json", false
|
8
9
|
end
|
9
10
|
|
10
11
|
Given(/^I update the vault item '(.+)\/(.+)' to be encrypted for '(.+)'( with the clean option)?$/) do |vault, item, nodelist, cleanopt|
|
@@ -41,18 +42,28 @@ Given(/^I try to decrypt the vault item '(.+)\/(.+)' as '(.+)'$/) do |vault, ite
|
|
41
42
|
run_simple "knife vault show #{vault} #{item} -z -c knife.rb -u #{node} -k #{node}.pem", false
|
42
43
|
end
|
43
44
|
|
44
|
-
Then(/^the vault item '(.+)\/(.+)' should( not)? be encrypted for '(.+)'
|
45
|
+
Then(/^the vault item '(.+)\/(.+)' should( not)? be encrypted for '(.+)'( with keys in sparse mode)?$/) do |vault, item, neg, nodelist, sparse|
|
45
46
|
nodes = nodelist.split(/,/)
|
46
47
|
command = "knife data bag show #{vault} #{item}_keys -z -c knife.rb -F json"
|
47
48
|
run_simple(command)
|
48
49
|
output = last_command_started.stdout
|
49
50
|
data = JSON.parse(output)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
if sparse
|
52
|
+
expect(data).to include("mode" => "sparse")
|
53
|
+
nodes.each do |node|
|
54
|
+
command = "knife data bag show #{vault} #{item}_key_#{node} -z -c knife.rb -F json"
|
55
|
+
run_simple(command, fail_on_error: false)
|
56
|
+
if neg
|
57
|
+
error = last_command_started.stderr
|
58
|
+
expect(error).to include("ERROR: The object you are looking for could not be found")
|
59
|
+
else
|
60
|
+
data = JSON.parse(last_command_started.stdout)
|
61
|
+
expect(data).to include("id" => "#{item}_key_#{node}")
|
62
|
+
end
|
55
63
|
end
|
64
|
+
else
|
65
|
+
expect(data).to include("mode" => "default")
|
66
|
+
nodes.each { |node| neg ? (expect(data).not_to include(node)) : (expect(data).to include(node)) }
|
56
67
|
end
|
57
68
|
end
|
58
69
|
|
@@ -46,6 +46,16 @@ Feature: knife vault create
|
|
46
46
|
And 'alice' should be an admin for the vault item 'test/item'
|
47
47
|
And 'bob' should not be an admin for the vault item 'test/item'
|
48
48
|
|
49
|
+
Scenario: create vault with several admins in sparse mode
|
50
|
+
Given a local mode chef repo with nodes 'one,two' with admins 'alice,bob'
|
51
|
+
And I create a vault item 'test/item' with keys in sparse mode containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
|
52
|
+
Then the vault item 'test/item' should be encrypted for 'one,two' with keys in sparse mode
|
53
|
+
And the vault item 'test/item' should not be encrypted for 'three' with keys in sparse mode
|
54
|
+
And 'one,two' should be a client for the vault item 'test/item'
|
55
|
+
And 'three' should not be a client for the vault item 'test/item'
|
56
|
+
And 'alice' should be an admin for the vault item 'test/item'
|
57
|
+
And 'bob' should not be an admin for the vault item 'test/item'
|
58
|
+
|
49
59
|
Scenario: create vault with an unknown admin
|
50
60
|
Given a local mode chef repo with nodes 'one,two'
|
51
61
|
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three' with 'alice' as admin
|
data/features/vault_list.feature
CHANGED
@@ -10,6 +10,12 @@ Feature: list data bags that are vaults
|
|
10
10
|
And I list the vaults
|
11
11
|
Then the output should match /(?m:^test$)/
|
12
12
|
|
13
|
+
Scenario: List bags that are vaults with keys in sparse mode
|
14
|
+
Given a local mode chef repo with nodes 'one,two,three'
|
15
|
+
And I create a vault item 'test/item' with keys in sparse mode containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
16
|
+
And I list the vaults
|
17
|
+
Then the output should match /(?m:^test$)/
|
18
|
+
|
13
19
|
Scenario: Skip data bags that are not vaults
|
14
20
|
Given a local mode chef repo with nodes 'one,two,three'
|
15
21
|
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
data/lib/chef-vault/actor.rb
CHANGED
@@ -66,18 +66,16 @@ class ChefVault
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def get_client_key
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
raise http_error
|
80
|
-
end
|
69
|
+
get_key("clients")
|
70
|
+
rescue Net::HTTPServerException => http_error
|
71
|
+
if http_error.response.code.eql?("403")
|
72
|
+
print_forbidden_error
|
73
|
+
raise http_error
|
74
|
+
elsif http_error.response.code.eql?("404")
|
75
|
+
raise ChefVault::Exceptions::ClientNotFound,
|
76
|
+
"#{name} is not a valid chef client and/or node"
|
77
|
+
else
|
78
|
+
raise http_error
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
data/lib/chef-vault/item_keys.rb
CHANGED
@@ -161,14 +161,23 @@ class ChefVault
|
|
161
161
|
|
162
162
|
def destroy
|
163
163
|
if Chef::Config[:solo_legacy_mode]
|
164
|
-
data_bag_path = File.join(Chef::Config[:data_bag_path],
|
165
|
-
data_bag)
|
164
|
+
data_bag_path = File.join(Chef::Config[:data_bag_path], data_bag)
|
166
165
|
data_bag_item_path = File.join(data_bag_path, @raw_data["id"])
|
167
|
-
|
166
|
+
data_bag_sparse_keys_path = File.join(data_bag_path, sparse_id("*"))
|
167
|
+
# destroy all sparse keys
|
168
|
+
FileUtils.rm(Dir.glob("#{data_bag_sparse_keys_path}.json"))
|
169
|
+
# destroy this metadata
|
168
170
|
FileUtils.rm("#{data_bag_item_path}.json")
|
169
|
-
|
170
171
|
nil
|
171
172
|
else
|
173
|
+
# destroy all sparse keys
|
174
|
+
rgx = Regexp.new("^#{sparse_id(".*")}")
|
175
|
+
items = Chef::DataBag.load(data_bag).keys.select { |item| item =~ rgx }
|
176
|
+
items.each do |id|
|
177
|
+
Chef::DataBagItem.from_hash("data_bag" => data_bag, "id" => id)
|
178
|
+
.destroy(data_bag, id)
|
179
|
+
end
|
180
|
+
# destroy this metadata
|
172
181
|
super(data_bag, id)
|
173
182
|
end
|
174
183
|
end
|
@@ -205,7 +214,7 @@ class ChefVault
|
|
205
214
|
# @private
|
206
215
|
|
207
216
|
def sparse_id(key, item_id = @raw_data["id"])
|
208
|
-
"#{item_id}_key_#{key}"
|
217
|
+
"#{item_id.chomp("_keys")}_key_#{key}"
|
209
218
|
end
|
210
219
|
|
211
220
|
def sparse_key(sid)
|
data/lib/chef-vault/version.rb
CHANGED
@@ -49,8 +49,12 @@ class Chef
|
|
49
49
|
|
50
50
|
def bag_is_vault?(bagname)
|
51
51
|
bag = Chef::DataBag.load(bagname)
|
52
|
-
#
|
53
|
-
|
52
|
+
# a data bag is a vault if and only if:
|
53
|
+
# - it has at least one item with item_keys
|
54
|
+
# - every item has a matching item_keys
|
55
|
+
# - item_keys has zero or more keys in sparse mode
|
56
|
+
# vaults have a number of keys >= 2
|
57
|
+
return false unless bag.keys.size >= 2
|
54
58
|
# partition into those that end in _keys
|
55
59
|
keylike, notkeylike = split_vault_keys(bag)
|
56
60
|
# there must be an equal number of keyline and not-keylike items
|
@@ -63,8 +67,15 @@ class Chef
|
|
63
67
|
end
|
64
68
|
|
65
69
|
def split_vault_keys(bag)
|
66
|
-
#
|
67
|
-
bag.keys.
|
70
|
+
# get all item keys
|
71
|
+
keys = bag.keys.select { |k| k =~ /_keys$/ }
|
72
|
+
# get all sparse keys
|
73
|
+
r = Regexp.union(keys.map { |k| Regexp.new("^#{k.chomp('_keys')}_key_.*") })
|
74
|
+
sparse = bag.keys.select { |k| k =~ r }
|
75
|
+
# the rest
|
76
|
+
items = bag.keys - keys - sparse
|
77
|
+
# return item keys and items
|
78
|
+
[keys, items]
|
68
79
|
end
|
69
80
|
end
|
70
81
|
end
|
@@ -26,6 +26,11 @@ class Chef
|
|
26
26
|
|
27
27
|
banner "knife vault create VAULT ITEM VALUES (options)"
|
28
28
|
|
29
|
+
option :keys_mode,
|
30
|
+
:short => "-K KEYS_MODE",
|
31
|
+
:long => "--keys-mode KEYS_MODE",
|
32
|
+
:description => "Mode in which to save vault keys"
|
33
|
+
|
29
34
|
option :search,
|
30
35
|
:short => "-S SEARCH",
|
31
36
|
:long => "--search SEARCH",
|
@@ -57,6 +62,7 @@ class Chef
|
|
57
62
|
search = config[:search]
|
58
63
|
json_file = config[:json]
|
59
64
|
file = config[:file]
|
65
|
+
keys_mode = config[:keys_mode]
|
60
66
|
|
61
67
|
set_mode(config[:vault_mode])
|
62
68
|
|
@@ -91,6 +97,7 @@ class Chef
|
|
91
97
|
vault_item.clients if search
|
92
98
|
vault_item.clients(clients) if clients
|
93
99
|
vault_item.admins(admins) if admins
|
100
|
+
vault_item.keys.mode(keys_mode) if keys_mode
|
94
101
|
|
95
102
|
vault_item.save
|
96
103
|
end
|
@@ -81,11 +81,8 @@ RSpec.describe ChefVault::ItemKeys do
|
|
81
81
|
|
82
82
|
describe "#save" do
|
83
83
|
let(:client_name) { "client_name" }
|
84
|
-
let(:chef_key)
|
85
|
-
|
86
|
-
before do
|
87
|
-
allow(chef_key).to receive(:key) { public_key_string }
|
88
|
-
end
|
84
|
+
let(:chef_key) { ChefVault::Actor.new("clients", client_name) }
|
85
|
+
before { allow(chef_key).to receive(:key) { public_key_string } }
|
89
86
|
|
90
87
|
it "should save the key data" do
|
91
88
|
keys.add(chef_key, shared_secret)
|
@@ -110,6 +107,29 @@ RSpec.describe ChefVault::ItemKeys do
|
|
110
107
|
keys.mode("default")
|
111
108
|
end
|
112
109
|
end
|
110
|
+
|
111
|
+
describe "#destroy" do
|
112
|
+
let(:client_name) { "client_name" }
|
113
|
+
let(:chef_key) { ChefVault::Actor.new("clients", client_name) }
|
114
|
+
before { allow(chef_key).to receive(:key) { public_key_string } }
|
115
|
+
|
116
|
+
it "should destroy the keys" do
|
117
|
+
keys.add(chef_key, shared_secret)
|
118
|
+
keys.save("bar")
|
119
|
+
keys.destroy
|
120
|
+
expect { Chef::DataBagItem.load("foo", "bar") }.to raise_error(Net::HTTPServerException)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should destroy the keys in sparse mode" do
|
124
|
+
keys.add(chef_key, shared_secret)
|
125
|
+
keys.mode("sparse")
|
126
|
+
keys.save("bar")
|
127
|
+
keys.destroy
|
128
|
+
expect { Chef::DataBagItem.load("foo", "bar") }.to raise_error(Net::HTTPServerException)
|
129
|
+
expect { Chef::DataBagItem.load("foo", "bar_key_client_name") }.to raise_error(Net::HTTPServerException)
|
130
|
+
keys.mode("default")
|
131
|
+
end
|
132
|
+
end
|
113
133
|
end
|
114
134
|
|
115
135
|
context "when running with chef-solo" do
|
@@ -182,6 +202,34 @@ RSpec.describe ChefVault::ItemKeys do
|
|
182
202
|
keys.mode("default")
|
183
203
|
end
|
184
204
|
end
|
205
|
+
|
206
|
+
describe "#destroy" do
|
207
|
+
let(:client_name) { "client_name" }
|
208
|
+
let(:chef_key) { ChefVault::Actor.new("clients", client_name) }
|
209
|
+
let(:data_bag_path) { Dir.mktmpdir("vault_item_keys") }
|
210
|
+
|
211
|
+
before do
|
212
|
+
Chef::Config[:data_bag_path] = data_bag_path
|
213
|
+
allow(chef_key).to receive(:key) { public_key_string }
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should destroy the keys" do
|
217
|
+
keys.add(chef_key, shared_secret)
|
218
|
+
keys.save("bar")
|
219
|
+
keys.destroy
|
220
|
+
expect(File.exist?(File.join(data_bag_path, "foo", "bar.json"))).to be(false)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should destroy the keys in sparse mode" do
|
224
|
+
keys.add(chef_key, shared_secret)
|
225
|
+
keys.mode("sparse")
|
226
|
+
keys.save("bar")
|
227
|
+
keys.destroy
|
228
|
+
expect(File.exist?(File.join(data_bag_path, "foo", "bar.json"))).to be(false)
|
229
|
+
expect(File.exist?(File.join(data_bag_path, "foo", "bar_key_client_name.json"))).to be(false)
|
230
|
+
keys.mode("default")
|
231
|
+
end
|
232
|
+
end
|
185
233
|
end
|
186
234
|
end
|
187
235
|
end
|
@@ -21,10 +21,9 @@ begin
|
|
21
21
|
require "github_changelog_generator/task"
|
22
22
|
|
23
23
|
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
24
|
-
config.future_release = ChefVault::VERSION
|
25
|
-
config.
|
26
|
-
config.
|
27
|
-
config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion".split(",")
|
24
|
+
config.future_release = "v#{ChefVault::VERSION}"
|
25
|
+
config.max_issues = 0
|
26
|
+
config.add_issues_wo_labels = false
|
28
27
|
end
|
29
28
|
rescue LoadError
|
30
29
|
puts "github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-vault
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thom May
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -202,12 +202,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
202
202
|
version: 2.2.0
|
203
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
204
|
requirements:
|
205
|
-
- - "
|
205
|
+
- - ">="
|
206
206
|
- !ruby/object:Gem::Version
|
207
|
-
version:
|
207
|
+
version: '0'
|
208
208
|
requirements: []
|
209
209
|
rubyforge_project:
|
210
|
-
rubygems_version: 2.
|
210
|
+
rubygems_version: 2.6.11
|
211
211
|
signing_key:
|
212
212
|
specification_version: 4
|
213
213
|
summary: Data encryption support for Chef using data bags
|