chef-encrypted-attributes 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
- #!/usr/bin/env rake
2
- # encoding: utf-8
1
+ # encoding: UTF-8
2
+ # -*- mode: ruby -*-
3
+ # vi: set ft=ruby :
4
+
5
+ # More info at https://github.com/jimweirich/rake/blob/master/doc/rakefile.rdoc
3
6
 
4
7
  #
5
8
  # Author:: Xabier de Zuazo (<xabier@onddo.com>)
@@ -24,23 +27,33 @@ Bundler::GemHelper.install_tasks
24
27
 
25
28
  require 'rake/testtask'
26
29
 
30
+ desc 'Run RuboCop style checks'
31
+ task :rubocop do
32
+ require 'rubocop/rake_task'
33
+ RuboCop::RakeTask.new
34
+ end
35
+
36
+ desc 'Run all style checks'
37
+ task style: %w(rubocop)
38
+
27
39
  {
28
- :test => '{unit,integration}',
29
- :unit => 'unit',
30
- :integration => 'integration',
31
- :benchmark => 'benchmark',
40
+ test: '{unit,integration}',
41
+ unit: 'unit',
42
+ integration: 'integration',
43
+ benchmark: 'benchmark'
32
44
  }.each do |test, dir|
33
- Rake::TestTask.new(test) do |test|
34
- test.libs << 'lib' << 'spec'
35
- test.pattern = "spec/#{dir}/**/*.rb"
36
- test.verbose = true
45
+ Rake::TestTask.new(test) do |t|
46
+ t.libs << 'lib' << 'spec'
47
+ t.pattern = "spec/#{dir}/**/*.rb"
48
+ t.verbose = true
37
49
  end
38
50
  end
39
51
 
40
52
  if RUBY_VERSION < '1.9.3'
41
- # integration tests are broken in 1.9.2 due to a chef-zero bug
42
- # https://github.com/opscode/chef-zero/issues/65
43
- task :default => :unit
53
+ # Integration tests are broken in 1.9.2 due to a chef-zero bug:
54
+ # https://github.com/opscode/chef-zero/issues/65
55
+ # RuboCop require Ruby 1.9.3.
56
+ task default: %w(unit)
44
57
  else
45
- task :default => :test
58
+ task default: %w(style test)
46
59
  end
data/TESTING.md CHANGED
@@ -1,22 +1,33 @@
1
1
  # Testing
2
2
 
3
+ ## Installing the Requirements
4
+
5
+ You can install gem dependencies with bundler:
6
+
7
+ $ gem install bundler
8
+ $ bundler install
9
+
3
10
  ## All the Tests
4
11
 
5
- $ rake test
12
+ $ bundle exec rake test
13
+
14
+ ## Running the Syntax Style Tests
15
+
16
+ $ bundle exec rake style
6
17
 
7
- ## Unit Tests
18
+ ## Running the Unit Tests
8
19
 
9
- $ rake unit
20
+ $ bundle exec rake unit
10
21
 
11
- ## Integration Tests
22
+ ## Running the Integration Tests
12
23
 
13
- $ rake integration
24
+ $ bundle exec rake integration
14
25
 
15
- ## Benchmarks
26
+ ## Running the Benchmarks
16
27
 
17
28
  You can run some simple benchmarks, not at all realistic:
18
29
 
