chef-vault 2.1.0 → 2.2.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 +8 -8
- data/.gitignore +2 -0
- data/CONTRIBUTING.md +3 -3
- data/Changelog.md +11 -1
- data/KNIFE_EXAMPLES.md +102 -72
- data/README.md +37 -35
- data/lib/chef-vault/item.rb +30 -18
- data/lib/chef-vault/item_keys.rb +15 -6
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef/knife/decrypt.rb +33 -0
- data/lib/chef/knife/encrypt_create.rb +25 -74
- data/lib/chef/knife/encrypt_delete.rb +10 -39
- data/lib/chef/knife/encrypt_remove.rb +18 -75
- data/lib/chef/knife/encrypt_rotate_keys.rb +10 -39
- data/lib/chef/knife/encrypt_update.rb +25 -73
- data/lib/chef/knife/vault_base.rb +46 -0
- data/lib/chef/knife/vault_create.rb +95 -0
- data/lib/chef/knife/vault_decrypt.rb +59 -0
- data/lib/chef/knife/vault_delete.rb +49 -0
- data/lib/chef/knife/vault_edit.rb +70 -0
- data/lib/chef/knife/vault_remove.rb +86 -0
- data/lib/chef/knife/vault_rotate_all_keys.rb +57 -0
- data/lib/chef/knife/vault_rotate_keys.rb +49 -0
- data/lib/chef/knife/vault_show.rb +89 -0
- data/lib/chef/knife/vault_update.rb +87 -0
- data/spec/chef-vault_spec.rb +11 -36
- data/spec/item_keys_spec.rb +6 -18
- data/spec/item_spec.rb +16 -21
- metadata +13 -3
- data/lib/chef/knife/Decrypt.rb +0 -71
data/lib/chef-vault/item.rb
CHANGED
@@ -49,19 +49,27 @@ class ChefVault::Item < Chef::DataBagItem
|
|
49
49
|
keys.delete(node.name, "clients")
|
50
50
|
else
|
51
51
|
raise ChefVault::Exceptions::KeysActionNotValid,
|
52
|
-
|
52
|
+
"#{action} is not a valid action"
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
unless results_returned
|
57
57
|
puts "WARNING: No clients were returned from search, you may not have "\
|
58
|
-
|
58
|
+
"got what you expected!!"
|
59
59
|
end
|
60
60
|
else
|
61
61
|
keys.clients
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
def search(search_query=nil)
|
66
|
+
if search_query
|
67
|
+
keys.search_query(search_query)
|
68
|
+
else
|
69
|
+
keys.search_query
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
65
73
|
def admins(admins=nil, action=:add)
|
66
74
|
if admins
|
67
75
|
admins.split(",").each do |admin|
|
@@ -73,7 +81,7 @@ class ChefVault::Item < Chef::DataBagItem
|
|
73
81
|
keys.delete(admin, "admins")
|
74
82
|
else
|
75
83
|
raise ChefVault::Exceptions::KeysActionNotValid,
|
76
|
-
|
84
|
+
"#{action} is not a valid action"
|
77
85
|
end
|
78
86
|
end
|
79
87
|
else
|
@@ -90,9 +98,9 @@ class ChefVault::Item < Chef::DataBagItem
|
|
90
98
|
private_key = OpenSSL::PKey::RSA.new(open(Chef::Config[:client_key]).read())
|
91
99
|
private_key.private_decrypt(Base64.decode64(@keys[Chef::Config[:node_name]]))
|
92
100
|
else
|
93
|
-
raise ChefVault::Exceptions::SecretDecryption,
|
94
|
-
|
95
|
-
|
101
|
+
raise ChefVault::Exceptions::SecretDecryption,
|
102
|
+
"#{data_bag}/#{id} is not encrypted with your public key. "\
|
103
|
+
"Contact an administrator of the vault item to encrypt for you!"
|
96
104
|
end
|
97
105
|
end
|
98
106
|
|
@@ -132,10 +140,14 @@ class ChefVault::Item < Chef::DataBagItem
|
|
132
140
|
end
|
133
141
|
|
134
142
|
def save(item_id=@raw_data['id'])
|
143
|
+
|
144
|
+
# validate the format of the id before attempting to save
|
145
|
+
validate_id!(item_id)
|
146
|
+
|
135
147
|
# save the keys first, raising an error if no keys were defined
|
136
148
|
if keys.admins.empty? && keys.clients.empty?
|
137
|
-
raise ChefVault::Exceptions::NoKeysDefined,
|
138
|
-
|
149
|
+
raise ChefVault::Exceptions::NoKeysDefined,
|
150
|
+
"No keys defined for #{item_id}"
|
139
151
|
end
|
140
152
|
|
141
153
|
keys.save
|
@@ -150,10 +162,10 @@ class ChefVault::Item < Chef::DataBagItem
|
|
150
162
|
data_bag_item_path = File.join(data_bag_path, item_id)
|
151
163
|
|
152
164
|
FileUtils.mkdir(data_bag_path) unless File.exists?(data_bag_path)
|
153
|
-
File.open("#{data_bag_item_path}.json",'w') do |file|
|
165
|
+
File.open("#{data_bag_item_path}.json",'w') do |file|
|
154
166
|
file.write(JSON.pretty_generate(self.raw_data))
|
155
167
|
end
|
156
|
-
|
168
|
+
|
157
169
|
self.raw_data
|
158
170
|
else
|
159
171
|
begin
|
@@ -189,25 +201,25 @@ class ChefVault::Item < Chef::DataBagItem
|
|
189
201
|
else
|
190
202
|
super(data_bag, id)
|
191
203
|
end
|
192
|
-
end
|
204
|
+
end
|
193
205
|
|
194
206
|
def self.load(vault, name)
|
195
207
|
item = new(vault, name)
|
196
208
|
item.load_keys(vault, "#{name}_keys")
|
197
|
-
|
209
|
+
|
198
210
|
begin
|
199
|
-
item.raw_data =
|
211
|
+
item.raw_data =
|
200
212
|
Chef::EncryptedDataBagItem.load(vault, name, item.secret).to_hash
|
201
213
|
rescue Net::HTTPServerException => http_error
|
202
214
|
if http_error.response.code == "404"
|
203
215
|
raise ChefVault::Exceptions::ItemNotFound,
|
204
|
-
|
216
|
+
"#{vault}/#{name} could not be found"
|
205
217
|
else
|
206
218
|
raise http_error
|
207
219
|
end
|
208
220
|
rescue Chef::Exceptions::ValidationFailed
|
209
221
|
raise ChefVault::Exceptions::ItemNotFound,
|
210
|
-
|
222
|
+
"#{vault}/#{name} could not be found"
|
211
223
|
end
|
212
224
|
|
213
225
|
item
|
@@ -220,7 +232,7 @@ class ChefVault::Item < Chef::DataBagItem
|
|
220
232
|
end
|
221
233
|
|
222
234
|
def reload_raw_data
|
223
|
-
@raw_data =
|
235
|
+
@raw_data =
|
224
236
|
Chef::EncryptedDataBagItem.load(@data_bag, @raw_data["id"], secret).to_hash
|
225
237
|
@encrypted = false
|
226
238
|
|
@@ -237,7 +249,7 @@ class ChefVault::Item < Chef::DataBagItem
|
|
237
249
|
admin = load_client(admin)
|
238
250
|
rescue ChefVault::Exceptions::ClientNotFound
|
239
251
|
raise ChefVault::Exceptions::AdminNotFound,
|
240
|
-
|
252
|
+
"FATAL: Could not find #{admin} in users or clients!"
|
241
253
|
end
|
242
254
|
else
|
243
255
|
raise http_error
|
@@ -253,7 +265,7 @@ class ChefVault::Item < Chef::DataBagItem
|
|
253
265
|
rescue Net::HTTPServerException => http_error
|
254
266
|
if http_error.response.code == "404"
|
255
267
|
raise ChefVault::Exceptions::ClientNotFound,
|
256
|
-
|
268
|
+
"#{client} is not a valid chef client and/or node"
|
257
269
|
else
|
258
270
|
raise http_error
|
259
271
|
end
|
data/lib/chef-vault/item_keys.rb
CHANGED
@@ -21,6 +21,7 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
21
21
|
@raw_data["id"] = name
|
22
22
|
@raw_data["admins"] = []
|
23
23
|
@raw_data["clients"] = []
|
24
|
+
@raw_data["search_query"] = []
|
24
25
|
end
|
25
26
|
|
26
27
|
def include?(key)
|
@@ -29,9 +30,9 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
29
30
|
|
30
31
|
def add(chef_client, data_bag_shared_secret, type)
|
31
32
|
public_key = OpenSSL::PKey::RSA.new chef_client.public_key
|
32
|
-
self[chef_client.name] =
|
33
|
+
self[chef_client.name] =
|
33
34
|
Base64.encode64(public_key.public_encrypt(data_bag_shared_secret))
|
34
|
-
|
35
|
+
|
35
36
|
@raw_data[type] << chef_client.name unless @raw_data[type].include?(chef_client.name)
|
36
37
|
@raw_data[type]
|
37
38
|
end
|
@@ -41,6 +42,14 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
41
42
|
raw_data[type].delete(chef_client)
|
42
43
|
end
|
43
44
|
|
45
|
+
def search_query(search_query=nil)
|
46
|
+
if search_query
|
47
|
+
@raw_data["search_query"] = search_query
|
48
|
+
else
|
49
|
+
@raw_data["search_query"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
44
53
|
def clients
|
45
54
|
@raw_data["clients"]
|
46
55
|
end
|
@@ -56,7 +65,7 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
56
65
|
data_bag_item_path = File.join(data_bag_path, item_id)
|
57
66
|
|
58
67
|
FileUtils.mkdir(data_bag_path) unless File.exists?(data_bag_path)
|
59
|
-
File.open("#{data_bag_item_path}.json",'w') do |file|
|
68
|
+
File.open("#{data_bag_item_path}.json",'w') do |file|
|
60
69
|
file.write(JSON.pretty_generate(self.raw_data))
|
61
70
|
end
|
62
71
|
|
@@ -71,7 +80,7 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
71
80
|
chef_data_bag.create
|
72
81
|
end
|
73
82
|
end
|
74
|
-
|
83
|
+
|
75
84
|
super
|
76
85
|
end
|
77
86
|
end
|
@@ -88,7 +97,7 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
88
97
|
else
|
89
98
|
super(data_bag, id)
|
90
99
|
end
|
91
|
-
end
|
100
|
+
end
|
92
101
|
|
93
102
|
def to_json(*a)
|
94
103
|
json = super
|
@@ -118,4 +127,4 @@ class ChefVault::ItemKeys < Chef::DataBagItem
|
|
118
127
|
|
119
128
|
from_data_bag_item(data_bag_item)
|
120
129
|
end
|
121
|
-
end
|
130
|
+
end
|
data/lib/chef-vault/version.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Description: Chef-Vault Decrypt class
|
2
|
+
# Copyright 2013, Nordstrom, Inc.
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
require 'chef/knife/vault_decrypt'
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class Decrypt < VaultDecrypt
|
22
|
+
|
23
|
+
include Knife::VaultBase
|
24
|
+
|
25
|
+
banner "knife decrypt VAULT ITEM [VALUES] (options)"
|
26
|
+
|
27
|
+
def run
|
28
|
+
puts "DEPRECATION WARNING: knife decrypt is deprecated. Please use knife vault decrypt instead."
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -13,89 +13,40 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
require 'chef/knife'
|
17
|
-
require 'chef
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
require 'chef/knife/vault_create'
|
18
18
|
|
19
|
-
class
|
20
|
-
|
21
|
-
|
22
|
-
require File.expand_path('../mixin/compat', __FILE__)
|
23
|
-
require File.expand_path('../mixin/helper', __FILE__)
|
24
|
-
include ChefVault::Mixin::KnifeCompat
|
25
|
-
include ChefVault::Mixin::Helper
|
26
|
-
end
|
27
|
-
|
28
|
-
banner "knife encrypt create VAULT ITEM VALUES "\
|
29
|
-
"--mode MODE --search SEARCH --admins ADMINS --json FILE --file FILE"
|
30
|
-
|
31
|
-
option :mode,
|
32
|
-
:short => '-M MODE',
|
33
|
-
:long => '--mode MODE',
|
34
|
-
:description => 'Chef mode to run in default - solo'
|
35
|
-
|
36
|
-
option :search,
|
37
|
-
:short => '-S SEARCH',
|
38
|
-
:long => '--search SEARCH',
|
39
|
-
:description => 'Chef SOLR search for clients'
|
40
|
-
|
41
|
-
option :admins,
|
42
|
-
:short => '-A ADMINS',
|
43
|
-
:long => '--admins ADMINS',
|
44
|
-
:description => 'Chef users to be added as admins'
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class EncryptCreate < VaultCreate
|
45
22
|
|
46
|
-
|
47
|
-
:short => '-J FILE',
|
48
|
-
:long => '--json FILE',
|
49
|
-
:description => 'File containing JSON data to encrypt'
|
23
|
+
include Knife::VaultBase
|
50
24
|
|
51
|
-
|
52
|
-
:long => '--file FILE',
|
53
|
-
:description => 'File to be added to vault item as file-content'
|
25
|
+
banner "knife encrypt create VAULT ITEM VALUES (options)"
|
54
26
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
search = config[:search]
|
60
|
-
admins = config[:admins]
|
61
|
-
json_file = config[:json]
|
62
|
-
file = config[:file]
|
27
|
+
option :search,
|
28
|
+
:short => '-S SEARCH',
|
29
|
+
:long => '--search SEARCH',
|
30
|
+
:description => 'Chef SOLR search for clients'
|
63
31
|
|
64
|
-
|
32
|
+
option :admins,
|
33
|
+
:short => '-A ADMINS',
|
34
|
+
:long => '--admins ADMINS',
|
35
|
+
:description => 'Chef users to be added as admins'
|
65
36
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
"#{vault_item.data_bag}/#{vault_item.id} already exists, "\
|
71
|
-
"use 'knife encrypt remove' and "\
|
72
|
-
"'knife encrypt update' to make changes."
|
73
|
-
rescue ChefVault::Exceptions::KeysNotFound,
|
74
|
-
ChefVault::Exceptions::ItemNotFound
|
75
|
-
vault_item = ChefVault::Item.new(vault, item)
|
37
|
+
option :json,
|
38
|
+
:short => '-J FILE',
|
39
|
+
:long => '--json FILE',
|
40
|
+
:description => 'File containing JSON data to encrypt'
|
76
41
|
|
77
|
-
|
78
|
-
|
79
|
-
|
42
|
+
option :file,
|
43
|
+
:long => '--file FILE',
|
44
|
+
:description => 'File to be added to vault item as file-content'
|
80
45
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
vault_item.clients(search) if search
|
87
|
-
vault_item.admins(admins) if admins
|
88
|
-
|
89
|
-
vault_item.save
|
46
|
+
def run
|
47
|
+
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
48
|
+
super
|
90
49
|
end
|
91
|
-
else
|
92
|
-
show_usage
|
93
50
|
end
|
94
51
|
end
|
95
|
-
|
96
|
-
def show_usage
|
97
|
-
super
|
98
|
-
exit 1
|
99
|
-
end
|
100
52
|
end
|
101
|
-
|
@@ -13,50 +13,21 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
require 'chef/knife'
|
17
|
-
require 'chef
|
18
|
-
|
19
|
-
class EncryptDelete < Chef::Knife
|
20
|
-
deps do
|
21
|
-
require 'chef/search/query'
|
22
|
-
require File.expand_path('../mixin/compat', __FILE__)
|
23
|
-
require File.expand_path('../mixin/helper', __FILE__)
|
24
|
-
include ChefVault::Mixin::KnifeCompat
|
25
|
-
include ChefVault::Mixin::Helper
|
26
|
-
end
|
27
|
-
|
28
|
-
banner "knife encrypt delete VAULT ITEM --mode MODE"
|
29
|
-
|
30
|
-
option :mode,
|
31
|
-
:short => '-M MODE',
|
32
|
-
:long => '--mode MODE',
|
33
|
-
:description => 'Chef mode to run in default - solo'
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
require 'chef/knife/vault_delete'
|
34
18
|
|
35
|
-
|
36
|
-
|
37
|
-
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class EncryptDelete < VaultDelete
|
38
22
|
|
39
|
-
|
23
|
+
include Knife::VaultBase
|
40
24
|
|
41
|
-
|
42
|
-
delete_object(ChefVault::Item, "#{vault}/#{item}", "chef_vault_item") do
|
43
|
-
begin
|
44
|
-
ChefVault::Item.load(vault, item).destroy
|
45
|
-
rescue ChefVault::Exceptions::KeysNotFound,
|
46
|
-
ChefVault::Exceptions::ItemNotFound
|
25
|
+
banner "knife encrypt delete VAULT ITEM (options)"
|
47
26
|
|
48
|
-
|
49
|
-
|
50
|
-
|
27
|
+
def run
|
28
|
+
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
29
|
+
super
|
51
30
|
end
|
52
|
-
else
|
53
|
-
show_usage
|
54
31
|
end
|
55
32
|
end
|
56
|
-
|
57
|
-
def show_usage
|
58
|
-
super
|
59
|
-
exit 1
|
60
|
-
end
|
61
33
|
end
|
62
|
-
|
@@ -13,88 +13,31 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
require 'chef/knife'
|
17
|
-
require 'chef
|
16
|
+
require 'chef/knife/vault_base'
|
17
|
+
require 'chef/knife/vault_remove'
|
18
18
|
|
19
|
-
class
|
20
|
-
|
21
|
-
|
22
|
-
require File.expand_path('../mixin/compat', __FILE__)
|
23
|
-
require File.expand_path('../mixin/helper', __FILE__)
|
24
|
-
include ChefVault::Mixin::KnifeCompat
|
25
|
-
include ChefVault::Mixin::Helper
|
26
|
-
end
|
27
|
-
|
28
|
-
banner "knife encrypt remove VAULT ITEM VALUES "\
|
29
|
-
"--mode MODE --search SEARCH --admins ADMINS"
|
30
|
-
|
31
|
-
option :mode,
|
32
|
-
:short => '-M MODE',
|
33
|
-
:long => '--mode MODE',
|
34
|
-
:description => 'Chef mode to run in default - solo'
|
35
|
-
|
36
|
-
option :search,
|
37
|
-
:short => '-S SEARCH',
|
38
|
-
:long => '--search SEARCH',
|
39
|
-
:description => 'Chef SOLR search for clients'
|
40
|
-
|
41
|
-
option :admins,
|
42
|
-
:short => '-A ADMINS',
|
43
|
-
:long => '--admins ADMINS',
|
44
|
-
:description => 'Chef users to be added as admins'
|
45
|
-
|
46
|
-
def run
|
47
|
-
vault = @name_args[0]
|
48
|
-
item = @name_args[1]
|
49
|
-
values = @name_args[2]
|
50
|
-
search = config[:search]
|
51
|
-
admins = config[:admins]
|
52
|
-
json_file = config[:json]
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class EncryptRemove < VaultRemove
|
53
22
|
|
54
|
-
|
23
|
+
include Knife::VaultBase
|
55
24
|
|
56
|
-
|
57
|
-
begin
|
58
|
-
vault_item = ChefVault::Item.load(vault, item)
|
59
|
-
remove_items = []
|
25
|
+
banner "knife encrypt remove VAULT ITEM VALUES (options)"
|
60
26
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
remove_items << key
|
66
|
-
end
|
67
|
-
rescue JSON::ParserError
|
68
|
-
remove_items = values.split(",")
|
69
|
-
rescue Exception => e
|
70
|
-
raise e
|
71
|
-
end
|
27
|
+
option :search,
|
28
|
+
:short => '-S SEARCH',
|
29
|
+
:long => '--search SEARCH',
|
30
|
+
:description => 'Chef SOLR search for clients'
|
72
31
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
32
|
+
option :admins,
|
33
|
+
:short => '-A ADMINS',
|
34
|
+
:long => '--admins ADMINS',
|
35
|
+
:description => 'Chef users to be added as admins'
|
78
36
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
vault_item.rotate_keys!
|
83
|
-
rescue ChefVault::Exceptions::KeysNotFound,
|
84
|
-
ChefVault::Exceptions::ItemNotFound
|
85
|
-
|
86
|
-
raise ChefVault::Exceptions::ItemNotFound,
|
87
|
-
"#{vault}/#{item} does not exists, "\
|
88
|
-
"use 'knife encrypt create' to create."
|
37
|
+
def run
|
38
|
+
puts "DEPRECATION WARNING: knife encrypt is deprecated. Please use knife vault instead."
|
39
|
+
super
|
89
40
|
end
|
90
|
-
else
|
91
|
-
show_usage
|
92
41
|
end
|
93
42
|
end
|
94
|
-
|
95
|
-
def show_usage
|
96
|
-
super
|
97
|
-
exit 1
|
98
|
-
end
|
99
43
|
end
|
100
|
-
|