chef-encrypted-attributes 0.3.0 → 0.4.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.yardopts +8 -0
  5. data/CHANGELOG.md +40 -4
  6. data/CONTRIBUTING.md +7 -6
  7. data/KNIFE.md +151 -0
  8. data/README.md +70 -192
  9. data/Rakefile +27 -14
  10. data/TESTING.md +18 -7
  11. data/TODO.md +2 -5
  12. data/lib/chef-encrypted-attributes.rb +7 -1
  13. data/lib/chef/encrypted_attribute.rb +282 -121
  14. data/lib/chef/encrypted_attribute/api.rb +521 -0
  15. data/lib/chef/encrypted_attribute/assertions.rb +16 -6
  16. data/lib/chef/encrypted_attribute/cache_lru.rb +54 -13
  17. data/lib/chef/encrypted_attribute/config.rb +198 -89
  18. data/lib/chef/encrypted_attribute/encrypted_mash.rb +127 -33
  19. data/lib/chef/encrypted_attribute/encrypted_mash/version0.rb +236 -48
  20. data/lib/chef/encrypted_attribute/encrypted_mash/version1.rb +249 -36
  21. data/lib/chef/encrypted_attribute/encrypted_mash/version2.rb +133 -19
  22. data/lib/chef/encrypted_attribute/exceptions.rb +19 -3
  23. data/lib/chef/encrypted_attribute/local_node.rb +15 -4
  24. data/lib/chef/encrypted_attribute/remote_clients.rb +33 -17
  25. data/lib/chef/encrypted_attribute/remote_node.rb +84 -29
  26. data/lib/chef/encrypted_attribute/remote_nodes.rb +62 -11
  27. data/lib/chef/encrypted_attribute/remote_users.rb +58 -19
  28. data/lib/chef/encrypted_attribute/search_helper.rb +214 -74
  29. data/lib/chef/encrypted_attribute/version.rb +3 -1
  30. data/lib/chef/encrypted_attributes.rb +20 -0
  31. data/lib/chef/knife/core/config.rb +4 -1
  32. data/lib/chef/knife/core/encrypted_attribute_base.rb +179 -0
  33. data/lib/chef/knife/core/encrypted_attribute_depends.rb +43 -0
  34. data/lib/chef/knife/core/encrypted_attribute_editor_options.rb +125 -61
  35. data/lib/chef/knife/encrypted_attribute_create.rb +51 -31
  36. data/lib/chef/knife/encrypted_attribute_delete.rb +32 -40
  37. data/lib/chef/knife/encrypted_attribute_edit.rb +51 -32
  38. data/lib/chef/knife/encrypted_attribute_show.rb +30 -55
  39. data/lib/chef/knife/encrypted_attribute_update.rb +43 -28
  40. data/spec/benchmark_helper.rb +2 -1
  41. data/spec/integration_helper.rb +1 -0
  42. data/spec/spec_helper.rb +21 -7
  43. metadata +75 -36
  44. metadata.gz.sig +1 -1
  45. data/API.md +0 -174
  46. data/INTERNAL.md +0 -166
