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
@@ -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)
@@ -18,23 +19,38 @@
18
19
 
19
20
  class Chef
20
21
  class EncryptedAttribute
21
-
22
+ # Exception raised when some requirements to use the encrypted attributes
23
+ # are not met.
22
24
  class RequirementsFailure < StandardError; end
25
+ # Exception raised when the encrypted attribute format is unknown.
23
26
  class UnsupportedEncryptedAttributeFormat < StandardError; end
27
+ # Exception raised when the encrypted attribute format is wrong.
24
28
  class UnacceptableEncryptedAttributeFormat < StandardError; end
29
+ # Exception raised when there are decryption errors.
25
30
  class DecryptionFailure < StandardError; end
31
+ # Exception raised when there are encryption errors.
26
32
  class EncryptionFailure < StandardError; end
33
+ # Exception raised when there errors generating the HMAC.
27
34
  class MessageAuthenticationFailure < StandardError; end
35
+ # Exception raised when the public key is wrong.
28
36
  class InvalidPublicKey < StandardError; end
29
- class InvalidPrivateKey < StandardError; end
37
+ # Exception raised when the key is wrong.
38
+ class InvalidKey < StandardError; end
30
39
 
40
+ # Exception raised when you don't have enough privileges in the Chef Server
41
+ # to do what you intend. Usually happens when you try to read Client or Node
42
+ # keys without being admin.
31
43
  class InsufficientPrivileges < StandardError; end
44
+ # Exception raised when the user does not exist.
32
45
  class UserNotFound < StandardError; end
46
+ # Exception raised when the client does not exist.
33
47
  class ClientNotFound < StandardError; end
34
48
 
49
+ # Exception raised for search errors.
35
50
  class SearchFailure < StandardError; end
51
+ # Exception raised for search fatal errors.
36
52
  class SearchFatalError < StandardError; end
53
+ # Exception raised when search keys are wrong.
37
54
  class InvalidSearchKeys < StandardError; end
38
-
39
55
  end
40
56
  end
@@ -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)
@@ -18,21 +19,31 @@
18
19
 
19
20
  class Chef
20
21
  class EncryptedAttribute
22
+ # Get name and keys from local Chef Node.
21
23
  class LocalNode
22
-
23
- # currently not used
24
+ # Gets the local node name.
25
+ #
26
+ # @return [String] local node name.
27
+ # @note currently not used
24
28
  def name
25
29
  Chef::Config[:node_name]
26
30
  end
27
31
 
32
+ # Gets the local node key.
33
+ #
34
+ # The key has the private key and the public key embedded.
35
+ #
36
+ # @return [OpenSSL::PKey::RSA] the local node private and the public key.
28
37
  def key
29
- OpenSSL::PKey::RSA.new(open(Chef::Config[:client_key]).read())
38
+ OpenSSL::PKey::RSA.new(open(Chef::Config[:client_key]).read)
30
39
  end
31
40
 
41
+ # Gets the local node public key.
42
+ #
43
+ # @return [OpenSSL::PKey::RSA] the local node public key.
32
44
  def public_key
33
45
  key.public_key
34
46
  end
35
-
36
47
  end
37
48
  end
38
49
  end
@@ -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)
@@ -24,37 +25,52 @@ require 'chef/encrypted_attribute/cache_lru'
24
25
 
25
26
  class Chef
26
27
  class EncryptedAttribute
28
+ # Search remote Chef Clients public keys.
27
29
  class RemoteClients
28
30
  extend ::Chef::EncryptedAttribute::SearchHelper
29
31
 
32
+ # Remote clients search results cache.
33
+ #
34
+ # You can disable it setting it's size to zero:
35
+ #
36
+ # ```ruby
37
+ # Chef::EncryptedAttribute::RemoteClients.cache.max_size(0)
38
+ # ```
39
+ #
40
+ # @return [CacheLru] Remote clients LRU cache.
30
41
  def self.cache
31
42
  @@cache ||= Chef::EncryptedAttribute::CacheLru.new
32
43
  end
33
44
 
45
+ # Gets remote client public key.
46
+ #
47
+ # @param name [String] Chef client name.
48
+ # @return [String] Chef client public key as string.
49
+ # @raise [ClientNotFound] if client does not exist.
50
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
34
51
  def self.get_public_key(name)
35
52
  Chef::ApiClient.load(name).public_key
