chef-vault 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|