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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +40 -4
- data/CONTRIBUTING.md +7 -6
- data/KNIFE.md +151 -0
- data/README.md +70 -192
- data/Rakefile +27 -14
- data/TESTING.md +18 -7
- data/TODO.md +2 -5
- data/lib/chef-encrypted-attributes.rb +7 -1
- data/lib/chef/encrypted_attribute.rb +282 -121
- data/lib/chef/encrypted_attribute/api.rb +521 -0
- data/lib/chef/encrypted_attribute/assertions.rb +16 -6
- data/lib/chef/encrypted_attribute/cache_lru.rb +54 -13
- data/lib/chef/encrypted_attribute/config.rb +198 -89
- data/lib/chef/encrypted_attribute/encrypted_mash.rb +127 -33
- data/lib/chef/encrypted_attribute/encrypted_mash/version0.rb +236 -48
- data/lib/chef/encrypted_attribute/encrypted_mash/version1.rb +249 -36
- data/lib/chef/encrypted_attribute/encrypted_mash/version2.rb +133 -19
- data/lib/chef/encrypted_attribute/exceptions.rb +19 -3
- data/lib/chef/encrypted_attribute/local_node.rb +15 -4
- data/lib/chef/encrypted_attribute/remote_clients.rb +33 -17
- data/lib/chef/encrypted_attribute/remote_node.rb +84 -29
- data/lib/chef/encrypted_attribute/remote_nodes.rb +62 -11
- data/lib/chef/encrypted_attribute/remote_users.rb +58 -19
- data/lib/chef/encrypted_attribute/search_helper.rb +214 -74
- data/lib/chef/encrypted_attribute/version.rb +3 -1
- data/lib/chef/encrypted_attributes.rb +20 -0
- data/lib/chef/knife/core/config.rb +4 -1
- data/lib/chef/knife/core/encrypted_attribute_base.rb +179 -0
- data/lib/chef/knife/core/encrypted_attribute_depends.rb +43 -0
- data/lib/chef/knife/core/encrypted_attribute_editor_options.rb +125 -61
- data/lib/chef/knife/encrypted_attribute_create.rb +51 -31
- data/lib/chef/knife/encrypted_attribute_delete.rb +32 -40
- data/lib/chef/knife/encrypted_attribute_edit.rb +51 -32
- data/lib/chef/knife/encrypted_attribute_show.rb +30 -55
- data/lib/chef/knife/encrypted_attribute_update.rb +43 -28
- data/spec/benchmark_helper.rb +2 -1
- data/spec/integration_helper.rb +1 -0
- data/spec/spec_helper.rb +21 -7
- metadata +75 -36
- metadata.gz.sig +1 -1
- data/API.md +0 -174
- data/INTERNAL.md +0 -166
@@ -0,0 +1,43 @@
|
|
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/knife'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
module Core
|
25
|
+
# Loads knife encrypted attribute dependencies.
|
26
|
+
module EncryptedAttributeDepends
|
27
|
+
# Reopens EncryptedAttributeDepends class to define knife dependencies.
|
28
|
+
#
|
29
|
+
# Includes the required gems to work with encrypted attributes.
|
30
|
+
#
|
31
|
+
# @param includer [Class] includer class.
|
32
|
+
def self.included(includer)
|
33
|
+
includer.class_eval do
|
34
|
+
deps do
|
35
|
+
require 'chef/encrypted_attribute'
|
36
|
+
require 'chef/json_compat'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
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)
|
@@ -21,88 +22,151 @@ require 'chef/knife/core/config'
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
23
24
|
module Core
|
24
|
-
|
25
|
+
# Reads knife encrypted attribute edit commands arguments
|
25
26
|
module EncryptedAttributeEditorOptions
|
27
|
+
# Reopens EncryptedAttributeEditorOptions class to define knife
|
28
|
+
# argument options.
|
29
|
+
#
|
30
|
+
# @param includer [Class] includer class.
|
26
31
|
def self.included(includer)
|
27
32
|
includer.class_eval do
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
# Helper method to set the encrypted attributes configuration.
|
35
|
+
def self.encrypted_attributes_option_set(key, value)
|
36
|
+
Chef::Config[:knife][:encrypted_attributes][key] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
# Helper method to add a value to an encrypted configuration array
|
40
|
+
# option.
|
41
|
+
def self.encrypted_attributes_option_push(key, value)
|
42
|
+
unless Chef::Config[:knife][:encrypted_attributes][key]
|
43
|
+
.is_a?(Array)
|
44
|
+
Chef::Config[:knife][:encrypted_attributes][key] = []
|
45
|
+
end
|
46
|
+
Chef::Config[:knife][:encrypted_attributes][key] << value
|
32
47
|
end
|
33
48
|
|
34
49
|
option :encrypted_attribute_version,
|
35
|
-
|
36
|
-
|
37
|
-
|
50
|
+
long: '--encrypted-attribute-version VERSION',
|
51
|
+
description: 'Encrypted Attribute protocol version to use',
|
52
|
+
proc: ->(i) { encrypted_attributes_option_set(:version, i) }
|
38
53
|
|
39
54
|
option :encrypted_attribute_partial_search,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
55
|
+
short: '-P',
|
56
|
+
long: '--disable-partial-search',
|
57
|
+
description: 'Disable partial search',
|
58
|
+
boolean: true,
|
59
|
+
proc:
|
60
|
+
(lambda do |_i|
|
61
|
+
encrypted_attributes_option_set(:partial_search, false)
|
62
|
+
end)
|
45
63
|
|
46
64
|
option :encrypted_attribute_client_search,
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
65
|
+
short: '-C CLIENT_SEARCH_QUERY',
|
66
|
+
long: '--client-search CLIENT_SEARCH_QUERY',
|
67
|
+
description:
|
68
|
+
'Client search query. Can be specified multiple times',
|
69
|
+
proc:
|
70
|
+
(lambda do |i|
|
71
|
+
encrypted_attributes_option_push(:client_search, i)
|
72
|
+
end)
|
54
73
|
|
55
74
|
option :encrypted_attribute_node_search,
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
}
|
75
|
+
short: '-N NODE_SEARCH_QUERY',
|
76
|
+
long: '--node-search NODE_SEARCH_QUERY',
|
77
|
+
description:
|
78
|
+
'Node search query. Can be specified multiple times',
|
79
|
+
proc:
|
80
|
+
->(i) { encrypted_attributes_option_push(:node_search, i) }
|
63
81
|
|
64
82
|
option :encrypted_attribute_users,
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
}
|
83
|
+
short: '-U USER',
|
84
|
+
long: '--encrypted-attribute-user USER',
|
85
|
+
description:
|
86
|
+
'User name to allow access to. Can be specified multiple '\
|
87
|
+
'times',
|
88
|
+
proc: ->(i) { encrypted_attributes_option_push(:users, i) }
|
72
89
|
|
73
|
-
# TODO option :keys
|
90
|
+
# TODO: option :keys
|
91
|
+
end # includer.class_eval
|
92
|
+
end # self.included(includer)
|
74
93
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
94
|
+
# Converts a string data to a Ruby value.
|
95
|
+
#
|
96
|
+
# @param data [String] data to convert.
|
97
|
+
# @param format [String] `'plain'` or `'json'`.
|
98
|
+
# @return [String, Mixed] Ruby value.
|
99
|
+
def edit_data_string_to_obj(data, format)
|
100
|
+
case format
|
101
|
+
when 'JSON', 'json'
|
102
|
+
if data.nil?
|
103
|
+
{}
|
104
|
+
else
|
105
|
+
Chef::JSONCompat.to_json_pretty(data, quirks_mode: true)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
data.nil? ? '' : data
|
109
|
+
end
|
110
|
+
end
|
83
111
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
112
|
+
# Converts Ruby values to string.
|
113
|
+
#
|
114
|
+
# @param data [Mixed] Ruby value to convert.
|
115
|
+
# @param format [String] `'plain'` or `'json'`.
|
116
|
+
# @return [String] value encoded as string.
|
117
|
+
def edit_data_obj_to_string(data, format)
|
118
|
+
case format
|
119
|
+
when 'JSON', 'json'
|
120
|
+
FFI_Yajl::Parser.parse(data)
|
121
|
+
else
|
122
|
+
data
|
123
|
+
end
|
124
|
+
end
|
90
125
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
126
|
+
# Runs system editor.
|
127
|
+
#
|
128
|
+
# @param path [String] path file to edit.
|
129
|
+
# @return void
|
130
|
+
# @raise [RuntimeError] if the editing command fails.
|
131
|
+
def edit_data_run_editor_command(path)
|
132
|
+
return if system("#{config[:editor]} #{path}")
|
133
|
+
fail 'Please set EDITOR environment variable'
|
134
|
+
end
|
95
135
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
136
|
+
# Edits a data using the system editor.
|
137
|
+
#
|
138
|
+
# Creates a temporal file to edit the data value.
|
139
|
+
#
|
140
|
+
# @param data [String] data to edit.
|
141
|
+
# @return [String] the data after the editing.
|
142
|
+
# @raise [RuntimeError] if the editing command fails.
|
143
|
+
def edit_data_run_editor(data)
|
144
|
+
return if config[:disable_editing]
|
145
|
+
result = nil
|
146
|
+
Tempfile.open(%w(knife-edit- .json)) do |tf|
|
147
|
+
tf.sync = true
|
148
|
+
tf.puts(data)
|
149
|
+
tf.close
|
150
|
+
edit_data_run_editor_command(tf.path)
|
151
|
+
result = IO.read(tf.path)
|
152
|
+
end
|
153
|
+
result
|
154
|
+
end
|
103
155
|
|
104
|
-
|
105
|
-
|
156
|
+
# Edits data using an editor.
|
157
|
+
#
|
158
|
+
# Modified `Chef::Knife::UI#edit_data` method with plain text format
|
159
|
+
# support
|
160
|
+
#
|
161
|
+
# @param data [String] default data value to edit.
|
162
|
+
# @param format [String] `'plain'` or `'json'`.
|
163
|
+
# @return [String] resulting data value after edition.
|
164
|
+
# @raise [RuntimeError] if the editing command fails.
|
165
|
+
def edit_data(data = nil, format = 'plain')
|
166
|
+
output = edit_data_string_to_obj(data, format)
|
167
|
+
output = edit_data_run_editor(output)
|
168
|
+
edit_data_obj_to_string(output, format)
|
169
|
+
end # def edit_data
|
106
170
|
end # EncryptedAttributeEditorOptions
|
107
171
|
end # Core
|
108
172
|
end # Knife
|
@@ -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,52 +17,71 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require 'chef/knife/
|
20
|
+
require 'chef/knife/core/encrypted_attribute_base'
|
21
|
+
require 'chef/knife/core/encrypted_attribute_depends'
|
20
22
|
require 'chef/knife/core/encrypted_attribute_editor_options'
|
21
23
|
|
22
24
|
class Chef
|
23
25
|
class Knife
|
24
|
-
|
25
|
-
|
26
|
+
# knife encrypted attribute create command.
|
27
|
+
#
|
28
|
+
# ```
|
29
|
+
# $ knife encrypted attribute create NODE ATTRIBUTE (options)
|
30
|
+
# ```
|
31
|
+
class EncryptedAttributeCreate < Core::EncryptedAttributeBase
|
32
|
+
include Knife::Core::EncryptedAttributeDepends
|
26
33
|
include Knife::Core::EncryptedAttributeEditorOptions
|
27
34
|
|
28
35
|
option :input_format,
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
short: '-i FORMAT',
|
37
|
+
long: '--input-format FORMAT',
|
38
|
+
description:
|
39
|
+
'Input (EDITOR) format, supported formats are "plain" '\
|
40
|
+
'(default) and "json"'
|
32
41
|
|
33
42
|
banner 'knife encrypted attribute create NODE ATTRIBUTE (options)'
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if node_name.nil?
|
40
|
-
show_usage
|
41
|
-
ui.fatal('You must specify a node name')
|
42
|
-
exit 1
|
43
|
-
end
|
44
|
-
|
45
|
-
if attr_path.nil?
|
46
|
-
show_usage
|
47
|
-
ui.fatal('You must specify an encrypted attribute name')
|
48
|
-
exit 1
|
49
|
-
end
|
50
|
-
|
51
|
-
attr_ary = attribute_path_to_ary(attr_path)
|
52
|
-
|
44
|
+
# (see EncryptedAttributeBase#assert_valid_args)
|
45
|
+
# @raise [ArgumentError] if the attribute path format is wrong.
|
46
|
+
def assert_valid_args
|
53
47
|
# check if the encrypted attribute already exists
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
assert_attribute_does_not_exist(@node_name, @attr_ary)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Runs knife command.
|
52
|
+
#
|
53
|
+
# @raise [RuntimeError] if the editing command fails.
|
54
|
+
# @raise [ArgumentError] if the attribute path format or the user list is
|
55
|
+
# wrong.
|
56
|
+
# @raise [UnacceptableEncryptedAttributeFormat] if encrypted attribute
|
57
|
+
# format is wrong or does not exist.
|
58
|
+
# @raise [UnsupportedEncryptedAttributeFormat] if encrypted attribute
|
59
|
+
# format is not supported or unknown.
|
60
|
+
# @raise [EncryptionFailure] if there are encryption errors.
|
61
|
+
# @raise [MessageAuthenticationFailure] if HMAC calculation error.
|
62
|
+
# @raise [InvalidPublicKey] if it is not a valid RSA public key.
|
63
|
+
# @raise [InvalidKey] if the RSA key format is wrong.
|
64
|
+
# @raise [InsufficientPrivileges] if you lack enough privileges to read
|
65
|
+
# the keys from the Chef Server.
|
66
|
+
# @raise [ClientNotFound] if client does not exist.
|
67
|
+
# @raise [Net::HTTPServerException] for Chef Server HTTP errors.
|
68
|
+
# @raise [RequirementsFailure] if the specified encrypted attribute
|
69
|
+
# version cannot be used.
|
70
|
+
# @raise [SearchFailure] if there is a Chef search error.
|
71
|
+
# @raise [SearchFatalError] if the Chef search response is wrong.
|
72
|
+
# @raise [InvalidSearchKeys] if search keys structure is wrong.
|
73
|
+
# @return void
|
74
|
+
def run
|
75
|
+
parse_args
|
58
76
|
|
59
77
|
# create encrypted attribute
|
60
78
|
output = edit_data(nil, config[:input_format])
|
61
|
-
enc_attr =
|
62
|
-
|
79
|
+
enc_attr =
|
80
|
+
Chef::EncryptedAttribute.new(
|
81
|
+
Chef::Config[:knife][:encrypted_attributes]
|
82
|
+
)
|
83
|
+
enc_attr.create_on_node(@node_name, @attr_ary, output)
|
63
84
|
end
|
64
|
-
|
65
85
|
end
|
66
86
|
end
|
67
87
|
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)
|
@@ -16,56 +17,47 @@
|
|
16
17
|
# limitations under the License.
|
17
18
|
#
|
18
19
|
|
19
|
-
require 'chef/knife'
|
20
|
-
require 'chef/knife/
|
20
|
+
require 'chef/knife/core/encrypted_attribute_base'
|
21
|
+
require 'chef/knife/core/encrypted_attribute_depends'
|
21
22
|
require 'chef/encrypted_attribute/remote_node'
|
22
23
|
|
23
24
|
class Chef
|
24
25
|
class Knife
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
# knife encrypted attribute delete command.
|
27
|
+
#
|
28
|
+
# ```
|
29
|
+
# $ knife encrypted attribute delete NODE ATTRIBUTE (options)
|
30
|
+
# ```
|
31
|
+
class EncryptedAttributeDelete < Core::EncryptedAttributeBase
|
32
|
+
include Knife::Core::EncryptedAttributeDepends
|
31
33
|
|
32
34
|
banner 'knife encrypted attribute delete NODE ATTRIBUTE (options)'
|
33
35
|
|
34
36
|
option :force,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
short: '-f',
|
38
|
+
long: '--force',
|
39
|
+
description:
|
40
|
+
'Force the attribute deletion even if you cannot read it',
|
41
|
+
boolean: true
|
42
|
+
|
43
|
+
# Runs knife command.
|
44
|
+
#
|
45
|
+
# @return void
|
46
|
+
# @raise [ArgumentError] if the attribute path format is wrong.
|
47
|
+
# @raise [SearchFailure] if there is a Chef search error.
|
48
|
+
# @raise [SearchFatalError] if the Chef search response is wrong.
|
49
|
+
# @raise [InvalidSearchKeys] if search keys structure is wrong.
|
40
50
|
def run
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
if attr_path.nil?
|
51
|
-
show_usage
|
52
|
-
ui.fatal('You must specify an encrypted attribute name')
|
53
|
-
exit 1
|
54
|
-
end
|
55
|
-
|
56
|
-
attr_ary = attribute_path_to_ary(attr_path)
|
57
|
-
if Chef::EncryptedAttribute.exist_on_node?(node_name, attr_ary)
|
58
|
-
# TODO move this to lib/EncryptedAttribute
|
59
|
-
unless config[:force] # try to read the attribute
|
60
|
-
Chef::EncryptedAttribute.load_from_node(node_name, attr_ary)
|
61
|
-
end
|
62
|
-
remote_node = Chef::EncryptedAttribute::RemoteNode.new(node_name)
|
63
|
-
if remote_node.delete_attribute(attr_ary)
|
64
|
-
ui.info('Encrypted attribute deleted.')
|
65
|
-
end
|
66
|
-
end
|
51
|
+
parse_args
|
52
|
+
|
53
|
+
return unless
|
54
|
+
Chef::EncryptedAttribute.exist_on_node?(@node_name, @attr_ary)
|
55
|
+
# TODO: move this to lib/EncryptedAttribute
|
56
|
+
assert_attribute_readable(@node_name, @attr_ary) unless config[:force]
|
57
|
+
remote_node = Chef::EncryptedAttribute::RemoteNode.new(@node_name)
|
58
|
+
return unless remote_node.delete_attribute(@attr_ary)
|
59
|
+
ui.info('Encrypted attribute deleted.')
|
67
60
|
end
|
68
|
-
|
69
61
|
end
|
70
62
|
end
|
71
63
|
end
|