36
53
  rescue Net::HTTPServerException => e
37
- case e.response.code
38
- when '404' # Not Found
39
- raise ClientNotFound, "Chef Client not found: \"#{name}\"."
40
- else
41
- raise e
42
- end
54
+ raise e unless e.response.code == '404'
55
+ raise ClientNotFound, "Chef Client not found: #{name.inspect}."
43
56
  end
44
57
 
45
- def self.search_public_keys(search='*:*', partial_search=true)
58
+ # Searches for chef client public keys.
59
+ #
60
+ # @param search [Array<String>, String] search queries to perform, the
61
+ # query result will be *OR*-ed.
62
+ # @return [Array<String>] list of public keys.
63
+ # @raise [SearchFailure] if there is a Chef search error.
64
+ # @raise [SearchFatalError] if the Chef search response is wrong.
65
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
66
+ def self.search_public_keys(search = '*:*', partial_search = true)
46
67
  escaped_query = escape_query(search)
47
- if cache.has_key?(escaped_query)
48
- cache[escaped_query]
49
- else
50
- cache[escaped_query] = search(:client, search, {
51
- 'public_key' => [ 'public_key' ]
52
- }, 1000, partial_search).map do |client|
53
- client['public_key']
54
- end.compact
55
- end
68
+ return cache[escaped_query] if cache.key?(escaped_query)
69
+ cache[escaped_query] = search(
70
+ :client, search,
71
+ { 'public_key' => %w(public_key) }, 1000, partial_search
72
+ ).map { |client| client['public_key'] }.compact
56
73
  end
57
-
58
74
  end
59
75
  end
60
76
  end
@@ -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)
@@ -22,55 +23,77 @@ require 'chef/encrypted_attribute/cache_lru'
22
23
 
23
24
  class Chef
24
25
  class EncryptedAttribute
26
+ # Remote Node object to read and save node attributes remotely.
25
27
  class RemoteNode
26
28
  include ::Chef::Mixin::ParamsValidate
27
29
  include ::Chef::EncryptedAttribute::SearchHelper
28
30
 
31
+ # Remote Node object constructor.
32
+ #
33
+ # @param name [String] node name.
29
34
  def initialize(name)
30
35
  name(name)
31
36
  end
32
37
 
38
+ # Remote node attribute values cache.
39
+ #
40
+ # It is disabled by default. You can enable it changing it's size:
41
+ #
42
+ # ```ruby
43
+ # Chef::EncryptedAttribute::RemoteNode.cache.max_size(1024)
44
+ # ```
45
+ #
46
+ # @return [CacheLru] node attributes LRU cache.
33
47
  def self.cache
34
- @@cache ||= Chef::EncryptedAttribute::CacheLru.new(0) # disabled by default
48
+ # disabled by default
49
+ @@cache ||= Chef::EncryptedAttribute::CacheLru.new(0)
35
50
  end
36
51
 
37
- def name(arg=nil)
52
+ # Read or set node name.
53
+ #
54
+ # @param arg [String] node name.
55
+ # @return [String] node name.
56
+ def name(arg = nil)
57
+ # TODO: clean the cache when changed?
38
58
  set_or_return(
39
59
  :name,
40
60
  arg,
41
- :kind_of => String
61
+ kind_of: String
42
62
  )
43
63
  end
44
64
 
45
- def load_attribute(attr_ary, partial_search=true)
46
- unless attr_ary.kind_of?(Array)
47
- raise ArgumentError, "#{self.class.to_s}##{__method__} attr_ary argument must be an array of strings. You passed #{attr_ary.inspect}."
48
- end
65
+ # Loads a remote node attribute.
66
+ #
67
+ # @param attr_ary [Array<String>] node attribute path as Array.
68
+ # @param partial_search [Boolean] whether to use partial search.
69
+ # @return [Mixed] node attribute value.
70
+ # @raise [ArgumentError] if the attribute path format is wrong.
71
+ # @raise [SearchFailure] if there is a Chef search error.
72
+ # @raise [SearchFatalError] if the Chef search response is wrong.
73
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
74
+ def load_attribute(attr_ary, partial_search = true)
75
+ assert_attribute_array(attr_ary)
49
76
  cache_key = cache_key(name, attr_ary)
