chef-vault 1.2.5 → 2.0.1.pre
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 +15 -0
- data/Changelog.md +17 -0
- data/KNIFE_EXAMPLES.md +169 -0
- data/README.md +83 -106
- data/bin/chef-vault +25 -19
- data/lib/chef-vault.rb +17 -9
- data/lib/chef-vault/certificate.rb +7 -28
- data/lib/chef-vault/chef_patch/api_client.rb +40 -0
- data/lib/chef-vault/chef_patch/user.rb +33 -0
- data/lib/chef-vault/exceptions.rb +27 -0
- data/lib/chef-vault/item.rb +243 -0
- data/lib/chef-vault/item_keys.rb +121 -0
- data/lib/chef-vault/user.rb +7 -28
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef/knife/Decrypt.rb +64 -0
- data/lib/chef/knife/encrypt_create.rb +91 -0
- data/lib/chef/knife/encrypt_delete.rb +62 -0
- data/lib/chef/knife/encrypt_remove.rb +100 -0
- data/lib/chef/knife/encrypt_rotate_keys.rb +62 -0
- data/lib/chef/knife/encrypt_update.rb +90 -0
- data/lib/{chef-vault/chef/offline.rb → chef/knife/mixin/compat.rb} +15 -11
- data/lib/chef/knife/mixin/helper.rb +50 -0
- data/spec/chef-vault_spec.rb +19 -30
- data/spec/item_keys_spec.rb +29 -0
- data/spec/item_spec.rb +33 -0
- metadata +23 -21
- data/lib/chef/knife/DecryptCert.rb +0 -59
- data/lib/chef/knife/DecryptPassword.rb +0 -58
- data/lib/chef/knife/EncryptCert.rb +0 -185
- data/lib/chef/knife/EncryptPassword.rb +0 -182
- data/lib/chef/knife/compat.rb +0 -71
data/lib/chef-vault.rb
CHANGED
@@ -17,19 +17,23 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef'
|
20
|
+
require 'chef/user'
|
21
|
+
require 'chef-vault/version'
|
22
|
+
require 'chef-vault/exceptions'
|
23
|
+
require 'chef-vault/item'
|
24
|
+
require 'chef-vault/item_keys'
|
20
25
|
require 'chef-vault/user'
|
21
26
|
require 'chef-vault/certificate'
|
22
|
-
require 'chef-vault/
|
23
|
-
require 'chef-vault/
|
27
|
+
require 'chef-vault/chef_patch/api_client'
|
28
|
+
require 'chef-vault/chef_patch/user'
|
24
29
|
|
25
30
|
class ChefVault
|
26
31
|
|
27
|
-
attr_accessor :
|
28
|
-
attr_accessor :chef_config_file
|
32
|
+
attr_accessor :vault
|
29
33
|
|
30
|
-
def initialize(
|
31
|
-
@
|
32
|
-
|
34
|
+
def initialize(vault, chef_config_file=nil)
|
35
|
+
@vault = vault
|
36
|
+
ChefVault.load_config(chef_config_file) if chef_config_file
|
33
37
|
end
|
34
38
|
|
35
39
|
def version
|
@@ -37,10 +41,14 @@ class ChefVault
|
|
37
41
|
end
|
38
42
|
|
39
43
|
def user(username)
|
40
|
-
ChefVault::User.new(
|
44
|
+
ChefVault::User.new(vault, username)
|
41
45
|
end
|
42
46
|
|
43
47
|
def certificate(name)
|
44
|
-
ChefVault::Certificate.new(
|
48
|
+
ChefVault::Certificate.new(vault, name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.load_config(chef_config_file)
|
52
|
+
Chef::Config.from_file(chef_config_file)
|
45
53
|
end
|
46
54
|
end
|
@@ -15,38 +15,17 @@
|
|
15
15
|
|
16
16
|
class ChefVault
|
17
17
|
class Certificate
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@name = name
|
22
|
-
@data_bag = data_bag
|
18
|
+
def initialize(vault, name)
|
19
|
+
@item = ChefVault::Item.load(vault, name)
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
chef.connect
|
27
|
-
end
|
22
|
+
def [](key)
|
23
|
+
@item[key]
|
28
24
|
end
|
29
25
|
|
30
26
|
def decrypt_contents
|
31
|
-
|
32
|
-
|
33
|
-
private_key = OpenSSL::PKey::RSA.new(private_key)
|
34
|
-
|
35
|
-
begin
|
36
|
-
keys = Chef::DataBagItem.load(@data_bag, "#{name}_keys")
|
37
|
-
rescue
|
38
|
-
throw "Could not find data bag item #{name}_keys in data bag #{@data_bag}"
|
39
|
-
end
|
40
|
-
|
41
|
-
unless keys[Chef::Config[:node_name]]
|
42
|
-
throw "#{name} is not encrypted for you! Rebuild the certificate data bag"
|
43
|
-
end
|
44
|
-
|
45
|
-
node_key = Base64.decode64(keys[Chef::Config[:node_name]])
|
46
|
-
shared_secret = private_key.private_decrypt(node_key)
|
47
|
-
certificate = Chef::EncryptedDataBagItem.load(@data_bag, @name, shared_secret)
|
48
|
-
|
49
|
-
certificate["contents"]
|
27
|
+
puts "WARNING: This method is deprecated, please switch to item['value'] calls"
|
28
|
+
@item["contents"]
|
50
29
|
end
|
51
30
|
end
|
52
31
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Author:: Kevin Moser <kevin.moser@nordstrom.com>
|
2
|
+
# Copyright:: Copyright 2013, Nordstrom, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class ChefVault
|
18
|
+
module ChefPatch
|
19
|
+
class ApiClient < Chef::ApiClient
|
20
|
+
# Fix an issue where core Chef::ApiClient does not load
|
21
|
+
# the private key for Chef 10
|
22
|
+
def self.load(name)
|
23
|
+
response = http_api.get("clients/#{name}")
|
24
|
+
if response.kind_of?(Chef::ApiClient)
|
25
|
+
response
|
26
|
+
else
|
27
|
+
client = Chef::ApiClient.new
|
28
|
+
client.name(response['clientname'])
|
29
|
+
|
30
|
+
if response['certificate']
|
31
|
+
der = OpenSSL::X509::Certificate.new response['certificate']
|
32
|
+
client.public_key der.public_key.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
client
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Author:: Kevin Moser <kevin.moser@nordstrom.com>
|
2
|
+
# Copyright:: Copyright 2013, Nordstrom, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class ChefVault
|
18
|
+
module ChefPatch
|
19
|
+
class User < Chef::User
|
20
|
+
# def from_hash for our implementation because name is not being
|
21
|
+
# set correctly for Chef 10 server
|
22
|
+
def superclass.from_hash(user_hash)
|
23
|
+
user = Chef::User.new
|
24
|
+
user.name user_hash['username'] ? user_hash['username'] : user_hash['name']
|
25
|
+
user.private_key user_hash['private_key'] if user_hash.key?('private_key')
|
26
|
+
user.password user_hash['password'] if user_hash.key?('password')
|
27
|
+
user.public_key user_hash['public_key']
|
28
|
+
user.admin user_hash['admin']
|
29
|
+
user
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Author:: Kevin Moser <kevin.moser@nordstrom.com>
|
2
|
+
# Copyright:: Copyright 2013, Nordstrom, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class ChefVault::Exceptions
|
18
|
+
class SecretDecryption < RuntimeError; end
|
19
|
+
class NoKeysDefined < RuntimeError; end
|
20
|
+
class ItemNotEncrypted < RuntimeError; end
|
21
|
+
class KeysActionNotValue < RuntimeError; end
|
22
|
+
class AdminNotFound < RuntimeError; end
|
23
|
+
class ClientNotFound < RuntimeError; end
|
24
|
+
class KeysNotFound < RuntimeError; end
|
25
|
+
class ItemNotFound < RuntimeError; end
|
26
|
+
class ItemAlreadyExists < RuntimeError; end
|
27
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
# Author:: Kevin Moser <kevin.moser@nordstrom.com>
|
2
|
+
# Copyright:: Copyright 2013, Nordstrom, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class ChefVault::Item < Chef::DataBagItem
|
18
|
+
attr_accessor :keys
|
19
|
+
attr_accessor :encrypted_data_bag_item
|
20
|
+
|
21
|
+
def initialize(vault, name)
|
22
|
+
super() # Don't pass parameters
|
23
|
+
@data_bag = vault
|
24
|
+
@raw_data["id"] = name
|
25
|
+
@keys = ChefVault::ItemKeys.new(vault, "#{name}_keys")
|
26
|
+
@secret = generate_secret
|
27
|
+
@encrypted = false
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_keys(vault, keys)
|
31
|
+
@keys = ChefVault::ItemKeys.load(vault, keys)
|
32
|
+
@secret = secret
|
33
|
+
end
|
34
|
+
|
35
|
+
def clients(search=nil, action=:add)
|
36
|
+
if search
|
37
|
+
results_returned = false
|
38
|
+
|
39
|
+
query = Chef::Search::Query.new
|
40
|
+
query.search(:node, search)[0].each do |node|
|
41
|
+
results_returned = true
|
42
|
+
|
43
|
+
case action
|
44
|
+
when :add
|
45
|
+
begin
|
46
|
+
keys.add(ChefVault::ChefPatch::ApiClient.load(node.name), @secret, "clients")
|
47
|
+
rescue Net::HTTPServerException => http_error
|
48
|
+
if http_error.response.code == "404"
|
49
|
+
raise ChefVault::Exceptions::ClientNotFound,
|
50
|
+
"#{node.name} is not a valid chef client and/or node"
|
51
|
+
else
|
52
|
+
raise http_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
when :delete
|
56
|
+
keys.delete(node.name, "clients")
|
57
|
+
else
|
58
|
+
raise ChefVault::Exceptions::KeysActionNotValid,
|
59
|
+
"#{action} is not a valid action"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
unless results_returned
|
64
|
+
puts "WARNING: No clients were returned from search, you may not have "\
|
65
|
+
"got what you expected!!"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
keys.clients
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def admins(admins=nil, action=:add)
|
73
|
+
if admins
|
74
|
+
admins.split(",").each do |admin|
|
75
|
+
admin.strip!
|
76
|
+
case action
|
77
|
+
when :add
|
78
|
+
begin
|
79
|
+
keys.add(ChefVault::ChefPatch::User.load(admin), @secret, "admins")
|
80
|
+
rescue Net::HTTPServerException => http_error
|
81
|
+
if http_error.response.code == "404"
|
82
|
+
raise ChefVault::Exceptions::AdminNotFound,
|
83
|
+
"#{admin} is not a valid chef admin"
|
84
|
+
else
|
85
|
+
raise http_error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when :delete
|
89
|
+
keys.delete(admin, "admins")
|
90
|
+
else
|
91
|
+
raise ChefVault::Exceptions::KeysActionNotValid,
|
92
|
+
"#{action} is not a valid action"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
else
|
96
|
+
keys.admins
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def remove(key)
|
101
|
+
@raw_data.delete(key)
|
102
|
+
end
|
103
|
+
|
104
|
+
def secret
|
105
|
+
if @keys.include?(Chef::Config[:node_name])
|
106
|
+
private_key = OpenSSL::PKey::RSA.new(open(Chef::Config[:client_key]).read())
|
107
|
+
private_key.private_decrypt(Base64.decode64(@keys[Chef::Config[:node_name]]))
|
108
|
+
else
|
109
|
+
raise ChefVault::Exceptions::SecretDecryption,
|
110
|
+
"#{data_bag}/#{id} is not encrypted with your public key. "\
|
111
|
+
"Contact an administrator of the vault item to encrypt for you!"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def rotate_keys!
|
116
|
+
@secret = generate_secret
|
117
|
+
|
118
|
+
unless clients.empty?
|
119
|
+
clients.each do |client|
|
120
|
+
clients("name:#{client}")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
unless admins.empty?
|
125
|
+
admins.each do |admin|
|
126
|
+
admins(admin)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
save
|
131
|
+
reload_raw_data
|
132
|
+
end
|
133
|
+
|
134
|
+
def generate_secret
|
135
|
+
OpenSSL::PKey::RSA.new(245).to_pem.lines.to_a[1..-2].join
|
136
|
+
end
|
137
|
+
|
138
|
+
def []=(key, value)
|
139
|
+
reload_raw_data if @encrypted
|
140
|
+
super
|
141
|
+
end
|
142
|
+
|
143
|
+
def [](key)
|
144
|
+
reload_raw_data if @encrypted
|
145
|
+
super
|
146
|
+
end
|
147
|
+
|
148
|
+
def save(item_id=@raw_data['id'])
|
149
|
+
# save the keys first, raising an error if no keys were defined
|
150
|
+
if keys.admins.empty? && keys.clients.empty?
|
151
|
+
raise ChefVault::Exceptions::NoKeysDefined,
|
152
|
+
"No keys defined for #{item_id}"
|
153
|
+
end
|
154
|
+
|
155
|
+
keys.save
|
156
|
+
|
157
|
+
# Make sure the item is encrypted before saving
|
158
|
+
encrypt! unless @encrypted
|
159
|
+
|
160
|
+
# Now save the encrypted data
|
161
|
+
if Chef::Config[:solo]
|
162
|
+
data_bag_path = File.join(Chef::Config[:data_bag_path],
|
163
|
+
data_bag)
|
164
|
+
data_bag_item_path = File.join(data_bag_path, item_id)
|
165
|
+
|
166
|
+
FileUtils.mkdir(data_bag_path) unless File.exists?(data_bag_path)
|
167
|
+
File.open("#{data_bag_item_path}.json",'w') do |file|
|
168
|
+
file.write(JSON.pretty_generate(self))
|
169
|
+
end
|
170
|
+
|
171
|
+
self
|
172
|
+
else
|
173
|
+
begin
|
174
|
+
chef_data_bag = Chef::DataBag.load(data_bag)
|
175
|
+
rescue Net::HTTPServerException => http_error
|
176
|
+
if http_error.response.code == "404"
|
177
|
+
chef_data_bag = Chef::DataBag.new
|
178
|
+
chef_data_bag.name data_bag
|
179
|
+
chef_data_bag.create
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
super
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_json(*a)
|
188
|
+
json = super
|
189
|
+
json.gsub(self.class.name, self.class.superclass.name)
|
190
|
+
end
|
191
|
+
|
192
|
+
def destroy
|
193
|
+
keys.destroy
|
194
|
+
|
195
|
+
if Chef::Config[:solo]
|
196
|
+
data_bag_path = File.join(Chef::Config[:data_bag_path],
|
197
|
+
data_bag)
|
198
|
+
data_bag_item_path = File.join(data_bag_path, @raw_data["id"])
|
199
|
+
|
200
|
+
FileUtils.rm("#{data_bag_item_path}.json")
|
201
|
+
|
202
|
+
nil
|
203
|
+
else
|
204
|
+
super(data_bag, id)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.load(vault, name)
|
209
|
+
item = new(vault, name)
|
210
|
+
item.load_keys(vault, "#{name}_keys")
|
211
|
+
|
212
|
+
begin
|
213
|
+
item.raw_data =
|
214
|
+
Chef::EncryptedDataBagItem.load(vault, name, item.secret).to_hash
|
215
|
+
rescue Net::HTTPServerException => http_error
|
216
|
+
if http_error.response.code == "404"
|
217
|
+
raise ChefVault::Exceptions::ItemNotFound,
|
218
|
+
"#{vault}/#{name} could not be found"
|
219
|
+
else
|
220
|
+
raise http_error
|
221
|
+
end
|
222
|
+
rescue Chef::Exceptions::ValidationFailed
|
223
|
+
raise ChefVault::Exceptions::ItemNotFound,
|
224
|
+
"#{vault}/#{name} could not be found"
|
225
|
+
end
|
226
|
+
|
227
|
+
item
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
def encrypt!
|
232
|
+
@raw_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(self, @secret)
|
233
|
+
@encrypted = true
|
234
|
+
end
|
235
|
+
|
236
|
+
def reload_raw_data
|
237
|
+
@raw_data =
|
238
|
+
Chef::EncryptedDataBagItem.load(@data_bag, @raw_data["id"], secret).to_hash
|
239
|
+
@encrypted = false
|
240
|
+
|
241
|
+
@raw_data
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Author:: Kevin Moser <kevin.moser@nordstrom.com>
|
2
|
+
# Copyright:: Copyright 2013, Nordstrom, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class ChefVault::ItemKeys < Chef::DataBagItem
|
18
|
+
def initialize(vault, name)
|
19
|
+
super() # parenthesis required to strip off parameters
|
20
|
+
@data_bag = vault
|
21
|
+
@raw_data["id"] = name
|
22
|
+
@raw_data["admins"] = []
|
23
|
+
@raw_data["clients"] = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def include?(key)
|
27
|
+
@raw_data.keys.include?(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def add(chef_client, data_bag_shared_secret, type)
|
31
|
+
public_key = OpenSSL::PKey::RSA.new chef_client.public_key
|
32
|
+
self[chef_client.name] =
|
33
|
+
Base64.encode64(public_key.public_encrypt(data_bag_shared_secret))
|
34
|
+
|
35
|
+
@raw_data[type] << chef_client.name unless @raw_data[type].include?(chef_client.name)
|
36
|
+
@raw_data[type]
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(chef_client, type)
|
40
|
+
raw_data.delete(chef_client)
|
41
|
+
raw_data[type].delete(chef_client)
|
42
|
+
end
|
43
|
+
|
44
|
+
def clients
|
45
|
+
@raw_data["clients"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def admins
|
49
|
+
@raw_data["admins"]
|
50
|
+
end
|
51
|
+
|
52
|
+
def save(item_id=@raw_data['id'])
|
53
|
+
if Chef::Config[:solo]
|
54
|
+
data_bag_path = File.join(Chef::Config[:data_bag_path],
|
55
|
+
data_bag)
|
56
|
+
data_bag_item_path = File.join(data_bag_path, item_id)
|
57
|
+
|
58
|
+
FileUtils.mkdir(data_bag_path) unless File.exists?(data_bag_path)
|
59
|
+
File.open("#{data_bag_item_path}.json",'w') do |file|
|
60
|
+
file.write(JSON.pretty_generate(self))
|
61
|
+
end
|
62
|
+
|
63
|
+
self
|
64
|
+
else
|
65
|
+
begin
|
66
|
+
chef_data_bag = Chef::DataBag.load(data_bag)
|
67
|
+
rescue Net::HTTPServerException => http_error
|
68
|
+
if http_error.response.code == "404"
|
69
|
+
chef_data_bag = Chef::DataBag.new
|
70
|
+
chef_data_bag.name data_bag
|
71
|
+
chef_data_bag.create
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def destroy
|
80
|
+
if Chef::Config[:solo]
|
81
|
+
data_bag_path = File.join(Chef::Config[:data_bag_path],
|
82
|
+
data_bag)
|
83
|
+
data_bag_item_path = File.join(data_bag_path, @raw_data["id"])
|
84
|
+
|
85
|
+
FileUtils.rm("#{data_bag_item_path}.json")
|
86
|
+
|
87
|
+
nil
|
88
|
+
else
|
89
|
+
super(data_bag, id)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_json(*a)
|
94
|
+
json = super
|
95
|
+
json.gsub(self.class.name, self.class.superclass.name)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.from_data_bag_item(data_bag_item)
|
99
|
+
item = new(data_bag_item.data_bag, data_bag_item.name)
|
100
|
+
item.raw_data = data_bag_item.raw_data
|
101
|
+
item
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.load(vault, name)
|
105
|
+
begin
|
106
|
+
data_bag_item = Chef::DataBagItem.load(vault, name)
|
107
|
+
rescue Net::HTTPServerException => http_error
|
108
|
+
if http_error.response.code == "404"
|
109
|
+
raise ChefVault::Exceptions::KeysNotFound,
|
110
|
+
"#{vault}/#{name} could not be found"
|
111
|
+
else
|
112
|
+
raise http_error
|
113
|
+
end
|
114
|
+
rescue Chef::Exceptions::ValidationFailed
|
115
|
+
raise ChefVault::Exceptions::KeysNotFound,
|
116
|
+
"#{vault}/#{name} could not be found"
|
117
|
+
end
|
118
|
+
|
119
|
+
from_data_bag_item(data_bag_item)
|
120
|
+
end
|
121
|
+
end
|