@@ -0,0 +1,521 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Xabier de Zuazo (<xabier@onddo.com>)
4
+ # Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/encrypted_attribute/config'
21
+ require 'chef/encrypted_attribute/encrypted_mash'
22
+ require 'chef/config'
23
+
24
+ require 'chef/encrypted_attribute/local_node'
25
+ require 'chef/encrypted_attribute/remote_node'
26
+ require 'chef/encrypted_attribute/encrypted_mash/version0'
27
+ require 'chef/encrypted_attribute/encrypted_mash/version1'
28
+ require 'chef/encrypted_attribute/encrypted_mash/version2'
29
+
30
+ class Chef
31
+ class EncryptedAttribute
32
+ # Main EncryptedAttribute class methods API module.
33
+ #
34
+ # All these methods are available as static methods in the
35
+ # {Chef::EncryptedAttribute} class.
36
+ #
37
+ # These methods are intended to be used from Chef
38
+ # [Recipes](http://docs.getchef.com/recipes.html) or
39
+ # [Resources](https://docs.getchef.com/resource.html).
40
+ #
41
+ # The attributes created by these methods are encrypted **only for the local
42
+ # node** by default.
43
+ #
44
+ # The static `*_on_node` methods can be used, although they have not been
45
+ # designed for this purpose (have not been tested).
46
+ #
47
+ # This module uses the {Chef::EncryptedAttribute} instance methods
48
+ # internally.
49
+ #
50
+ # # Configuration
51
+ #
52
+ # All the methods read the default configuration from the
53
+ # `Chef::Config[:encrypted_attributes]` hash. Most of methods also support
54
+ # setting some configuration parameters as last argument. Both the global
55
+ # and the method argument configuration will be merged.
56
+ #
57
+ # If the configuration value to be merged is an array or a hash (for example
58
+ # `keys`), the method argument configuration value has preference over the
59
+ # global configuration. arrays and hashes are not merged.
60
+ #
61
+ # Both `Chef::Config[:encrypted_attributes]` and method's `config` parameter
62
+ # should be a hash which may have any of the following keys:
63
+ #
64
+ # * `:version` - `EncryptedMash` format version to use, by default `1` is
65
+ # used which is recommended. The version `2` uses [GCM]
66
+ # (http://en.wikipedia.org/wiki/Galois/Counter_Mode) and probably should
67
+ # be considered the most secure, but it is disabled by default because it
68
+ # has some more requirements: Ruby `>= 2` and OpenSSL `>= 1.0.1`.
69
+ # * `:partial_search` - Whether to use Chef Server partial search, enabled
70
+ # by default. It may not work in some old versions of Chef Server.
71
+ # * `:client_search` - Search query for clients allowed to read the
72
+ # encrypted attribute. Can be a simple string or an array of queries to be
73
+ # *OR*-ed.
74
+ # * `:node_search` - Search query for nodes allowed to read the encrypted
75
+ # attribute. Can be a simple string or an array of queries to be *OR*-ed.
76
+ # * `:users` - Array of user names to be allowed to read the encrypted
77
+ # attribute(s). `"*"` to allow access to all users. Keep in mind that only
78
+ # admin clients or admin users are allowed to read user public keys. It is
79
+ # **not recommended** to use this from cookbooks unless you know what you
80
+ # are doing.
81
+ # * `:keys` - raw RSA public keys to be allowed to read encrypted
82
+ # attributes(s), in PEM (string) format. Can be client public keys, user
83
+ # public keys or any other RSA public key.
84
+ #
85
+ # @see Config
86
+ #
87
+ # For example, to disable Partial Search globally:
88
+ #
89
+ # ```ruby
90
+ # Chef::Config[:encrypted_attributes][:partial_search] = false
91
+ #
92
+ # # ftp_pass = Chef::EncryptedAttribute.load(node['myapp']['ftp_password'])
93
+ # # ...
94
+ # ```
95
+ #
96
+ # To disable Partial Search locally:
97
+ #
98
+ # ```ruby
99
+ # ftp_pass = Chef::EncryptedAttribute.load(
100
+ # node['myapp']['ftp_password'], { :partial_search => false }
101
+ # )
102
+ # ```
103
+ #
104
+ # To use protocol version 2 globally, which uses [GCM]
105
+ # (http://en.wikipedia.org/wiki/Galois/Counter_Mode):
106
+ #
107
+ # ```ruby
108
+ # Chef::Config[:encrypted_attributes][:version] = 2
109
+ # # ...
110
+ # ```
111
+ #
112
+ # If you want to use knife to work with encrypted attributes, surely you
113
+ # will need to save your Chef User public keys in a Data Bag (there is no
114
+ # need to encrypt them because they are public) and add them to the `:keys`
115
+ # configuration option. See the [Example Using User Keys Data Bag]
116
+ # (README.md#example-using-user-keys-data-bag) in the README for more
117
+ # information on this.
118
+ #
119
+ # # Caches
120
+ #
121
+ # This API uses some LRU caches to avoid making many requests to the Chef
122
+ # Server. All the caches are global and has the following methods:
123
+ #
124
+ # * `max_size` - Gets or sets the cache maximum item size.
125
+ # * `clear` - To empty the cache.
126
+ # * `[]` - To read a cache value (used internally).
127
+ # * `[]=` - To set a cache value (used internally).
128
+ #
129
+ # @see CacheLru
130
+ #
131
+ # This are the currently available caches:
132
+ #
133
+ # * `Chef::EncryptedAttribute::RemoteClients.cache` - Caches the
134
+ # `:client_search` query results (max_size: `1024`).
135
+ # * `Chef::EncryptedAttribute::RemoteNodes.cache` - Caches the
136
+ # `:node_search` query results (max_size: `1024`).
137
+ # * `Chef::EncryptedAttribute::RemoteUsers.cache` - Caches the Chef Users
138
+ # public keys (max_size: `1024`).
139
+ # * `Chef::EncryptedAttribute::RemoteNode.cache` - Caches the node
140
+ # (encrypted) attributes. Disabled by default (max_size: `0`).
141
+ #
142
+ # ### Clear All the Caches
143
+ #
144
+ # You can clear all the caches with the following code:
145
+ #
146
+ # ```ruby
147
+ # Chef::EncryptedAttribute::RemoteClients.cache.clear
148
+ # Chef::EncryptedAttribute::RemoteNodes.cache.clear
149
+ # Chef::EncryptedAttribute::RemoteUsers.cache.clear
150
+ # Chef::EncryptedAttribute::RemoteNode.cache.clear
151
+ # ```
152
+ #
153
+ # ### Disable All the Caches
154
+ #
155
+ # You can disable all the caches with the following code:
156
+ #
157
+ # ```ruby
158
+ # Chef::EncryptedAttribute::RemoteClients.cache.max_size(0)
159
+ # Chef::EncryptedAttribute::RemoteNodes.cache.max_size(0)
160
+ # Chef::EncryptedAttribute::RemoteUsers.cache.max_size(0)
161
+ # Chef::EncryptedAttribute::RemoteNode.cache.max_size(0)
162
+ # ```
163
+ #
164
+ # @see RemoteClients.cache
165
+ # @see RemoteNodes.cache
166
+ # @see RemoteUsers.cache
167
+ # @see RemoteNode.cache
168
+ module API
169
+ # Prints a Chef debug message.
170
+ #
171
+ # @param msg [String] message to print.
172
+ # @return void
173
+ # @api private
174
+ def debug(msg)
175
+ Chef::Log.debug("Chef::EncryptedAttribute: #{msg}")
176
+ end
177
+
178
+ # Prints a Chef warning message.
179
+ #
180
+ # @param msg [String] message to print.
181
+ # @return void
182
+ # @api private
183
+ def warn(msg)
184
+ Chef::Log.warn(msg)
185
+ end
186
+
187
+ # Gets local node object.
188
+ #
189
+ # @return [LocalNode] local node object.
190
+ # @api private
191
+ def local_node
192
+ LocalNode.new
193
+ end
194
+
195
+ # Creates a new {Config} object.
196
+ #
197
+ # Reads the default configuration from
198
+ # `Chef::Config[:encrypted_attributes]`.
199
+ #
200
+ # When the parameter is a {Chef::EncryptedAttribute::Config} class, all
201
+ # the configuration options will be replaced.
202
+ #
203
+ # When the parameter is a _Hash_, only the provided keys will be replaced.
204
+ #
205
+ # The local node public key will always be added to the provided
206
+ # configuration keys.
207
+ #
208
+ # @param arg [Config, Hash] the configuration to set.
209
+ # @return [Config] the read or set configuration object.
210
+ # @api private
211
+ def config(arg)
212
+ config =
213
+ EncryptedAttribute::Config.new(Chef::Config[:encrypted_attributes])
214
+ config.update!(arg)
215
+ config.keys(config.keys + [local_node.public_key])
216
+ config
217
+ end
218
+
219
+ # Reads an encrypted attribute from a hash, usually a node attribute.
220
+ #
221
+ # Uses the local private key to decrypt the attribute.
222
+ #
223
+ # An exception is thrown if the attribute cannot be decrypted or no
224
+ # encrypted attribute is found.
225
+ #
226
+ # @param enc_hs [Mash] an encrypted hash, usually a node attribute. For
227
+ # example: `node['myapp']['ftp_password']`.
228
+ # @param c [Config, Hash] a configuration hash. For example:
229
+ # `{ :partial_search => false }`.
230
+ # @return [Hash, Array, String, ...] the attribute in clear text,
231
+ # decrypted.
232
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
233
+ # format is wrong.
234
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
235
+ # format is not supported or unknown.
236
+ def load(enc_hs, c = {})
237
+ debug("Loading Local Encrypted Attribute from: #{enc_hs.inspect}")
238
+ enc_attr = EncryptedAttribute.new(config(c))
239
+ result = enc_attr.load(enc_hs)
240
+ debug('Local Encrypted Attribute loaded.')
241
+ result
242
+ end
243
+
244
+ # Reads an encrypted attribute from a remote node.
245
+ #
246
+ # Uses the local private key to decrypt the attribute.
247
+ #
248
+ # An exception is thrown if the attribute cannot be decrypted or no
249
+ # encrypted attribute is found.
250
+ #
251
+ # @param name [String] the node name.
252
+ # @param attr_ary [Array<String>] the attribute path as *array of
253
+ # strings*. For example: `%w(myapp ftp_password)`.
254
+ # @param c [Config, Hash] a configuration hash. For example:
255
+ # `{ :partial_search => false }`.
256
+ # @return [Hash, Array, String, ...] decrypted attribute value.
257
+ # @raise [ArgumentError] if the attribute path format is wrong.
258
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
259
+ # format is wrong.
260
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
261
+ # format is not supported or unknown.
262
+ # @raise [SearchFailure] if there is a Chef search error.
263
+ # @raise [SearchFatalError] if the Chef search response is wrong.
264
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
265
+ def load_from_node(name, attr_ary, c = {})
266
+ debug(
267
+ "Loading Remote Encrypted Attribute from #{name}: #{attr_ary.inspect}"
268
+ )
269
+ enc_attr = EncryptedAttribute.new(config(c))
270
+ result = enc_attr.load_from_node(name, attr_ary)
271
+ debug('Remote Encrypted Attribute loaded.')
272
+ result
273
+ end
274
+
275
+ # Creates an encrypted attribute.
276
+ #
277
+ # The returned value should be saved in a node attribute, like
278
+ # `node.normal[...] = Chef::EncryptedAttribute.create(...)`.
279
+ #
280
+ # The local node will always be able to decrypt the attribute.
281
+ #
282
+ # An exception is thrown if any error arises in the encryption process.
283
+ #
284
+ # @param value [Hash, Array, String, ...] the value to be encrypted. Can
285
+ # be a boolean, a number, a string, an array or a hash (the value will
286
+ # be converted to JSON internally).
287
+ # @param c [Config, Hash] a configuration hash. For example:
288
+ # `{ :client_search => "admin:true" }`.
289
+ # @return [EncryptedMash] encrypted attribute value. This is usually what
290
+ # is saved in the node attributes.
291
+ # @raise [ArgumentError] if user list is wrong.
292
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
293
+ # format is wrong or does not exist.
294
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
295
+ # format is not supported or unknown.
296
+ # @raise [EncryptionFailure] if there are encryption errors.
297
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
298
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
299
+ # @raise [InvalidKey] if the RSA key format is wrong.
300
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
301
+ # the keys from the Chef Server.
302
+ # @raise [ClientNotFound] if client does not exist.
303
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
304
+ # @raise [RequirementsFailure] if the specified encrypted attribute
305
+ # version cannot be used.
306
+ # @raise [SearchFailure] if there is a Chef search error.
307
+ # @raise [SearchFatalError] if the Chef search response is wrong.
308
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
309
+ def create(value, c = {})
310
+ debug('Creating Encrypted Attribute.')
311
+ enc_attr = EncryptedAttribute.new(config(c))
312
+ result = enc_attr.create(value)
313
+ debug('Encrypted Attribute created.')
314
+ result
315
+ end
316
+
317
+ # Creates an encrypted attribute on a remote node.
318
+ #
319
+ # Both the local node and the remote node will be able to decrypt the
320
+ # attribute.
321
+ #
322
+ # This method **requires admin privileges**. So in most cases, cannot be
323
+ # used from cookbooks.
324
+ #
325
+ # An exception is thrown if any error arises in the encryption process.
326
+ #
327
+ # @param name [String] the node name.
328
+ # @param attr_ary [Array<String>] the attribute path as *array of
329
+ # strings*. For example: `%w(myapp ftp_password)`.
330
+ # @param value [Hash, Array, String, Fixnum, ...] the value to be
331
+ # encrypted. Can be a boolean, a number, a string, an array or a hash
332
+ # (the value will be converted to JSON internally).
333
+ # @param c [Config, Hash] a configuration hash. For example:
334
+ # `{ :client_search => 'admin:true' }`.
335
+ # @return [EncryptedMash] encrypted attribute value.
336
+ # @raise [ArgumentError] if the attribute path format or the user list is
337
+ # wrong.
338
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
339
+ # format is wrong or does not exist.
340
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
341
+ # format is not supported or unknown.
342
+ # @raise [EncryptionFailure] if there are encryption errors.
343
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
344
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
345
+ # @raise [InvalidKey] if the RSA key format is wrong.
346
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
347
+ # the keys from the Chef Server.
348
+ # @raise [ClientNotFound] if client does not exist.
349
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
350
+ # @raise [RequirementsFailure] if the specified encrypted attribute
351
+ # version cannot be used.
352
+ # @raise [SearchFailure] if there is a Chef search error.
353
+ # @raise [SearchFatalError] if the Chef search response is wrong.
354
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
355
+ def create_on_node(name, attr_ary, value, c = {})
356
+ debug(
357
+ "Creating Remote Encrypted Attribute on #{name}: #{attr_ary.inspect}"
358
+ )
359
+ enc_attr = EncryptedAttribute.new(config(c))
360
+ result = enc_attr.create_on_node(name, attr_ary, value)
361
+ debug('Encrypted Remote Attribute created.')
362
+ result
363
+ end
364
+
365
+ # Updates who can read the attribute. This is intended to be used to
366
+ # update to the new nodes returned by `:client_search` and `:node_search`
367
+ # or perhaps global configuration changes.
368
+ #
369
+ # For example, in case new nodes are added or some are removed, and the
370
+ # clients returned by `:client_search` or `:node_search` are different,
371
+ # this `#update` method will decrypt the attribute and encrypt it again
372
+ # for the new nodes (or remove the old ones).
373
+ #
374
+ # If an update is made, the shared secrets are regenerated.
375
+ #
376
+ # Both the local node and the remote node will be able to decrypt the
377
+ # attribute.
378
+ #
379
+ # An exception is thrown if there is any error in the updating process.
380
+ #
381
+ # @param enc_hs [Mash] This must be a node encrypted attribute, this
382
+ # attribute will be updated, so it is mandatory to specify the type
383
+ # (usually `normal`). For example:
384
+ # `node.normal['myapp']['ftp_password']`.
385
+ # @param c [Config, Hash] a configuration hash. Surely you want this
386
+ # `#update` method to use the same `config` that the `#create` call.
387
+ # @return [Boolean] `true` if the encrypted attribute has been updated,
388
+ # `false` if not.
389
+ # @raise [ArgumentError] if user list is wrong.
390
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
391
+ # format is wrong or does not exist.
392
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
393
+ # format is not supported or unknown.
394
+ # @raise [EncryptionFailure] if there are encryption errors.
395
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
396
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
397
+ # @raise [InvalidKey] if the RSA key format is wrong.
398
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
399
+ # the keys from the Chef Server.
400
+ # @raise [ClientNotFound] if client does not exist.
401
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
402
+ # @raise [RequirementsFailure] if the specified encrypted attribute
403
+ # version cannot be used.
404
+ # @raise [SearchFailure] if there is a Chef search error.
405
+ # @raise [SearchFatalError] if the Chef search response is wrong.
406
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
407
+ def update(enc_hs, c = {})
408
+ debug("Updating Encrypted Attribute: #{enc_hs.inspect}")
409
+ enc_attr = EncryptedAttribute.new(config(c))
410
+ result = enc_attr.update(enc_hs)
411
+ if result
412
+ debug('Encrypted Attribute updated.')
413
+ else
414
+ debug('Encrypted Attribute not updated.')
415
+ end
416
+ result
417
+ end
418
+
419
+ # Updates who can decrypt the remote attribute.
420
+ #
421
+ # This method **requires admin privileges**. So in most cases, cannot be
422
+ # used from cookbooks.
423
+ #
424
+ # An exception is thrown if there is any error in the updating process.
425
+ #
426
+ # @param name [String] the node name.
427
+ # @param attr_ary [Array<String>] the attribute path as *array of
428
+ # strings*. For example: `%w(myapp ftp_password)`.
429
+ # @param c [Config, Hash] a configuration hash. Surely you want this
430
+ # `#update_on_node` method to use the same `config` that the `#create`
431
+ # call.
432
+ # @return [Boolean] `true` if the encrypted attribute has been updated,
433
+ # `false` if not.
434
+ # @raise [ArgumentError] if the attribute path format or the user list is
435
+ # wrong.
436
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
437
+ # format is wrong or does not exist.
438
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
439
+ # format is not supported or unknown.
440
+ # @raise [EncryptionFailure] if there are encryption errors.
441
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
442
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
443
+ # @raise [InvalidKey] if the RSA key format is wrong.
444
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
445
+ # the keys from the Chef Server.
446
+ # @raise [ClientNotFound] if client does not exist.
447
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
448
+ # @raise [RequirementsFailure] if the specified encrypted attribute
449
+ # version cannot be used.
450
+ # @raise [SearchFailure] if there is a Chef search error.
451
+ # @raise [SearchFatalError] if the Chef search response is wrong.
452
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
453
+ def update_on_node(name, attr_ary, c = {})
454
+ debug(
455
+ "Updating Remote Encrypted Attribute on #{name}: #{attr_ary.inspect}"
456
+ )
457
+ enc_attr = EncryptedAttribute.new(config(c))
458
+ result = enc_attr.update_on_node(name, attr_ary)
459
+ debug("Encrypted Remote Attribute #{result ? '' : 'not '}updated.")
460
+ result
461
+ end
462
+
463
+ # Checks whether an encrypted attribute exists.
464
+ #
465
+ # @param hs [Mash] an encrypted hash, usually a node attribute. The
466
+ # attribute type can be specified but is not necessary. For example:
467
+ # `node['myapp']['ftp_password']`.
468
+ # @return [Boolean] `true` if an encrypted attribute is found, `false` if
469
+ # not.
470
+ def exist?(hs)
471
+ debug("Checking if Encrypted Attribute exists here: #{hs.inspect}")
472
+ result = EncryptedMash.exist?(hs)
473
+ debug("Encrypted Attribute #{result ? '' : 'not '}found.")
474
+ result
475
+ end
476
+
477
+ # Checks whether an encrypted attribute exists in a remote node.
478
+ #
479
+ # @param [Mixed] args {#exist?} arguments.
480
+ # @return [Boolean] `true` if an encrypted attribute is found, `false` if
481
+ # not.
482
+ # @deprecated Use {#exist?} instead.
483
+ def exists?(*args)
484
+ warn("#{name}.exists? is deprecated in favor of #{name}.exist?.")
485
+ exist?(*args)
486
+ end
487
+
488
+ # Checks whether an encrypted attribute exists in a remote node.
489
+ #
490
+ # @param name [String] the node name.
491
+ # @param attr_ary [Array<String>] the attribute path as *array of
492
+ # strings*. For example: `%w(myapp ftp_password)`.
493
+ # @param c [Config, Hash] a configuration hash. For example:
494
+ # `{ :partial_search => false }`.
495
+ # @return [Boolean] `true` if an encrypted attribute is found, `false` if
496
+ # not.
497
+ # @raise [ArgumentError] if the attribute path format is wrong.
498
+ def exist_on_node?(name, attr_ary, c = {})
499
+ debug("Checking if Remote Encrypted Attribute exists on #{name}")
500
+ remote_node = RemoteNode.new(name)
501
+ node_attr =
502
+ remote_node.load_attribute(attr_ary, config(c).partial_search)
503
+ Chef::EncryptedAttribute.exist?(node_attr)
504
+ end
505
+
506
+ # Checks whether an encrypted attribute exists in a remote node.
507
+ #
508
+ # @param [Mixed] args {#exist_on_node?} arguments.
509
+ # @return [Boolean] `true` if an encrypted attribute is found, `false` if
510
+ # not.
511
+ # @deprecated Use {#exist_on_node?} instead.
512
+ def exists_on_node?(*args)
513
+ warn(
514
+ "#{name}.exists_on_node? is deprecated in favor of "\
515
+ "#{name}.exist_on_node?."
516
+ )
517
+ exist_on_node?(*args)
518
+ end
519
+ end
520
+ end
521
+ end