50
- if self.class.cache.has_key?(cache_key)
51
- self.class.cache[cache_key]
52
- else
53
- keys = { 'value' => attr_ary }
54
- res = search(:node, "name:#{@name}", keys, 1, partial_search)
55
- self.class.cache[cache_key] = if res.kind_of?(Array) and
56
- res[0].kind_of?(Hash) and res[0].has_key?('value')
57
- res[0]['value']
58
- else
59
- nil
60
- end
61
- end
77
+ return self.class.cache[cache_key] if self.class.cache.key?(cache_key)
78
+ keys = { 'value' => attr_ary }
79
+ res = search(:node, "name:#{@name}", keys, 1, partial_search)
80
+ self.class.cache[cache_key] = parse_search_result(res)
62
81
  end
63
82
 
83
+ # Saves a remote node attribute.
84
+ #
85
+ # @param attr_ary [Array<String>] node attribute path as Array.
86
+ # @param value [Mixed] node attribute value to set.
87
+ # @return [Mixed] node attribute value.
88
+ # @raise [ArgumentError] if the attribute path format is wrong.
64
89
  def save_attribute(attr_ary, value)
65
- unless attr_ary.kind_of?(Array)
66
- raise ArgumentError, "#{self.class.to_s}##{__method__} attr_ary argument must be an array of strings. You passed #{attr_ary.inspect}."
67
- end
90
+ assert_attribute_array(attr_ary)
68
91
  cache_key = cache_key(name, attr_ary)
69
92
 
70
93
  node = Chef::Node.load(name)
71
94
  last = attr_ary.pop
72
95
  node_attr = attr_ary.reduce(node.normal) do |a, k|
73
- a[k] = Mash.new unless a.has_key?(k)
96
+ a[k] = Mash.new unless a.key?(k)
74
97
  a[k]
75
98
  end
76
99
  node_attr[last] = value
@@ -79,18 +102,22 @@ class Chef
79
102
  self.class.cache[cache_key] = value
80
103
  end
81
104
 
105
+ # Deletes a remote node attribute.
106
+ #
107
+ # @param attr_ary [Array<String>] node attribute path as Array.
108
+ # @return [Boolean] whether the node attribute has been found and
109
+ # successfully deleted.
110
+ # @raise [ArgumentError] if the attribute path format is wrong.
82
111
  def delete_attribute(attr_ary)
83
- unless attr_ary.kind_of?(Array)
84
- raise ArgumentError, "#{self.class.to_s}##{__method__} attr_ary argument must be an array of strings. You passed #{attr_ary.inspect}."
85
- end
112
+ assert_attribute_array(attr_ary)
86
113
  cache_key = cache_key(name, attr_ary)
87
114
 
88
115
  node = Chef::Node.load(name)
89
116
  last = attr_ary.pop
90
117
  node_attr = attr_ary.reduce(node.normal) do |a, k|
91
- a.respond_to?(:has_key?) && a.has_key?(k) ? a[k] : nil
118
+ a.respond_to?(:key?) && a.key?(k) ? a[k] : nil
92
119
  end
93
- if node_attr.respond_to?(:has_key?) && node_attr.has_key?(last)
120
+ if node_attr.respond_to?(:key?) && node_attr.key?(last)
94
121
  node_attr.delete(last)
95
122
  node.save
96
123
  self.class.cache.delete(cache_key)
@@ -102,10 +129,38 @@ class Chef
102
129
 
103
130
  protected
104
131
 
132
+ # Parses {SearchHelper#search} result.
133
+ #
134
+ # @param res [Array<Hash>] {SearchHelper#search} result.
135
+ # @return [Mixed] final search result value.
136
+ def parse_search_result(res)
137
+ if res.is_a?(Array) && res[0].is_a?(Hash) && res[0].key?('value')
138
+ res[0]['value']
139
+ else
140
+ nil
141
+ end
142
+ end
143
+
144
+ # Generates the cache key.
145
+ #
146
+ # @param name [String] node name.
147
+ # @param attr_ary [Array<String>] node attribute path as Array.
148
+ # @return [String] cache key.
105
149
  def cache_key(name, attr_ary)
106
- "#{name}:#{attr_ary.inspect}" # TODO ok, this can be improved
150
+ "#{name}:#{attr_ary.inspect}" # TODO: OK, this can be improved
107
151
  end
108
152
 
