cheffish 1.6.0 → 2.0.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
- data/cheffish.gemspec +1 -0
- data/lib/chef/resource/chef_acl.rb +440 -20
- data/lib/chef/resource/chef_client.rb +50 -25
- data/lib/chef/resource/chef_container.rb +44 -11
- data/lib/chef/resource/chef_data_bag.rb +43 -10
- data/lib/chef/resource/chef_data_bag_item.rb +292 -82
- data/lib/chef/resource/chef_environment.rb +79 -27
- data/lib/chef/resource/chef_group.rb +77 -40
- data/lib/chef/resource/chef_mirror.rb +170 -21
- data/lib/chef/resource/chef_node.rb +77 -11
- data/lib/chef/resource/chef_organization.rb +153 -43
- data/lib/chef/resource/chef_resolved_cookbooks.rb +40 -9
- data/lib/chef/resource/chef_role.rb +81 -29
- data/lib/chef/resource/chef_user.rb +64 -33
- data/lib/chef/resource/private_key.rb +230 -17
- data/lib/chef/resource/public_key.rb +88 -9
- data/lib/cheffish/array_property.rb +29 -0
- data/lib/cheffish/base_resource.rb +254 -0
- data/lib/cheffish/chef_actor_base.rb +135 -0
- data/lib/cheffish/node_properties.rb +107 -0
- data/lib/cheffish/recipe_dsl.rb +0 -14
- data/lib/cheffish/version.rb +1 -1
- data/lib/cheffish.rb +4 -108
- data/spec/integration/chef_acl_spec.rb +0 -2
- data/spec/integration/chef_client_spec.rb +0 -1
- data/spec/integration/chef_container_spec.rb +0 -2
- data/spec/integration/chef_group_spec.rb +0 -2
- data/spec/integration/chef_mirror_spec.rb +0 -2
- data/spec/integration/chef_node_spec.rb +0 -2
- data/spec/integration/chef_organization_spec.rb +1 -3
- data/spec/integration/chef_role_spec.rb +0 -2
- data/spec/integration/chef_user_spec.rb +0 -2
- data/spec/integration/private_key_spec.rb +0 -4
- data/spec/integration/recipe_dsl_spec.rb +0 -2
- data/spec/support/spec_support.rb +0 -1
- data/spec/unit/get_private_key_spec.rb +13 -0
- metadata +22 -20
- data/lib/chef/provider/chef_acl.rb +0 -446
- data/lib/chef/provider/chef_client.rb +0 -53
- data/lib/chef/provider/chef_container.rb +0 -55
- data/lib/chef/provider/chef_data_bag.rb +0 -55
- data/lib/chef/provider/chef_data_bag_item.rb +0 -278
- data/lib/chef/provider/chef_environment.rb +0 -83
- data/lib/chef/provider/chef_group.rb +0 -83
- data/lib/chef/provider/chef_mirror.rb +0 -169
- data/lib/chef/provider/chef_node.rb +0 -87
- data/lib/chef/provider/chef_organization.rb +0 -155
- data/lib/chef/provider/chef_resolved_cookbooks.rb +0 -46
- data/lib/chef/provider/chef_role.rb +0 -84
- data/lib/chef/provider/chef_user.rb +0 -59
- data/lib/chef/provider/private_key.rb +0 -225
- data/lib/chef/provider/public_key.rb +0 -88
- data/lib/cheffish/actor_provider_base.rb +0 -131
- data/lib/cheffish/chef_provider_base.rb +0 -246
@@ -1,18 +1,15 @@
|
|
1
|
-
require '
|
1
|
+
require 'cheffish/base_resource'
|
2
|
+
require 'chef_zero'
|
2
3
|
|
3
4
|
class Chef
|
4
5
|
class Resource
|
5
|
-
class ChefResolvedCookbooks <
|
6
|
-
|
7
|
-
|
8
|
-
actions :resolve, :nothing
|
9
|
-
default_action :resolve
|
6
|
+
class ChefResolvedCookbooks < Cheffish::BaseResource
|
7
|
+
resource_name :chef_resolved_cookbooks
|
10
8
|
|
11
9
|
def initialize(*args)
|
12
10
|
super
|
13
11
|
require 'berkshelf'
|
14
12
|
berksfile Berkshelf::Berksfile.new('/tmp/Berksfile')
|
15
|
-
chef_server run_context.cheffish.current_chef_server
|
16
13
|
@cookbooks_from = []
|
17
14
|
end
|
18
15
|
|
@@ -28,8 +25,42 @@ class Chef
|
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
31
|
-
|
32
|
-
|
28
|
+
property :berksfile
|
29
|
+
|
30
|
+
action :resolve do
|
31
|
+
new_resource.cookbooks_from.each do |path|
|
32
|
+
::Dir.entries(path).each do |name|
|
33
|
+
if ::File.directory?(::File.join(path, name)) && name != '.' && name != '..'
|
34
|
+
new_resource.berksfile.cookbook name, :path => ::File.join(path, name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
new_resource.berksfile.install
|
40
|
+
|
41
|
+
# Ridley really really wants a key :/
|
42
|
+
if new_resource.chef_server[:options][:signing_key_filename]
|
43
|
+
new_resource.berksfile.upload(
|
44
|
+
:server_url => new_resource.chef_server[:chef_server_url],
|
45
|
+
:client_name => new_resource.chef_server[:options][:client_name],
|
46
|
+
:client_key => new_resource.chef_server[:options][:signing_key_filename])
|
47
|
+
else
|
48
|
+
file = Tempfile.new('privatekey')
|
49
|
+
begin
|
50
|
+
file.write(ChefZero::PRIVATE_KEY)
|
51
|
+
file.close
|
52
|
+
|
53
|
+
new_resource.berksfile.upload(
|
54
|
+
:server_url => new_resource.chef_server[:chef_server_url],
|
55
|
+
:client_name => new_resource.chef_server[:options][:client_name] || 'me',
|
56
|
+
:client_key => file.path)
|
57
|
+
|
58
|
+
ensure
|
59
|
+
file.close
|
60
|
+
file.unlink
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
33
64
|
end
|
34
65
|
end
|
35
66
|
end
|
@@ -1,38 +1,19 @@
|
|
1
1
|
require 'cheffish'
|
2
|
-
require '
|
2
|
+
require 'cheffish/base_resource'
|
3
3
|
require 'chef/run_list/run_list_item'
|
4
|
+
require 'chef/chef_fs/data_handler/role_data_handler'
|
4
5
|
|
5
6
|
class Chef
|
6
7
|
class Resource
|
7
|
-
class ChefRole <
|
8
|
-
|
8
|
+
class ChefRole < Cheffish::BaseResource
|
9
|
+
resource_name :chef_role
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
chef_server run_context.cheffish.current_chef_server
|
17
|
-
end
|
18
|
-
|
19
|
-
attribute :name, :kind_of => String, :regex => Cheffish::NAME_REGEX, :name_attribute => true
|
20
|
-
attribute :description, :kind_of => String
|
21
|
-
attribute :run_list, :kind_of => Array # We should let them specify it as a series of parameters too
|
22
|
-
attribute :env_run_lists, :kind_of => Hash
|
23
|
-
attribute :default_attributes, :kind_of => Hash
|
24
|
-
attribute :override_attributes, :kind_of => Hash
|
25
|
-
|
26
|
-
# Specifies that this is a complete specification for the environment (i.e. attributes you don't specify will be
|
27
|
-
# reset to their defaults)
|
28
|
-
attribute :complete, :kind_of => [TrueClass, FalseClass]
|
29
|
-
|
30
|
-
attribute :raw_json, :kind_of => Hash
|
31
|
-
attribute :chef_server, :kind_of => Hash
|
32
|
-
|
33
|
-
# `NOT_PASSED` is defined in chef-12.5.0, this guard will ensure we
|
34
|
-
# don't redefine it if it's already there
|
35
|
-
NOT_PASSED=Object.new unless defined?(NOT_PASSED)
|
11
|
+
property :name, Cheffish::NAME_REGEX, name_property: true
|
12
|
+
property :description, String
|
13
|
+
property :run_list, Array # We should let them specify it as a series of parameters too
|
14
|
+
property :env_run_lists, Hash
|
15
|
+
property :default_attributes, Hash
|
16
|
+
property :override_attributes, Hash
|
36
17
|
|
37
18
|
# default_attribute 'ip_address', '127.0.0.1'
|
38
19
|
# default_attribute [ 'pushy', 'port' ], '9000'
|
@@ -105,6 +86,77 @@ class Chef
|
|
105
86
|
@run_list_removers ||= []
|
106
87
|
@run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") }
|
107
88
|
end
|
89
|
+
|
90
|
+
action :create do
|
91
|
+
differences = json_differences(current_json, new_json)
|
92
|
+
|
93
|
+
if current_resource_exists?
|
94
|
+
if differences.size > 0
|
95
|
+
description = [ "update role #{new_resource.name} at #{rest.url}" ] + differences
|
96
|
+
converge_by description do
|
97
|
+
rest.put("roles/#{new_resource.name}", normalize_for_put(new_json))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else
|
101
|
+
description = [ "create role #{new_resource.name} at #{rest.url}" ] + differences
|
102
|
+
converge_by description do
|
103
|
+
rest.post("roles", normalize_for_post(new_json))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
action :delete do
|
109
|
+
if current_resource_exists?
|
110
|
+
converge_by "delete role #{new_resource.name} at #{rest.url}" do
|
111
|
+
rest.delete("roles/#{new_resource.name}")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
action_class.class_eval do
|
117
|
+
def load_current_resource
|
118
|
+
begin
|
119
|
+
@current_resource = json_to_resource(rest.get("roles/#{new_resource.name}"))
|
120
|
+
rescue Net::HTTPServerException => e
|
121
|
+
if e.response.code == "404"
|
122
|
+
@current_resource = not_found_resource
|
123
|
+
else
|
124
|
+
raise
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def augment_new_json(json)
|
130
|
+
# Apply modifiers
|
131
|
+
json['run_list'] = apply_run_list_modifiers(new_resource.run_list_modifiers, new_resource.run_list_removers, json['run_list'])
|
132
|
+
json['default_attributes'] = apply_modifiers(new_resource.default_attribute_modifiers, json['default_attributes'])
|
133
|
+
json['override_attributes'] = apply_modifiers(new_resource.override_attribute_modifiers, json['override_attributes'])
|
134
|
+
json
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Helpers
|
139
|
+
#
|
140
|
+
|
141
|
+
def resource_class
|
142
|
+
Chef::Resource::ChefRole
|
143
|
+
end
|
144
|
+
|
145
|
+
def data_handler
|
146
|
+
Chef::ChefFS::DataHandler::RoleDataHandler.new
|
147
|
+
end
|
148
|
+
|
149
|
+
def keys
|
150
|
+
{
|
151
|
+
'name' => :name,
|
152
|
+
'description' => :description,
|
153
|
+
'run_list' => :run_list,
|
154
|
+
'env_run_lists' => :env_run_lists,
|
155
|
+
'default_attributes' => :default_attributes,
|
156
|
+
'override_attributes' => :override_attributes
|
157
|
+
}
|
158
|
+
end
|
159
|
+
end
|
108
160
|
end
|
109
161
|
end
|
110
162
|
end
|
@@ -1,46 +1,31 @@
|
|
1
1
|
require 'cheffish'
|
2
|
-
require '
|
2
|
+
require 'cheffish/chef_actor_base'
|
3
3
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
|
-
class ChefUser <
|
7
|
-
|
8
|
-
|
9
|
-
actions :create, :delete, :nothing
|
10
|
-
default_action :create
|
11
|
-
|
12
|
-
# Grab environment from with_environment
|
13
|
-
def initialize(*args)
|
14
|
-
super
|
15
|
-
chef_server run_context.cheffish.current_chef_server
|
16
|
-
end
|
6
|
+
class ChefUser < Cheffish::ChefActorBase
|
7
|
+
resource_name :chef_user
|
17
8
|
|
18
9
|
# Client attributes
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
10
|
+
property :name, Cheffish::NAME_REGEX, name_property: true
|
11
|
+
property :display_name, String
|
12
|
+
property :admin, Boolean
|
13
|
+
property :email, String
|
14
|
+
property :external_authentication_uid
|
15
|
+
property :recovery_authentication_enabled, Boolean
|
16
|
+
property :password, String # Hmm. There is no way to idempotentize this.
|
17
|
+
#property :salt # TODO server doesn't support sending or receiving these, but it's the only way to backup / restore a user
|
18
|
+
#property :hashed_password
|
19
|
+
#property :hash_type
|
29
20
|
|
30
21
|
# Input key
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
property :source_key # String or OpenSSL::PKey::*
|
23
|
+
property :source_key_path, String
|
24
|
+
property :source_key_pass_phrase
|
34
25
|
|
35
26
|
# Output public key (if so desired)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# If this is set, client is not patchy
|
40
|
-
attribute :complete, :kind_of => [TrueClass, FalseClass]
|
41
|
-
|
42
|
-
attribute :raw_json, :kind_of => Hash
|
43
|
-
attribute :chef_server, :kind_of => Hash
|
27
|
+
property :output_key_path, String
|
28
|
+
property :output_key_format, [ :pem, :der, :openssh ], default: :openssh
|
44
29
|
|
45
30
|
# Proc that runs just before the resource executes. Called with (resource)
|
46
31
|
def before(&block)
|
@@ -51,6 +36,52 @@ class Chef
|
|
51
36
|
def after(&block)
|
52
37
|
block ? @after = block : @after
|
53
38
|
end
|
39
|
+
|
40
|
+
|
41
|
+
action :create do
|
42
|
+
create_actor
|
43
|
+
end
|
44
|
+
|
45
|
+
action :delete do
|
46
|
+
delete_actor
|
47
|
+
end
|
48
|
+
|
49
|
+
action_class.class_eval do
|
50
|
+
#
|
51
|
+
# Helpers
|
52
|
+
#
|
53
|
+
# Gives us new_json, current_json, not_found_json, etc.
|
54
|
+
|
55
|
+
def actor_type
|
56
|
+
'user'
|
57
|
+
end
|
58
|
+
|
59
|
+
def actor_path
|
60
|
+
"#{rest.root_url}/users"
|
61
|
+
end
|
62
|
+
|
63
|
+
def resource_class
|
64
|
+
Chef::Resource::ChefUser
|
65
|
+
end
|
66
|
+
|
67
|
+
def data_handler
|
68
|
+
Chef::ChefFS::DataHandler::UserDataHandler.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def keys
|
72
|
+
{
|
73
|
+
'name' => :name,
|
74
|
+
'username' => :name,
|
75
|
+
'display_name' => :display_name,
|
76
|
+
'admin' => :admin,
|
77
|
+
'email' => :email,
|
78
|
+
'password' => :password,
|
79
|
+
'external_authentication_uid' => :external_authentication_uid,
|
80
|
+
'recovery_authentication_enabled' => :recovery_authentication_enabled,
|
81
|
+
'public_key' => :source_key
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
54
85
|
end
|
55
86
|
end
|
56
87
|
end
|
@@ -1,38 +1,40 @@
|
|
1
1
|
require 'openssl/cipher'
|
2
|
-
require '
|
2
|
+
require 'cheffish/base_resource'
|
3
|
+
require 'openssl'
|
4
|
+
require 'cheffish/key_formatter'
|
3
5
|
|
4
6
|
class Chef
|
5
7
|
class Resource
|
6
|
-
class PrivateKey <
|
7
|
-
|
8
|
+
class PrivateKey < Cheffish::BaseResource
|
9
|
+
resource_name :private_key
|
8
10
|
|
9
|
-
|
11
|
+
allowed_actions :create, :delete, :regenerate, :nothing
|
10
12
|
default_action :create
|
11
13
|
|
12
14
|
# Path to private key. Set to :none to create the key in memory and not on disk.
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
property :path, [ String, :none ], name_property: true
|
16
|
+
property :format, [ :pem, :der ], default: :pem
|
17
|
+
property :type, [ :rsa, :dsa ], default: :rsa # TODO support :ec
|
16
18
|
# These specify an optional public_key you can spit out if you want.
|
17
|
-
|
18
|
-
|
19
|
+
property :public_key_path, String
|
20
|
+
property :public_key_format, [ :openssh, :pem, :der ], default: :openssh
|
19
21
|
# Specify this if you want to copy another private key but give it a different format / password
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
property :source_key
|
23
|
+
property :source_key_path, String
|
24
|
+
property :source_key_pass_phrase
|
23
25
|
|
24
26
|
# RSA and DSA
|
25
|
-
|
27
|
+
property :size, Integer, default: 2048
|
26
28
|
|
27
29
|
# RSA-only
|
28
|
-
|
30
|
+
property :exponent, Integer # For RSA
|
29
31
|
|
30
32
|
# PEM-only
|
31
|
-
|
32
|
-
|
33
|
+
property :pass_phrase, String
|
34
|
+
property :cipher, OpenSSL::Cipher.ciphers, default: 'DES-EDE3-CBC'
|
33
35
|
|
34
36
|
# Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.)
|
35
|
-
|
37
|
+
property :regenerate_if_different, Boolean
|
36
38
|
|
37
39
|
# Proc that runs after the resource completes. Called with (resource, private_key)
|
38
40
|
def after(&block)
|
@@ -43,6 +45,217 @@ class Chef
|
|
43
45
|
def load_prior_resource(*args)
|
44
46
|
Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
|
45
47
|
end
|
48
|
+
|
49
|
+
|
50
|
+
action :create do
|
51
|
+
create_key(false, :create)
|
52
|
+
end
|
53
|
+
|
54
|
+
action :regenerate do
|
55
|
+
create_key(true, :regenerate)
|
56
|
+
end
|
57
|
+
|
58
|
+
action :delete do
|
59
|
+
if current_resource.path
|
60
|
+
converge_by "delete private key #{new_path}" do
|
61
|
+
::File.unlink(new_path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
action_class.class_eval do
|
67
|
+
def create_key(regenerate, action)
|
68
|
+
if @should_create_directory
|
69
|
+
Cheffish.inline_resource(self, action) do
|
70
|
+
directory run_context.config[:private_key_write_path]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
final_private_key = nil
|
75
|
+
if new_source_key
|
76
|
+
#
|
77
|
+
# Create private key from source
|
78
|
+
#
|
79
|
+
desired_output = encode_private_key(new_source_key)
|
80
|
+
if current_resource.path == :none || desired_output != IO.read(new_path)
|
81
|
+
converge_by "reformat key at #{new_resource.source_key_path} to #{new_resource.format} private key #{new_path} (#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})" do
|
82
|
+
IO.write(new_path, desired_output)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
final_private_key = new_source_key
|
87
|
+
|
88
|
+
else
|
89
|
+
#
|
90
|
+
# Generate a new key
|
91
|
+
#
|
92
|
+
if current_resource.action == [ :delete ] || regenerate ||
|
93
|
+
(new_resource.regenerate_if_different &&
|
94
|
+
(!current_private_key ||
|
95
|
+
current_resource.size != new_resource.size ||
|
96
|
+
current_resource.type != new_resource.type))
|
97
|
+
|
98
|
+
case new_resource.type
|
99
|
+
when :rsa
|
100
|
+
if new_resource.exponent
|
101
|
+
final_private_key = OpenSSL::PKey::RSA.generate(new_resource.size, new_resource.exponent)
|
102
|
+
else
|
103
|
+
final_private_key = OpenSSL::PKey::RSA.generate(new_resource.size)
|
104
|
+
end
|
105
|
+
when :dsa
|
106
|
+
final_private_key = OpenSSL::PKey::DSA.generate(new_resource.size)
|
107
|
+
end
|
108
|
+
|
109
|
+
generated_key = true
|
110
|
+
elsif !current_private_key
|
111
|
+
raise "Could not read private key from #{current_resource.path}: missing pass phrase?"
|
112
|
+
else
|
113
|
+
final_private_key = current_private_key
|
114
|
+
generated_key = false
|
115
|
+
end
|
116
|
+
|
117
|
+
if generated_key
|
118
|
+
generated_description = " (#{new_resource.size} bits#{new_resource.pass_phrase ? ", #{new_resource.cipher} password" : ""})"
|
119
|
+
|
120
|
+
if new_path != :none
|
121
|
+
action = current_resource.path == :none ? 'create' : 'overwrite'
|
122
|
+
converge_by "#{action} #{new_resource.type} private key #{new_path}#{generated_description}" do
|
123
|
+
write_private_key(final_private_key)
|
124
|
+
end
|
125
|
+
else
|
126
|
+
converge_by "generate private key#{generated_description}" do
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
# Warn if existing key has different characteristics than expected
|
131
|
+
if current_resource.size != new_resource.size
|
132
|
+
Chef::Log.warn("Mismatched key size! #{current_resource.path} is #{current_resource.size} bytes, desired is #{new_resource.size} bytes. Use action :regenerate to force key regeneration.")
|
133
|
+
elsif current_resource.type != new_resource.type
|
134
|
+
Chef::Log.warn("Mismatched key type! #{current_resource.path} is #{current_resource.type}, desired is #{new_resource.type} bytes. Use action :regenerate to force key regeneration.")
|
135
|
+
end
|
136
|
+
|
137
|
+
if current_resource.format != new_resource.format
|
138
|
+
converge_by "change format of #{new_resource.type} private key #{new_path} from #{current_resource.format} to #{new_resource.format}" do
|
139
|
+
write_private_key(current_private_key)
|
140
|
+
end
|
141
|
+
elsif (@current_file_mode & 0077) != 0
|
142
|
+
new_mode = @current_file_mode & 07700
|
143
|
+
converge_by "change mode of private key #{new_path} to #{new_mode.to_s(8)}" do
|
144
|
+
::File.chmod(new_mode, new_path)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if new_resource.public_key_path
|
151
|
+
public_key_path = new_resource.public_key_path
|
152
|
+
public_key_format = new_resource.public_key_format
|
153
|
+
Cheffish.inline_resource(self, action) do
|
154
|
+
public_key public_key_path do
|
155
|
+
source_key final_private_key
|
156
|
+
format public_key_format
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
if new_resource.after
|
162
|
+
new_resource.after.call(new_resource, final_private_key)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def encode_private_key(key)
|
167
|
+
key_format = {}
|
168
|
+
key_format[:format] = new_resource.format if new_resource.format
|
169
|
+
key_format[:pass_phrase] = new_resource.pass_phrase if new_resource.pass_phrase
|
170
|
+
key_format[:cipher] = new_resource.cipher if new_resource.cipher
|
171
|
+
Cheffish::KeyFormatter.encode(key, key_format)
|
172
|
+
end
|
173
|
+
|
174
|
+
def write_private_key(key)
|
175
|
+
::File.open(new_path, 'w') do |file|
|
176
|
+
file.chmod(0600)
|
177
|
+
file.write(encode_private_key(key))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def new_source_key
|
182
|
+
@new_source_key ||= begin
|
183
|
+
if new_resource.source_key.is_a?(String)
|
184
|
+
source_key, source_key_format = Cheffish::KeyFormatter.decode(new_resource.source_key, new_resource.source_key_pass_phrase)
|
185
|
+
source_key
|
186
|
+
elsif new_resource.source_key
|
187
|
+
new_resource.source_key
|
188
|
+
elsif new_resource.source_key_path
|
189
|
+
source_key, source_key_format = Cheffish::KeyFormatter.decode(IO.read(new_resource.source_key_path), new_resource.source_key_pass_phrase, new_resource.source_key_path)
|
190
|
+
source_key
|
191
|
+
else
|
192
|
+
nil
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
attr_reader :current_private_key
|
198
|
+
|
199
|
+
def new_path
|
200
|
+
new_key_with_path[1]
|
201
|
+
end
|
202
|
+
|
203
|
+
def new_key_with_path
|
204
|
+
path = new_resource.path
|
205
|
+
if path.is_a?(Symbol)
|
206
|
+
return [ nil, path ]
|
207
|
+
elsif Pathname.new(path).relative?
|
208
|
+
private_key, private_key_path = Cheffish.get_private_key_with_path(path, run_context.config)
|
209
|
+
if private_key
|
210
|
+
return [ private_key, (private_key_path || :none) ]
|
211
|
+
elsif run_context.config[:private_key_write_path]
|
212
|
+
@should_create_directory = true
|
213
|
+
path = ::File.join(run_context.config[:private_key_write_path], path)
|
214
|
+
return [ nil, path ]
|
215
|
+
else
|
216
|
+
raise "Could not find key #{path} and Chef::Config.private_key_write_path is not set."
|
217
|
+
end
|
218
|
+
elsif ::File.exist?(path)
|
219
|
+
return [ IO.read(path), path ]
|
220
|
+
else
|
221
|
+
return [ nil, path ]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def load_current_resource
|
226
|
+
resource = Chef::Resource::PrivateKey.new(new_resource.name, run_context)
|
227
|
+
|
228
|
+
new_key, new_path = new_key_with_path
|
229
|
+
if new_path != :none && ::File.exist?(new_path)
|
230
|
+
resource.path new_path
|
231
|
+
@current_file_mode = ::File.stat(new_path).mode
|
232
|
+
else
|
233
|
+
resource.path :none
|
234
|
+
end
|
235
|
+
|
236
|
+
if new_key
|
237
|
+
begin
|
238
|
+
key, key_format = Cheffish::KeyFormatter.decode(new_key, new_resource.pass_phrase, new_path)
|
239
|
+
if key
|
240
|
+
@current_private_key = key
|
241
|
+
resource.format key_format[:format]
|
242
|
+
resource.type key_format[:type]
|
243
|
+
resource.size key_format[:size]
|
244
|
+
resource.exponent key_format[:exponent]
|
245
|
+
resource.pass_phrase key_format[:pass_phrase]
|
246
|
+
resource.cipher key_format[:cipher]
|
247
|
+
end
|
248
|
+
rescue
|
249
|
+
# If there's an error reading, we assume format and type are wrong and don't futz with them
|
250
|
+
Chef::Log.warn("Error reading #{new_path}: #{$!}")
|
251
|
+
end
|
252
|
+
else
|
253
|
+
resource.action :delete
|
254
|
+
end
|
255
|
+
|
256
|
+
@current_resource = resource
|
257
|
+
end
|
258
|
+
end
|
46
259
|
end
|
47
260
|
end
|
48
261
|
end
|