chef-encrypted-attributes 0.1.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 +7 -0
- data/API.md +163 -0
- data/CHANGELOG.md +7 -0
- data/INTERNAL.md +111 -0
- data/LICENSE +190 -0
- data/README.md +330 -0
- data/Rakefile +46 -0
- data/TESTING.md +45 -0
- data/TODO.md +20 -0
- data/lib/chef-encrypted-attributes.rb +19 -0
- data/lib/chef/encrypted_attribute.rb +218 -0
- data/lib/chef/encrypted_attribute/cache_lru.rb +74 -0
- data/lib/chef/encrypted_attribute/config.rb +200 -0
- data/lib/chef/encrypted_attribute/encrypted_mash.rb +122 -0
- data/lib/chef/encrypted_attribute/encrypted_mash/version0.rb +143 -0
- data/lib/chef/encrypted_attribute/encrypted_mash/version1.rb +140 -0
- data/lib/chef/encrypted_attribute/exceptions.rb +38 -0
- data/lib/chef/encrypted_attribute/local_node.rb +38 -0
- data/lib/chef/encrypted_attribute/remote_clients.rb +46 -0
- data/lib/chef/encrypted_attribute/remote_node.rb +111 -0
- data/lib/chef/encrypted_attribute/remote_users.rb +73 -0
- data/lib/chef/encrypted_attribute/search_helper.rb +144 -0
- data/lib/chef/encrypted_attribute/version.rb +23 -0
- data/lib/chef/knife/core/config.rb +19 -0
- data/lib/chef/knife/core/encrypted_attribute_editor_options.rb +100 -0
- data/lib/chef/knife/encrypted_attribute_create.rb +67 -0
- data/lib/chef/knife/encrypted_attribute_delete.rb +71 -0
- data/lib/chef/knife/encrypted_attribute_edit.rb +68 -0
- data/lib/chef/knife/encrypted_attribute_show.rb +86 -0
- data/lib/chef/knife/encrypted_attribute_update.rb +65 -0
- data/spec/benchmark_helper.rb +32 -0
- data/spec/integration_helper.rb +20 -0
- data/spec/spec_helper.rb +38 -0
- metadata +204 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Xabier de Zuazo (<xabier@onddo.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/mash'
|
20
|
+
require 'chef/encrypted_attribute/exceptions'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class EncryptedAttribute
|
24
|
+
class EncryptedMash < Mash
|
25
|
+
|
26
|
+
# This class is oriented to be easily integrable with
|
27
|
+
# chef in the future using JSONCompat
|
28
|
+
|
29
|
+
JSON_CLASS = 'x_json_class'.freeze
|
30
|
+
CHEF_TYPE = 'chef_type'.freeze
|
31
|
+
CHEF_TYPE_VALUE = 'encrypted_attribute'.freeze
|
32
|
+
|
33
|
+
VERSION_PREFIX = "#{self.name}::Version"
|
34
|
+
|
35
|
+
def initialize(enc_hs=nil)
|
36
|
+
super
|
37
|
+
self[JSON_CLASS] = self.class.name
|
38
|
+
self[CHEF_TYPE] = CHEF_TYPE_VALUE
|
39
|
+
update_from!(enc_hs) if enc_hs.kind_of?(Hash)
|
40
|
+
end
|
41
|
+
|
42
|
+
%w{encrypt decrypt can_be_decrypted_by? needs_update?}.each do |meth|
|
43
|
+
define_method(meth) do
|
44
|
+
raise NotImplementedError, "#{self.class.to_s}##{__method__} method not implemented."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.exists?(enc_hs)
|
49
|
+
enc_hs.kind_of?(Hash) and
|
50
|
+
enc_hs.has_key?(JSON_CLASS) and
|
51
|
+
enc_hs[JSON_CLASS] =~ /^#{Regexp.escape(Module.nesting[1].name)}/ and
|
52
|
+
enc_hs.has_key?(CHEF_TYPE) and enc_hs[CHEF_TYPE] == CHEF_TYPE_VALUE
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.create(version)
|
56
|
+
klass = version_klass(version)
|
57
|
+
klass.send(:new)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Serialize this object as a Hash
|
61
|
+
def to_json(*a)
|
62
|
+
for_json.to_json(*a)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a Hash for JSON
|
66
|
+
def for_json
|
67
|
+
to_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
# Update the EncryptedMash from Hash
|
71
|
+
def update_from!(enc_hs)
|
72
|
+
unless self.class.exists?(enc_hs)
|
73
|
+
raise UnacceptableEncryptedAttributeFormat, 'Trying to construct invalid encrypted attribute. Maybe it is not encrypted?'
|
74
|
+
end
|
75
|
+
enc_hs = enc_hs.dup
|
76
|
+
enc_hs.delete(JSON_CLASS)
|
77
|
+
enc_hs.delete(CHEF_TYPE)
|
78
|
+
update(enc_hs)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Create an EncryptedMash::Version from JSON Hash
|
82
|
+
def self.json_create(enc_hs)
|
83
|
+
klass = string_to_klass(enc_hs[JSON_CLASS])
|
84
|
+
if klass.nil?
|
85
|
+
raise UnsupportedEncryptedAttributeFormat, "Unknown chef-encrypted-attribute class \"#{enc_hs[JSON_CLASS]}\""
|
86
|
+
end
|
87
|
+
klass.send(:new, enc_hs)
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def self.string_to_klass(class_name)
|
93
|
+
unless class_name.kind_of?(String)
|
94
|
+
raise UnacceptableEncryptedAttributeFormat, "Bad chef-encrypted-attribute class name \"#{class_name.inspect}\""
|
95
|
+
end
|
96
|
+
begin
|
97
|
+
if RUBY_VERSION < '1.9'
|
98
|
+
class_name.split('::').inject(Kernel) { |scope, const| scope.const_get(const) }
|
99
|
+
else
|
100
|
+
class_name.split('::').inject(Kernel) { |scope, const| scope.const_get(const, scope === Kernel) }
|
101
|
+
end
|
102
|
+
rescue NameError => e
|
103
|
+
Chef::Log.error(e)
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.version_klass(version)
|
109
|
+
version = version.to_s unless version.kind_of?(String)
|
110
|
+
if version.empty?
|
111
|
+
raise UnacceptableEncryptedAttributeFormat, "Bad chef-encrypted-attribute version \"#{version.inspect}\""
|
112
|
+
end
|
113
|
+
klass = string_to_klass("#{VERSION_PREFIX}#{version}")
|
114
|
+
if klass.nil?
|
115
|
+
raise UnsupportedEncryptedAttributeFormat, "This version of chef-encrypted-attribute does not support encrypted attribute item format version: \"#{version}\""
|
116
|
+
end
|
117
|
+
klass
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Xabier de Zuazo (<xabier@onddo.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/encrypted_attribute/encrypted_mash'
|
20
|
+
require 'chef/encrypted_attribute/exceptions'
|
21
|
+
require 'yajl'
|
22
|
+
|
23
|
+
# Version0 format: using RSA without shared secret
|
24
|
+
class Chef
|
25
|
+
class EncryptedAttribute
|
26
|
+
class EncryptedMash
|
27
|
+
class Version0 < Chef::EncryptedAttribute::EncryptedMash
|
28
|
+
|
29
|
+
def encrypt(value, public_keys)
|
30
|
+
value_json = json_encode(value)
|
31
|
+
public_keys = parse_public_keys(public_keys)
|
32
|
+
self['encrypted_data'] = rsa_encrypt_multi_key(value_json, public_keys)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def decrypt(key)
|
37
|
+
key = parse_decryption_key(key)
|
38
|
+
value_json = rsa_decrypt_multi_key(self['encrypted_data'], key)
|
39
|
+
json_decode(value_json)
|
40
|
+
# we avoid saving the decrypted value, only return it
|
41
|
+
end
|
42
|
+
|
43
|
+
def can_be_decrypted_by?(keys)
|
44
|
+
return false unless encrypted?
|
45
|
+
parse_public_keys(keys).reduce(true) do |r, k|
|
46
|
+
r and data_can_be_decrypted_by_key?(self['encrypted_data'], k)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def needs_update?(keys)
|
51
|
+
keys = parse_public_keys(keys)
|
52
|
+
not can_be_decrypted_by?(keys) && self['encrypted_data'].keys.count == keys.count
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def encrypted?
|
58
|
+
has_key?('encrypted_data') and self['encrypted_data'].kind_of?(Hash)
|
59
|
+
end
|
60
|
+
|
61
|
+
def pem_to_key(k)
|
62
|
+
k.kind_of?(OpenSSL::PKey::RSA) ? k : OpenSSL::PKey::RSA.new(k)
|
63
|
+
rescue OpenSSL::PKey::RSAError, TypeError => e
|
64
|
+
raise InvalidPrivateKey, "The provided key is invalid: #{k.inspect}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_public_key(key)
|
68
|
+
key = pem_to_key(key)
|
69
|
+
unless key.public?
|
70
|
+
raise InvalidPublicKey, 'Invalid public key provided.'
|
71
|
+
end
|
72
|
+
key
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_decryption_key(key)
|
76
|
+
key = pem_to_key(key)
|
77
|
+
unless key.public? and key.private?
|
78
|
+
raise InvalidPrivateKey, 'The provided key for decryption is invalid, a valid public and private key is required.'
|
79
|
+
end
|
80
|
+
unless can_be_decrypted_by?(key) # TODO optimize, node key digest is calculated multiple times
|
81
|
+
raise DecryptionFailure, 'Attribute data cannot be decrypted by the provided key.'
|
82
|
+
end
|
83
|
+
key
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_public_keys(keys)
|
87
|
+
keys = [ keys ].flatten
|
88
|
+
keys.map do |k|
|
89
|
+
parse_public_key(k)
|
90
|
+
end.uniq { |k| k.public_key.to_s.chomp }
|
91
|
+
end
|
92
|
+
|
93
|
+
def json_encode(o)
|
94
|
+
# TODO This does not check if the object is correct, should be an Array or a Hash
|
95
|
+
Yajl::Encoder.encode(o)
|
96
|
+
end
|
97
|
+
|
98
|
+
def json_decode(o)
|
99
|
+
Yajl::Parser.parse(o.to_s)
|
100
|
+
rescue Yajl::ParseError => e
|
101
|
+
raise DecryptionFailure, "#{e.class.name}: #{e.to_s}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def node_key(public_key)
|
105
|
+
Digest::SHA1.hexdigest(public_key.to_der)
|
106
|
+
end
|
107
|
+
|
108
|
+
def rsa_encrypt_value(value, public_key)
|
109
|
+
Base64.encode64(public_key.public_encrypt(value))
|
110
|
+
rescue OpenSSL::PKey::RSAError => e
|
111
|
+
raise EncryptionFailure, "#{e.class.name}: #{e.to_s}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def rsa_decrypt_value(value, key)
|
115
|
+
key.private_decrypt(Base64.decode64(value.to_s))
|
116
|
+
rescue OpenSSL::PKey::RSAError => e
|
117
|
+
raise DecryptionFailure, "#{e.class.name}: #{e.to_s}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def rsa_encrypt_multi_key(value, public_keys)
|
121
|
+
Mash.new(Hash[
|
122
|
+
public_keys.map do |public_key|
|
123
|
+
[
|
124
|
+
node_key(public_key),
|
125
|
+
rsa_encrypt_value(value, public_key),
|
126
|
+
]
|
127
|
+
end
|
128
|
+
])
|
129
|
+
end
|
130
|
+
|
131
|
+
def rsa_decrypt_multi_key(enc_value, key)
|
132
|
+
enc_value = enc_value[node_key(key.public_key)]
|
133
|
+
rsa_decrypt_value(enc_value, key)
|
134
|
+
end
|
135
|
+
|
136
|
+
def data_can_be_decrypted_by_key?(enc_value, key)
|
137
|
+
enc_value.has_key?(node_key(key.public_key))
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Xabier de Zuazo (<xabier@onddo.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/encrypted_attribute/encrypted_mash/version0'
|
20
|
+
require 'chef/encrypted_attribute/exceptions'
|
21
|
+
|
22
|
+
# Version1 format: using RSA with a shared secret and message authentication (HMAC)
|
23
|
+
class Chef
|
24
|
+
class EncryptedAttribute
|
25
|
+
class EncryptedMash
|
26
|
+
class Version1 < Chef::EncryptedAttribute::EncryptedMash::Version0
|
27
|
+
SYMM_ALGORITHM = 'aes-256-cbc'
|
28
|
+
HMAC_ALGORITHM = 'sha256'
|
29
|
+
|
30
|
+
def encrypt(value, public_keys)
|
31
|
+
secrets = {}
|
32
|
+
value_json = json_encode(value)
|
33
|
+
public_keys = parse_public_keys(public_keys)
|
34
|
+
# encrypt the data
|
35
|
+
encrypted_data = symmetric_encrypt_value(value_json)
|
36
|
+
secrets['data'] = encrypted_data.delete('secret') # should no include the secret in clear
|
37
|
+
self['encrypted_data'] = encrypted_data
|
38
|
+
# generate hmac (encrypt-then-mac), excluding the secret
|
39
|
+
hmac = generate_hmac(json_encode(self['encrypted_data'].sort))
|
40
|
+
secrets['hmac'] = hmac.delete('secret')
|
41
|
+
self['hmac'] = hmac
|
42
|
+
# encrypt the shared secrets
|
43
|
+
self['encrypted_secret'] = rsa_encrypt_multi_key(json_encode(secrets), public_keys)
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def decrypt(key)
|
48
|
+
key = parse_decryption_key(key)
|
49
|
+
enc_value = self['encrypted_data'].dup
|
50
|
+
hmac = self['hmac'].dup
|
51
|
+
# decrypt the shared secrets
|
52
|
+
secrets = json_decode(rsa_decrypt_multi_key(self['encrypted_secret'], key))
|
53
|
+
enc_value['secret'] = secrets['data']
|
54
|
+
hmac['secret'] = secrets['hmac']
|
55
|
+
# check hmac (encrypt-then-mac -> mac-then-decrypt)
|
56
|
+
unless hmac_matches?(hmac, json_encode(self['encrypted_data'].sort))
|
57
|
+
raise DecryptionFailure, 'Error decrypting encrypted attribute: invalid hmac. Most likely the data is corrupted.'
|
58
|
+
end
|
59
|
+
# decrypt the data
|
60
|
+
value_json = symmetric_decrypt_value(enc_value)
|
61
|
+
json_decode(value_json)
|
62
|
+
end
|
63
|
+
|
64
|
+
def can_be_decrypted_by?(keys)
|
65
|
+
return false unless encrypted?
|
66
|
+
parse_public_keys(keys).reduce(true) do |r, k|
|
67
|
+
r and data_can_be_decrypted_by_key?(self['encrypted_secret'], k)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def needs_update?(keys)
|
72
|
+
keys = parse_public_keys(keys)
|
73
|
+
not can_be_decrypted_by?(keys) && self['encrypted_secret'].keys.count == keys.count
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def encrypted?
|
79
|
+
super and
|
80
|
+
self['encrypted_data'].has_key?('iv') and
|
81
|
+
self['encrypted_data']['iv'].kind_of?(String) and
|
82
|
+
self['encrypted_data'].has_key?('data') and
|
83
|
+
self['encrypted_data']['data'].kind_of?(String) and
|
84
|
+
self['encrypted_secret'].kind_of?(Hash) and
|
85
|
+
self['hmac'].kind_of?(Hash) and
|
86
|
+
self['hmac'].has_key?('data') and
|
87
|
+
self['hmac']['data'].kind_of?(String)
|
88
|
+
end
|
89
|
+
|
90
|
+
def symmetric_encrypt_value(value, algo=SYMM_ALGORITHM)
|
91
|
+
enc_value = Mash.new({ 'cipher' => algo })
|
92
|
+
begin
|
93
|
+
cipher = OpenSSL::Cipher.new(algo)
|
94
|
+
cipher.encrypt
|
95
|
+
enc_value['iv'] = Base64.encode64(cipher.iv = cipher.random_iv)
|
96
|
+
enc_value['secret'] = Base64.encode64(cipher.key = cipher.random_key)
|
97
|
+
enc_data = cipher.update(value) + cipher.final
|
98
|
+
rescue OpenSSL::Cipher::CipherError => e
|
99
|
+
raise EncryptionFailure, "#{e.class.name}: #{e.to_s}"
|
100
|
+
end
|
101
|
+
enc_value['data'] = Base64.encode64(enc_data)
|
102
|
+
enc_value
|
103
|
+
end
|
104
|
+
|
105
|
+
def symmetric_decrypt_value(enc_value, algo=SYMM_ALGORITHM)
|
106
|
+
cipher = OpenSSL::Cipher.new(enc_value['cipher'] || algo) # TODO maybe it's better to ignore [cipher] ?
|
107
|
+
cipher.decrypt
|
108
|
+
cipher.iv = Base64.decode64(enc_value['iv'])
|
109
|
+
cipher.key = Base64.decode64(enc_value['secret'])
|
110
|
+
cipher.update(Base64.decode64(enc_value['data'])) + cipher.final
|
111
|
+
rescue OpenSSL::Cipher::CipherError => e
|
112
|
+
raise DecryptionFailure, "#{e.class.name}: #{e.to_s}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def generate_hmac(data, algo=HMAC_ALGORITHM)
|
116
|
+
hmac = Mash.new({ 'cipher' => algo }) # [cipher] is ignored, only as info
|
117
|
+
digest = OpenSSL::Digest.new(algo)
|
118
|
+
secret = OpenSSL::Random.random_bytes(digest.block_length)
|
119
|
+
hmac['secret'] = Base64.encode64(secret)
|
120
|
+
hmac['data'] = Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data))
|
121
|
+
hmac
|
122
|
+
rescue OpenSSL::Digest::DigestError, OpenSSL::HMACError, RuntimeError => e
|
123
|
+
# RuntimeError is raised for unsupported algorithms
|
124
|
+
raise MessageAuthenticationFailure, "#{e.class.name}: #{e.to_s}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def hmac_matches?(orig_hmac, data, algo=HMAC_ALGORITHM)
|
128
|
+
digest = OpenSSL::Digest.new(algo)
|
129
|
+
secret = Base64.decode64(orig_hmac['secret'])
|
130
|
+
new_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data))
|
131
|
+
orig_hmac['data'] == new_hmac
|
132
|
+
rescue OpenSSL::Digest::DigestError, OpenSSL::HMACError, RuntimeError => e
|
133
|
+
# RuntimeError is raised for unsupported algorithms
|
134
|
+
raise MessageAuthenticationFailure, "#{e.class.name}: #{e.to_s}"
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Xabier de Zuazo (<xabier@onddo.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class EncryptedAttribute
|
21
|
+
|
22
|
+
class UnsupportedEncryptedAttributeFormat < StandardError; end
|
23
|
+
class UnacceptableEncryptedAttributeFormat < StandardError; end
|
24
|
+
class DecryptionFailure < StandardError; end
|
25
|
+
class EncryptionFailure < StandardError; end
|
26
|
+
class MessageAuthenticationFailure < StandardError; end
|
27
|
+
class InvalidPublicKey < StandardError; end
|
28
|
+
class InvalidPrivateKey < StandardError; end
|
29
|
+
|
30
|
+
class InsufficientPrivileges < StandardError; end
|
31
|
+
class UserNotFound < StandardError; end
|
32
|
+
|
33
|
+
class SearchFailure < StandardError; end
|
34
|
+
class SearchFatalError < StandardError; end
|
35
|
+
class InvalidSearchKeys < StandardError; end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Xabier de Zuazo (<xabier@onddo.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Onddo Labs, SL. (www.onddo.com)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class EncryptedAttribute
|
21
|
+
class LocalNode
|
22
|
+
|
23
|
+
# currently not used
|
24
|
+
def name
|
25
|
+
Chef::Config[:node_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def key
|
29
|
+
OpenSSL::PKey::RSA.new(open(Chef::Config[:client_key]).read())
|
30
|
+
end
|
31
|
+
|
32
|
+
def public_key
|
33
|
+
key.public_key
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|