153
+ # Asserts that the attribute path is in the correct format.
154
+ #
155
+ # @param attr_ary [Array<String>] node attribute path as Array.
156
+ # @return void
157
+ # @raise [ArgumentError] if the attribute path format is wrong.
158
+ def assert_attribute_array(attr_ary)
159
+ return if attr_ary.is_a?(Array)
160
+ fail ArgumentError,
161
+ "#{self.class}##{__method__} attr_ary argument must be an array "\
162
+ "of strings. You passed #{attr_ary.inspect}."
163
+ end
109
164
  end
110
165
  end
111
166
  end
@@ -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)
@@ -23,26 +24,76 @@ require 'chef/encrypted_attribute/remote_clients'
23
24
 
24
25
  class Chef
25
26
  class EncryptedAttribute
27
+ # Helpers to search nodes remotely and get it's public keys.
26
28
  class RemoteNodes
27
29
  extend ::Chef::EncryptedAttribute::SearchHelper
28
30
 
31
+ # Remote nodes search results cache.
32
+ #
33
+ # You can disable it setting it's size to zero:
34
+ #
35
+ # ```ruby
36
+ # Chef::EncryptedAttribute::RemoteNodes.cache.max_size(0)
37
+ # ```
38
+ #
39
+ # @return [CacheLru] Remote nodes LRU cache.
29
40
  def self.cache
30
41
  @@cache ||= Chef::EncryptedAttribute::CacheLru.new
31
42
  end
32
43
 
33
- def self.search_public_keys(search='*:*', partial_search=true)
34
- escaped_query = escape_query(search)
35
- if cache.has_key?(escaped_query)
36
- cache[escaped_query]
37
- else
38
- cache[escaped_query] = search(:node, search, {
39
- 'name' => [ 'name' ]
40
- }, 1000, partial_search).map do |node|
41
- RemoteClients.get_public_key(node['name'])
42
- end.compact
43
- end
44
+ # Gets remote node public key.
45
+ #
46
+ # It first tries to read the key from the `node['public_key']` attribute.
47
+ #
48
+ # If the `"public_key"` attribute does not exist, it tries to read the
49
+ # node client key directly using the Chef API (this require **admin**
50
+ # privileges).
51
+ #
52
+ # @param node [Chef::Node] Chef node object.
53
+ # @return [String] Chef client public key as string.
54
+ # @raise [InsufficientPrivileges] if you lack enoght privileges to read
55
+ # the keys from the Chef Server.
56
+ # @raise [ClientNotFound] if client does not exist.
57
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
58
+ def self.get_public_key(node)
59
+ return node['public_key'] unless node['public_key'].nil?
60
+ RemoteClients.get_public_key(node['name'])
61
+ rescue Net::HTTPServerException => e
62
+ raise e unless e.response.code == '403'
63
+ raise InsufficientPrivileges,
64
+ "You cannot read #{node['name']} client key. Consider including "\
65
+ 'the encrypted_attributes::expose_key recipe in the '\
66
+ "#{node['name']} node run list."
44
67
  end
45
68
 
69
+ # Searches for node client public keys.
70
+ #
71
+ # It first tries to read the key from the `node['public_key']` attribute.
72
+ #
73
+ # If the `"public_key"` attribute does not exist, it tries to read the
74
+ # node client key directly using the Chef API (this require **admin**
75
+ # privileges).
76
+ #
77
+ # @param search [Array<String>, String] search queries to perform, the
78
+ # query result will be *OR*-ed.
79
+ # @return [Array<String>] list of public keys.
80
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
81
+ # the keys from the Chef Server.
82
+ # @raise [ClientNotFound] if client does not exist.
83
+ # @raise [Net::HTTPServerException] for Chef Server HTTP errors.
84
+ # @raise [SearchFailure] if there is a Chef search error.
85
+ # @raise [SearchFatalError] if the Chef search response is wrong.
86
+ # @raise [InvalidSearchKeys] if search keys structure is wrong.
87
+ def self.search_public_keys(search = '*:*', partial_search = true)
88
+ escaped_query = escape_query(search)
89
+ return cache[escaped_query] if cache.key?(escaped_query)
90
+ cache[escaped_query] =
91
+ search(
92
+ :node, search,
93
+ { 'name' => %w(name), 'public_key' => %w(public_key) },
94
+ 1000, partial_search
95
+ ).map { |node| get_public_key(node) }.compact
96
+ end
46
97
  end
47
98
  end
48
99
  end