19
- $ rspec spec/benchmark/*
30
+ $ bundle exec rspec spec/benchmark/*
20
31
  user system total real
21
32
  Local EncryptedAttribute read (v=0) 0.410000 0.000000 0.410000 ( 0.417956)
22
33
  Local EncryptedAttribute read (v=1) 0.390000 0.010000 0.400000 ( 0.398934)
data/TODO.md CHANGED
@@ -1,20 +1,17 @@
1
1
  TODO
2
2
  ====
3
3
 
4
+ * Fix all RuboCop offenses.
4
5
  * knife encrypted attribute create/edit from file.
5
6
  * Save config inside encrypted data: `:client_search`, `:node_search` and `:keys` (including user keys).
6
7
  * Chef internal node attribute integration monkey-patch. It may require some `EncryptedMash` class rewrite or adding some methods.
7
8
  * Support for Chef `< 11.4` (add `JSONCompat#map_to_rb_obj`, disable `Chef::User` for `< 11.2`, ...).
8
- * Test with Chef `10`.
9
- * Add Ruby `1.8` support?
10
- * Document the Ruby code.
11
9
  * Add more info/debug prints.
12
10
  * Space-optimized `EncryptedMash::Version3` class.
13
11
  * Tests: Add test helper functions (key generation, ApiClients including priv keys, Node creation...).
14
12
  * Tests: Add more tests for `EncryptedMash::Version1` and `EncryptedMash::Version2`.
15
13
  * Tests: Add unit tests for `EncryptedAttribute`.
16
14
  * Tests: Add unit tests for all knife commands.
17
- * Tests: Tests `raise_error` always include regex.
18
- * Tests: Review and clean some tests.
15
+ * Tests: `raise_error` tests always include regex.
19
16
  * Add `chef-vault` to benchmarks.
20
17
  * Signed attributes?
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  #
2
3
  # Author:: Xabier de Zuazo (<xabier@onddo.com>)
3
4
  # Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
@@ -16,4 +17,9 @@
16
17
  # limitations under the License.
17
18
  #
18
19
 
19
- require 'chef/encrypted_attribute'
20
+ warn(
21
+ '[DEPRECATION] The required "chef-encrypted-attributes" file has been moved '\
22
+ 'to "chef/encrypted_attributes" and will be removed in a future release. '\
23
+ 'Please switch to "chef/encrypted_attributes" as soon as possible.'
24
+ )
25
+ require 'chef/encrypted_attributes'
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  #
2
3
  # Author:: Xabier de Zuazo (<xabier@onddo.com>)
3
4
  # Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
@@ -21,6 +22,7 @@ require 'chef/encrypted_attribute/encrypted_mash'
21
22
  require 'chef/config'
22
23
  require 'chef/mash'
23
24
 
25
+ require 'chef/encrypted_attribute/api'
24
26
  require 'chef/encrypted_attribute/local_node'
25
27
  require 'chef/encrypted_attribute/remote_node'
26
28
  require 'chef/encrypted_attribute/remote_nodes'
@@ -30,60 +32,227 @@ require 'chef/encrypted_attribute/encrypted_mash/version0'
30
32
  require 'chef/encrypted_attribute/encrypted_mash/version1'
31
33
  require 'chef/encrypted_attribute/encrypted_mash/version2'
32
34
 
33
- Chef::Config[:encrypted_attributes] = Mash.new unless Chef::Config[:encrypted_attributes].kind_of?(Hash)
35
+ unless Chef::Config[:encrypted_attributes].is_a?(Hash)
36
+ Chef::Config[:encrypted_attributes] = Mash.new
37
+ end
34
38
 
35
39
  class Chef
40
+ # Main EncryptedAttribute class.
41
+ #
42
+ # This class contains both static and instance level public methods.
43
+ # Internally, all work with {EncryptedMash} object instances.
44
+ #
45
+ # # Class Methods
46
+ #
47
+ # The *class methods* (or static methods) are normally used **from Chef
48
+ # cookbooks**.
49
+ #
50
+ # The attributes create with the class methods are encrypted **only for the
51
+ # local node** by default.
52
+ #
53
+ # The static `*_on_node` methods can be used, although they have not been
54
+ # designed for this purpose (have not been tested).
55
+ #
56
+ # They are # documented in the {Chef::EncryptedAttribute::API} class.
57
+ #
58
+ # # Instance Methods
59
+ #
60
+ # The *instance methods* are normally used **by other libraries or gems**. For
61
+ # example, the knife extensions included in this gem uses these methods.
62
+ #
63
+ # The instance methods will grant encrypted attribute access **only to the
64
+ # remote node** by default.
65
+ #
66
+ # Usually only the `*_from_node/*_on_node` instance methods will be used.
67
+ #
68
+ # @see EncryptedAttribute::API
36
69
  class EncryptedAttribute
70
+ # Include the *class methods* for the recipe API.
71
+ extend Chef::EncryptedAttribute::API
37
72
 
38
- def initialize(c=nil)
73
+ # Chef::EncryptedAttribute constructor.
74
+ #
75
+ # @param c [Config, Hash] configuration to use.
76
+ def initialize(c = nil)
39
77
  config(c)
40
78
  end
41
79
 
42
- def config(arg=nil)
43
- @config ||= EncryptedAttribute::Config.new(Chef::Config[:encrypted_attributes])
80
+ # Sets or gets the encrypted attribute configuration.
81
+ #
82
+ # Reads the default configuration from
83
+ # `Chef::Config[:encrypted_attributes]`.
84
+ #
85
+ # When setting using a {Chef::EncryptedAttribute::Config} class, all the
86
+ # configuration options will be replaced.
87
+ #
88
+ # When setting using a _Hash_, only the provided keys will be replaced.
89
+ #
90
+ # @param arg [Config, Hash] the configuration to set.
91
+ # @return [Config] the read or set configuration object.
92
+ def config(arg = nil)
93
+ @config ||= EncryptedAttribute::Config.new(
94
+ Chef::Config[:encrypted_attributes]
95
+ )
44
96
  @config.update!(arg) unless arg.nil?
45
97
  @config
46
98
  end
47
99
 
48
- # Decrypts an encrypted attribute from a (encrypted) Hash
49
- def load(enc_hs, key=nil)
100
+ # Decrypts an encrypted attribute from a local node attribute.
101
+ #
102
+ # @param enc_hs [Mash] the encrypted hash as read from the node attributes.
103
+ # @param key [String, OpenSSL::PKey::RSA] private key to use in the
104
+ # decryption process, uses the local node key by default.
105
+ # @return [Hash, Array, String, ...] decrypted attribute value.
106
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
107
+ # format is wrong.
108
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
109
+ # format is not supported or unknown.
110
+ def load(enc_hs, key = nil)
50
111
  enc_attr = EncryptedMash.json_create(enc_hs)
51
112
  decrypted = enc_attr.decrypt(key || local_key)
52
- decrypted['content'] # TODO check this Hash
113
+ decrypted['content'] # TODO: check this Hash
53
114
  end
54
115
 
55
- # Decrypts a encrypted attribute from a remote node
56
- def load_from_node(name, attr_ary, key=nil)
116
+ # Decrypts a encrypted attribute from a remote node.
117
+ #
118
+ # @param name [String] node name.
119
+ # @param attr_ary [Array<String>] node attribute path as Array.
120
+ # @param key [String, OpenSSL::PKey::RSA] private key to use in the
121
+ # decryption process, uses the local key by default.
122
+ # @return [Hash, Array, String, ...] decrypted attribute value.
123
+ # @raise [ArgumentError] if the attribute path format is wrong.
124
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
125
+ # format is wrong.
126
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
127
+ # format is not supported or unknown.
128
+ # @raise [SearchFailure] if there is a Chef search error.
129
+ # @raise [SearchFatalError] if the Chef search response is wrong.
130
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
131
+ def load_from_node(name, attr_ary, key = nil)
57
132
  remote_node = RemoteNode.new(name)
58
- self.load(remote_node.load_attribute(attr_ary, config.partial_search), key)
133
+ load(remote_node.load_attribute(attr_ary, config.partial_search), key)
59
134
  end
60
135
 
61
- # Creates an encrypted attribute from a Hash
62
- def create(value, keys=nil)
136
+ # Creates an encrypted attribute from a Hash.
137
+ #
138
+ # Only the **keys passed as parameter and the configured keys** will be able
139
+ # to decrypt the attribute, so beware of including your local key if you
140
+ # need to decrypt it in the future.
141
+ #
142
+ # @param value [Hash, Array, String, Fixnum, ...] the value to encrypt in
143
+ # clear.
144
+ # @param keys [String, OpenSSL::PKey::RSA] public keys that will be able to
145
+ # decrypt the attribute.
146
+ # @raise [ArgumentError] if user list is wrong.
147
+ # @return [EncryptedMash] encrypted attribute value. This is usually what is
148
+ # saved in the node attributes.
149
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
150
+ # format is wrong or does not exist.
151
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
152
+ # format is not supported or unknown.
153
+ # @raise [EncryptionFailure] if there are encryption errors.
154
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
155
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
156
+ # @raise [InvalidKey] if the RSA key format is wrong.
157
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
158
+ # the keys from the Chef Server.
159
+ # @raise [ClientNotFound] if client does not exist.
160
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
161
+ # @raise [RequirementsFailure] if the specified encrypted attribute
162
+ # version cannot be used.
163
+ # @raise [SearchFailure] if there is a Chef search error.
164
+ # @raise [SearchFatalError] if the Chef search response is wrong.
165
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
166
+ def create(value, keys = nil)
63
167
  decrypted = { 'content' => value }
64
168
 
65
169
  enc_attr = EncryptedMash.create(config.version)
66
170
  enc_attr.encrypt(decrypted, target_keys(keys))
67
171
  end
68
172
 
173
+ # Creates an encrypted attribute on a remote node.
174
+ #
175
+ # The remote node will always be able to decrypt it. The local node will
176
+ # not be able to decrypt it by default, you must remember to include the key
177
+ # in the configuration.
178
+ #
179
+ # @param name [String] node name.
180
+ # @param attr_ary [Array<String>] node attribute path as Array.
181
+ # @param value [Hash, Array, String, Fixnum, ...] the value to encrypt.
182
+ # @return [EncryptedMash] encrypted attribute value.
183
+ # @raise [ArgumentError] if the attribute path format or the user list is
184
+ # wrong.
185
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
186
+ # format is wrong or does not exist.
187
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
188
+ # format is not supported or unknown.
189
+ # @raise [EncryptionFailure] if there are encryption errors.
190
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
191
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
192
+ # @raise [InvalidKey] if the RSA key format is wrong.
193
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
194
+ # the keys from the Chef Server.
195
+ # @raise [ClientNotFound] if client does not exist.
196
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
197
+ # @raise [RequirementsFailure] if the specified encrypted attribute
198
+ # version cannot be used.
199
+ # @raise [SearchFailure] if there is a Chef search error.
200
+ # @raise [SearchFatalError] if the Chef search response is wrong.
201
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
69
202
  def create_on_node(name, attr_ary, value)
70
203
  # read the client public key
71
204
  node_public_key = RemoteClients.get_public_key(name)
72
205
 
73
206
  # create the encrypted attribute
74
- enc_attr = self.create(value, [ node_public_key ])
207
+ enc_attr = create(value, [node_public_key])
75
208
 
76
209
  # save encrypted attribute
77
210
  remote_node = RemoteNode.new(name)
78
211
  remote_node.save_attribute(attr_ary, enc_attr)
79
212
  end
80
213
 
81
- # Updates the keys for which the attribute is encrypted
82
- def update(enc_hs, keys=nil)
214
+ # Updates the keys for which a local attribute is encrypted.
215
+ #
216
+ # In case new keys are added or some keys are removed, the attribute will
217
+ # be re-created again.
218
+ #
219
+ # Only the **keys passed as parameter and the configured keys** will be able
220
+ # to decrypt the attribute, so beware of including your local key if you
221
+ # need to decrypt it in the future.
222
+ #
223
+ # Uses the local key to decrypt the attribute, so the local key should be
224
+ # able to read the attribute. At least before updating.
225
+ #
226
+ # @param enc_hs [Mash] encrypted attribute. This parameter value will be
227
+ # modified on updates.
228
+ # @param keys [Array<String, OpenSSL::PKey::RSA> public keys that should be
229
+ # able to read the attribute.
230
+ # @return [Boolean] Returns `true` if the encrypted attribute (the *Mash*
231
+ # parameter) has been updated.
232
+ # @raise [ArgumentError] if user list is wrong.
233
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
234
+ # format is wrong or does not exist.
235
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
236
+ # format is not supported or unknown.
237
+ # @raise [EncryptionFailure] if there are encryption errors.
238
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
239
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
240
+ # @raise [InvalidKey] if the RSA key format is wrong.
241
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
242
+ # the keys from the Chef Server.
243
+ # @raise [ClientNotFound] if client does not exist.
244
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
245
+ # @raise [RequirementsFailure] if the specified encrypted attribute
246
+ # version cannot be used.
247
+ # @raise [SearchFailure] if there is a Chef search error.
248
+ # @raise [SearchFatalError] if the Chef search response is wrong.
249
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
250
+ # @see #config
251
+ def update(enc_hs, keys = nil)
83
252
  old_enc_attr = EncryptedMash.json_create(enc_hs)
84
253
  if old_enc_attr.needs_update?(target_keys(keys))
85
254
  hs = old_enc_attr.decrypt(local_key)
86
- new_enc_attr = create(hs['content'], keys) # TODO check this Hash
255
+ new_enc_attr = create(hs['content'], keys) # TODO: check this Hash
87
256
  enc_hs.replace(new_enc_attr)
88
257
  true
89
258
  else
@@ -91,6 +260,42 @@ class Chef
91
260
  end
92
261
  end
93
262
 
263
+ # Updates the keys for which a remote attribute is encrypted.
264
+ #
265
+ # In case new keys are added or some keys are removed, the attribute will
266
+ # be re-created again.
267
+ #
268
+ # Only the **remote node and the configured keys** will be able to decrypt
269
+ # the attribute, so beware of including your local key if you need to
270
+ # decrypt it in the future.
271
+ #
272
+ # Uses the local key to decrypt the attribute, so the local key should be
273
+ # able to read the attribute. At least before updating.
274
+ #
275
+ # @param name [String] node name.
276
+ # @param attr_ary [Array<String>] node attribute path as Array.
277
+ # @return [Boolean] Returns `true` if the remote encrypted attribute has
278
+ # been updated.
279
+ # @raise [ArgumentError] if the attribute path format or the user list is
280
+ # wrong.
281
+ # @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
282
+ # format is wrong or does not exist.
283
+ # @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
284
+ # format is not supported or unknown.
285
+ # @raise [EncryptionFailure] if there are encryption errors.
286
+ # @raise [MessageAuthenticationFailure] if HMAC calculation error.
287
+ # @raise [InvalidPublicKey] if it is not a valid RSA public key.
288
+ # @raise [InvalidKey] if the RSA key format is wrong.
289
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
290
+ # the keys from the Chef Server.
291
+ # @raise [ClientNotFound] if client does not exist.
292
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
293
+ # @raise [RequirementsFailure] if the specified encrypted attribute
294
+ # version cannot be used.
295
+ # @raise [SearchFailure] if there is a Chef search error.
296
+ # @raise [SearchFatalError] if the Chef search response is wrong.
297
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
298
+ # @see #config
94
299
  def update_on_node(name, attr_ary)
95
300
  # read the client public key
96
301
  node_public_key = RemoteClients.get_public_key(name)
@@ -98,11 +303,11 @@ class Chef
98
303
  # update the encrypted attribute
99
304
  remote_node = RemoteNode.new(name)
100
305
  enc_hs = remote_node.load_attribute(attr_ary, config.partial_search)
101
- updated = update(enc_hs, [ node_public_key ])
306
+ updated = update(enc_hs, [node_public_key])
102
307
 
103
308
  # save encrypted attribute
104
309
  if updated
105
- # TODO Node is accessed twice (here and RemoteNode#load_attribute above)
310
+ # TODO: Node is accessed twice (RemoteNode#load_attribute above)
106
311
  remote_node.save_attribute(attr_ary, enc_hs)
107
312
  end
108
313
  updated
@@ -110,124 +315,80 @@ class Chef
110
315
 
111
316
  protected
112
317
 
318
+ # Gets remote client public keys using the *client search* query included in
319
+ # the configuration.
320
+ #
321
+ # @return [Array<String>] list of client public keys.
322
+ # @raise [ClientNotFound] if client does not exist.
323
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
324
+ # @raise [SearchFailure] if there is a Chef search error.
325
+ # @raise [SearchFatalError] if the Chef search response is wrong.
326
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
327
+ # @see #config
113
328
  def remote_client_keys
114
- RemoteClients.search_public_keys(config.client_search, config.partial_search)
329
+ RemoteClients.search_public_keys(
330
+ config.client_search, config.partial_search
331
+ )
115
332
  end
116
333
 
334
+ # Gets remote node public keys using the *node search* query included in the
335
+ # configuration.
336
+ #
337
+ # @return [Array<String>] list of node public keys.
338
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
339
+ # the keys from the Chef Server.
340
+ # @raise [ClientNotFound] if client does not exist.
341
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
342
+ # @raise [SearchFailure] if there is a Chef search error.
343
+ # @raise [SearchFatalError] if the Chef search response is wrong.
344
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
345
+ # @see #config
117
346
  def remote_node_keys
118
347
  RemoteNodes.search_public_keys(config.node_search, config.partial_search)
119
348
  end
120
349
 
350
+ # Gets remote user keys using the configured user list.
351
+ #
352
+ # @return [Array<String>] list of user public keys.
353
+ # @raise [ArgumentError] if user list is wrong.
354
+ # @see #config
121
355
  def remote_user_keys
122
356
  RemoteUsers.get_public_keys(config.users)
123
357
  end
124
358
 
125
- def target_keys(keys=nil)
126
- target_keys = config.keys + remote_client_keys + remote_node_keys + remote_user_keys
127
- target_keys += keys if keys.kind_of?(Array)
359
+ # Gets the public keys that should be able to read the attribute based on
360
+ # the configuration.
361
+ #
362
+ # This includes keys passed as parameter, configured keys,
363
+ # #remote_client_keys, #remote_node_keys and remote_user_keys.
364
+ #
365
+ # @param keys [Array<String>] list of public keys to include in addition to
366
+ # the configured.
367
+ # @return [Array<String>] list of user public keys.
368
+ # @raise [ArgumentError] if user list is wrong.
369
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
370
+ # the keys from the Chef Server.
371
+ # @raise [ClientNotFound] if client does not exist.
372
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
373
+ # @raise [SearchFailure] if there is a Chef search error.
374
+ # @raise [SearchFatalError] if the Chef search response is wrong.
375
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
376
+ # @see #config
377
+ # @see #remote_client_keys
378
+ # @see #remote_node_keys
379
+ # @see #remote_user_keys
380
+ def target_keys(keys = nil)
381
+ target_keys =
382
+ config.keys + remote_client_keys + remote_node_keys + remote_user_keys
383
+ target_keys += keys if keys.is_a?(Array)
128
384
  target_keys
129
385
  end
130
386
 
387
+ # Gets the local private key.
388
+ #
389
+ # @return [OpenSSL::PKey::RSA.new] local private (and public) key object.
131
390
  def local_key
132
- self.class.local_node.key
133
- end
134
-
135
- def self.local_node
136
- LocalNode.new
137
- end
138
-
139
- def self.config(arg)
140
- config = EncryptedAttribute::Config.new(Chef::Config[:encrypted_attributes])
141
- config.update!(arg)
142
- config.keys(config.keys + [ self.local_node.public_key ])
143
- config
144
- end
145
-
146
- public
147
-
148
- def self.load(hs, c={})
149
- Chef::Log.debug("#{self.class.name}: Loading Local Encrypted Attribute from: #{hs.to_s}")
150
- enc_attr = EncryptedAttribute.new(self.config(c))
151
- result = enc_attr.load(hs)
152
- Chef::Log.debug("#{self.class.name}: Local Encrypted Attribute loaded.")
153
- result
154
- end
155
-
156
- def self.load_from_node(name, attr_ary, c={})
157
- Chef::Log.debug("#{self.class.name}: Loading Remote Encrypted Attribute from #{name}: #{attr_ary.to_s}")
158
- enc_attr = EncryptedAttribute.new(self.config(c))
159
- result = enc_attr.load_from_node(name, attr_ary)
160
- Chef::Log.debug("#{self.class.name}: Remote Encrypted Attribute loaded.")
161
- result
162
- end
163
-
164
- def self.create(value, c={})
165
- Chef::Log.debug("#{self.class.name}: Creating Encrypted Attribute.")
166
- enc_attr = EncryptedAttribute.new(self.config(c))
167
- result = enc_attr.create(value)
168
- Chef::Log.debug("#{self.class.name}: Encrypted Attribute created.")
169
- result
170
- end
171
-
172
- def self.create_on_node(name, attr_ary, value, c={})
173
- Chef::Log.debug("#{self.class.name}: Creating Remote Encrypted Attribute on #{name}: #{attr_ary.to_s}")
174
- enc_attr = EncryptedAttribute.new(self.config(c))
175
- result = enc_attr.create_on_node(name, attr_ary, value)
176
- Chef::Log.debug("#{self.class.name}: Encrypted Remote Attribute created.")
177
- result
178
- end
179
-
180
- def self.update(hs, c={})
181
- Chef::Log.debug("#{self.class.name}: Updating Encrypted Attribute: #{hs.to_s}")
182
- enc_attr = EncryptedAttribute.new(self.config(c))
183
- result = enc_attr.update(hs)
184
- if result
185
- Chef::Log.debug("#{self.class.name}: Encrypted Attribute updated.")
186
- else
187
- Chef::Log.debug("#{self.class.name}: Encrypted Attribute not updated.")
188
- end
189
- result
190
- end
191
-
192
- def self.update_on_node(name, attr_ary, c={})
193
- Chef::Log.debug("#{self.class.name}: Updating Remote Encrypted Attribute on #{name}: #{attr_ary.to_s}")
194
- enc_attr = EncryptedAttribute.new(self.config(c))
195
- result = enc_attr.update_on_node(name, attr_ary)
196
- if result
197
- Chef::Log.debug("#{self.class.name}: Encrypted Remote Attribute updated.")
198
- else
199
- Chef::Log.debug("#{self.class.name}: Encrypted Remote Attribute not updated.")
200
- end
201
- result
202
- end
203
-
204
- def self.exist?(hs)
205
- Chef::Log.debug("#{self.class.name}: Checking if Encrypted Attribute exists here: #{hs.to_s}")
206
- result = EncryptedMash.exist?(hs)
207
- if result
208
- Chef::Log.debug("#{self.class.name}: Encrypted Attribute found.")
209
- else
210
- Chef::Log.debug("#{self.class.name}: Encrypted Attribute not found.")
211
- end
212
- result
391
+ LocalNode.new.key
213
392
  end
214
-
215
- def self.exists?(*args)
216
- Chef::Log.warn("#{self.name}.exists? is deprecated in favor of #{self.name}.exist?.")
217
- exist?(*args)
218
- end
219
-
220
- def self.exist_on_node?(name, attr_ary, c={})
221
- Chef::Log.debug("#{self.class.name}: Checking if Remote Encrypted Attribute exists on #{name}")
222
- remote_node = RemoteNode.new(name)
223
- node_attr = remote_node.load_attribute(attr_ary, self.config(c).partial_search)
224
- Chef::EncryptedAttribute.exist?(node_attr)
225
- end
226
-
227
- def self.exists_on_node?(*args)
228
- Chef::Log.warn("#{self.name}.exists_on_node? is deprecated in favor of #{self.name}.exist_on_node?.")
229
- exist_on_node?(*args)
230
- end
231
-
232
393
  end
233
394
  end