@@ -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)
@@ -22,52 +23,90 @@ require 'chef/encrypted_attribute/cache_lru'
22
23
 
23
24
  class Chef
24
25
  class EncryptedAttribute
26
+ # Helpers to get remote Chef Users keys.
27
+ #
28
+ # @note This class methods require **admin** privileges.
25
29
  class RemoteUsers
26
-
30
+ # Remote users public keys cache.
31
+ #
32
+ # You can disable it setting it's size to zero:
33
+ #
34
+ # ```ruby
35
+ # Chef::EncryptedAttribute::RemoteUsers.cache.max_size(0)
36
+ # ```
37
+ #
38
+ # @return [CacheLru] Remote users LRU cache.
27
39
  def self.cache
28
40
  @@cache ||= Chef::EncryptedAttribute::CacheLru.new
29
41
  end
30
42
 
31
- def self.get_public_keys(users=[])
43
+ # Gets some Chef users public keys.
44
+ #
45
+ # @note This method requires **admin** privileges.
46
+ #
47
+ # @param users [Array<String>, '*'] user list. Use `'*'` to get all users
48
+ # public keys.
49
+ # @return [Array<String>] public key list.
50
+ # @raise [ArgumentError] if user list is wrong.
51
+ def self.get_public_keys(users = [])
32
52
  if users == '*' # users are [a-z0-9\-_]+, cannot be *
33
- if cache.has_key?('*')
34
- cache['*']
35
- else
36
- cache['*'] = get_all_public_keys
37
- end
38
- elsif users.kind_of?(Array)
53
+ cache.key?('*') ? cache['*'] : cache['*'] = all_public_keys
54
+ elsif users.is_a?(Array)
39
55
  get_users_public_keys(users)
40
- elsif not users.nil?
41
- raise ArgumentError, "#{self.class.to_s}##{__method__} users argument must be an array or \"*\"."
56
+ elsif !users.nil?
57
+ fail ArgumentError,
58
+ "#{self.class}##{__method__} users argument must be an array "\
59
+ 'or "*".'
42
60
  end
43
61
  end
44
62
 
45
- protected
46
-
63
+ # Reads a Chef user public key.
64
+ #
65
+ # @note This method requires **admin** privileges.
66
+ #
67
+ # @param name [String] user name.
68
+ # @return [String] user public key as string.
69
+ # @raise [InsufficientPrivileges] if you lack enough privileges to read
70
+ # the keys from the Chef Server.
71
+ # @api private
47
72
  def self.get_user_public_key(name)
48
- return cache[name] if cache.has_key?(name)
73
+ return cache[name] if cache.key?(name)
49
74
  user = Chef::User.load(name)
50
75
  cache[name] = user.public_key
51
76
  rescue Net::HTTPServerException => e
52
77
  case e.response.code
53
78
  when '403'
54
- raise InsufficientPrivileges, 'Your node needs admin privileges to be able to work with Chef Users.'
55
- when '404' # Not Found
56
- raise UserNotFound, "Chef User not found: \"#{name}\"."
79
+ raise InsufficientPrivileges,
80
+ 'Your node needs admin privileges to be able to work with '\
81
+ 'Chef Users.'
82
+ when '404' then raise UserNotFound, "Chef User not found: \"#{name}\"."
57
83
  else
58
84
  raise e
59
85
  end
60
86
  end
61
87
 
88
+ # Gets some Chef users public keys.
89
+ #
90
+ # @note This method requires **admin** privileges.
91
+ #
92
+ # @param users [Array<String>] user list.
93
+ # @return [Array<String>] public key list.
94
+ # @api private
62
95
  def self.get_users_public_keys(users)
63
96
  users.map { |n| get_user_public_key(n) }
64
97
  end
65
98
 
66
- def self.get_all_public_keys
67
- # Chef::User.list(inflate=true) has a bug
99
+ # Gets all Chef users public keys.
100
+ #
101
+ # @note This method requires **admin** privileges.
102
+ #
103
+ # @return [Array<String>] public key list.
104
+ # @api private
105
+ def self.all_public_keys
106
+ # Chef::User.list(inflate=true) has a bug (fixed in 11.14.0)
107
+ # https://tickets.opscode.com/browse/CHEF-5328
68
108
  get_users_public_keys(Chef::User.list.keys)
69
109
  end
70
-
71
110
  end
72
111
  end
73
112
  end