cheffish 14.0.13 → 16.0.8
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/Gemfile +3 -9
- data/Rakefile +1 -1
- data/cheffish.gemspec +3 -3
- data/lib/chef/resource/chef_acl.rb +17 -14
- data/lib/chef/resource/chef_client.rb +3 -3
- data/lib/chef/resource/chef_container.rb +4 -4
- data/lib/chef/resource/chef_data_bag.rb +3 -3
- data/lib/chef/resource/chef_data_bag_item.rb +13 -12
- data/lib/chef/resource/chef_environment.rb +2 -2
- data/lib/chef/resource/chef_group.rb +2 -2
- data/lib/chef/resource/chef_mirror.rb +6 -5
- data/lib/chef/resource/chef_node.rb +2 -2
- data/lib/chef/resource/chef_organization.rb +3 -3
- data/lib/chef/resource/chef_resolved_cookbooks.rb +5 -3
- data/lib/chef/resource/chef_role.rb +6 -2
- data/lib/chef/resource/chef_user.rb +2 -2
- data/lib/chef/resource/private_key.rb +11 -11
- data/lib/chef/resource/public_key.rb +5 -4
- data/lib/cheffish.rb +1 -0
- data/lib/cheffish/base_resource.rb +13 -11
- data/lib/cheffish/basic_chef_client.rb +4 -5
- data/lib/cheffish/chef_actor_base.rb +3 -2
- data/lib/cheffish/chef_run.rb +5 -6
- data/lib/cheffish/chef_run_listener.rb +1 -3
- data/lib/cheffish/key_formatter.rb +5 -13
- data/lib/cheffish/merged_config.rb +2 -2
- data/lib/cheffish/node_properties.rb +7 -3
- data/lib/cheffish/recipe_dsl.rb +2 -2
- data/lib/cheffish/rspec/chef_run_support.rb +2 -2
- data/lib/cheffish/rspec/matchers/have_updated.rb +5 -5
- data/lib/cheffish/rspec/recipe_run_wrapper.rb +2 -2
- data/lib/cheffish/rspec/repository_support.rb +1 -0
- data/lib/cheffish/version.rb +1 -1
- data/spec/functional/fingerprint_spec.rb +8 -6
- data/spec/integration/chef_acl_spec.rb +28 -20
- data/spec/integration/chef_group_spec.rb +2 -2
- data/spec/integration/chef_node_spec.rb +2 -2
- data/spec/integration/chef_role_spec.rb +2 -2
- metadata +7 -7
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/data_handler_base"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefOrganization < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_organization
|
10
10
|
|
11
11
|
property :organization_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :full_name, String
|
@@ -68,7 +68,7 @@ class Chef
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
new_resource.members.each do |user|
|
71
|
-
|
71
|
+
unless existing_members.include?(user)
|
72
72
|
converge_by "Add #{user} to organization #{new_resource.organization_name}" do
|
73
73
|
rest.post("#{rest.root_url}/organizations/#{new_resource.organization_name}/users/", { "username" => user })
|
74
74
|
end
|
@@ -130,7 +130,7 @@ class Chef
|
|
130
130
|
action_class.class_eval do
|
131
131
|
def load_current_resource
|
132
132
|
@current_resource = json_to_resource(rest.get("#{rest.root_url}/organizations/#{new_resource.organization_name}"))
|
133
|
-
rescue Net::
|
133
|
+
rescue Net::HTTPClientException => e
|
134
134
|
if e.response.code == "404"
|
135
135
|
@current_resource = not_found_resource
|
136
136
|
else
|
@@ -4,7 +4,7 @@ require "chef_zero"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefResolvedCookbooks < Cheffish::BaseResource
|
7
|
-
|
7
|
+
provides :chef_resolved_cookbooks
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
super
|
@@ -43,7 +43,8 @@ class Chef
|
|
43
43
|
new_resource.berksfile.upload(
|
44
44
|
server_url: new_resource.chef_server[:chef_server_url],
|
45
45
|
client_name: new_resource.chef_server[:options][:client_name],
|
46
|
-
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
46
|
+
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
47
|
+
)
|
47
48
|
else
|
48
49
|
file = Tempfile.new("privatekey")
|
49
50
|
begin
|
@@ -53,7 +54,8 @@ class Chef
|
|
53
54
|
new_resource.berksfile.upload(
|
54
55
|
server_url: new_resource.chef_server[:chef_server_url],
|
55
56
|
client_name: new_resource.chef_server[:options][:client_name] || "me",
|
56
|
-
client_key: file.path
|
57
|
+
client_key: file.path
|
58
|
+
)
|
57
59
|
|
58
60
|
ensure
|
59
61
|
file.close
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/role_data_handler"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefRole < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_role
|
10
10
|
|
11
11
|
property :role_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :description, String
|
@@ -62,6 +62,7 @@ class Chef
|
|
62
62
|
if recipes.size == 0
|
63
63
|
raise ArgumentError, "At least one recipe must be specified"
|
64
64
|
end
|
65
|
+
|
65
66
|
@run_list_modifiers ||= []
|
66
67
|
@run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
67
68
|
end
|
@@ -70,6 +71,7 @@ class Chef
|
|
70
71
|
if roles.size == 0
|
71
72
|
raise ArgumentError, "At least one role must be specified"
|
72
73
|
end
|
74
|
+
|
73
75
|
@run_list_modifiers ||= []
|
74
76
|
@run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
75
77
|
end
|
@@ -78,6 +80,7 @@ class Chef
|
|
78
80
|
if recipes.size == 0
|
79
81
|
raise ArgumentError, "At least one recipe must be specified"
|
80
82
|
end
|
83
|
+
|
81
84
|
@run_list_removers ||= []
|
82
85
|
@run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
83
86
|
end
|
@@ -86,6 +89,7 @@ class Chef
|
|
86
89
|
if roles.size == 0
|
87
90
|
raise ArgumentError, "At least one role must be specified"
|
88
91
|
end
|
92
|
+
|
89
93
|
@run_list_removers ||= []
|
90
94
|
@run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") }
|
91
95
|
end
|
@@ -119,7 +123,7 @@ class Chef
|
|
119
123
|
action_class.class_eval do
|
120
124
|
def load_current_resource
|
121
125
|
@current_resource = json_to_resource(rest.get("roles/#{new_resource.role_name}"))
|
122
|
-
rescue Net::
|
126
|
+
rescue Net::HTTPClientException => e
|
123
127
|
if e.response.code == "404"
|
124
128
|
@current_resource = not_found_resource
|
125
129
|
else
|
@@ -4,7 +4,7 @@ require_relative "../../cheffish/chef_actor_base"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefUser < Cheffish::ChefActorBase
|
7
|
-
|
7
|
+
provides :chef_user
|
8
8
|
|
9
9
|
# Client attributes
|
10
10
|
property :user_name, Cheffish::NAME_REGEX, name_property: true
|
@@ -25,7 +25,7 @@ class Chef
|
|
25
25
|
|
26
26
|
# Output public key (if so desired)
|
27
27
|
property :output_key_path, String
|
28
|
-
property :output_key_format,
|
28
|
+
property :output_key_format, %i{pem der openssh}, default: :openssh
|
29
29
|
|
30
30
|
# Proc that runs just before the resource executes. Called with (resource)
|
31
31
|
def before(&block)
|
@@ -1,23 +1,23 @@
|
|
1
1
|
require "openssl/cipher"
|
2
2
|
require_relative "../../cheffish/base_resource"
|
3
|
-
require "openssl"
|
3
|
+
require "openssl" unless defined?(OpenSSL)
|
4
4
|
require_relative "../../cheffish/key_formatter"
|
5
5
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PrivateKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :private_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :regenerate, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
# Path to private key. Set to :none to create the key in memory and not on disk.
|
15
15
|
property :path, [ String, :none ], name_property: true
|
16
|
-
property :format,
|
17
|
-
property :type,
|
16
|
+
property :format, %i{pem der}, default: :pem
|
17
|
+
property :type, %i{rsa dsa}, default: :rsa # TODO support :ec
|
18
18
|
# These specify an optional public_key you can spit out if you want.
|
19
19
|
property :public_key_path, String
|
20
|
-
property :public_key_format,
|
20
|
+
property :public_key_format, %i{openssh pem der}, default: :openssh
|
21
21
|
# Specify this if you want to copy another private key but give it a different format / password
|
22
22
|
property :source_key
|
23
23
|
property :source_key_path, String
|
@@ -31,7 +31,7 @@ class Chef
|
|
31
31
|
|
32
32
|
# PEM-only
|
33
33
|
property :pass_phrase, String
|
34
|
-
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map
|
34
|
+
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map(&:downcase), default: "des-ede3-cbc", coerce: proc { |x| x.downcase }
|
35
35
|
|
36
36
|
# Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.)
|
37
37
|
property :regenerate_if_different, [TrueClass, FalseClass]
|
@@ -202,22 +202,22 @@ class Chef
|
|
202
202
|
def new_key_with_path
|
203
203
|
path = new_resource.path
|
204
204
|
if path.is_a?(Symbol)
|
205
|
-
|
205
|
+
[ nil, path ]
|
206
206
|
elsif Pathname.new(path).relative?
|
207
207
|
private_key, private_key_path = Cheffish.get_private_key_with_path(path, run_context.config)
|
208
208
|
if private_key
|
209
|
-
|
209
|
+
[ private_key, (private_key_path || :none) ]
|
210
210
|
elsif run_context.config[:private_key_write_path]
|
211
211
|
@should_create_directory = true
|
212
212
|
path = ::File.join(run_context.config[:private_key_write_path], path)
|
213
|
-
|
213
|
+
[ nil, path ]
|
214
214
|
else
|
215
215
|
raise "Could not find key #{path} and Chef::Config.private_key_write_path is not set."
|
216
216
|
end
|
217
217
|
elsif ::File.exist?(path)
|
218
|
-
|
218
|
+
[ IO.read(path), path ]
|
219
219
|
else
|
220
|
-
|
220
|
+
[ nil, path ]
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
@@ -1,18 +1,18 @@
|
|
1
1
|
require "openssl/cipher"
|
2
2
|
require_relative "../../cheffish/base_resource"
|
3
|
-
require "openssl"
|
3
|
+
require "openssl" unless defined?(OpenSSL)
|
4
4
|
require_relative "../../cheffish/key_formatter"
|
5
5
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PublicKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :public_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
property :path, String, name_property: true
|
15
|
-
property :format,
|
15
|
+
property :format, %i{pem der openssh}, default: :openssh
|
16
16
|
|
17
17
|
property :source_key
|
18
18
|
property :source_key_path, String
|
@@ -24,9 +24,10 @@ class Chef
|
|
24
24
|
end
|
25
25
|
|
26
26
|
action :create do
|
27
|
-
|
27
|
+
unless new_source_key
|
28
28
|
raise "No source key specified"
|
29
29
|
end
|
30
|
+
|
30
31
|
desired_output = encode_public_key(new_source_key)
|
31
32
|
if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_resource.path)
|
32
33
|
converge_by "write #{new_resource.format} public key #{new_resource.path} from #{new_source_key_publicity} key #{new_resource.source_key_path}" do
|
data/lib/cheffish.rb
CHANGED
@@ -98,6 +98,7 @@ module Cheffish
|
|
98
98
|
elsif config[:private_key_paths]
|
99
99
|
config[:private_key_paths].each do |private_key_path|
|
100
100
|
next unless File.exist?(private_key_path)
|
101
|
+
|
101
102
|
Dir.entries(private_key_path).sort.each do |key|
|
102
103
|
ext = File.extname(key)
|
103
104
|
if key == name || ext == "" || ext == ".pem"
|
@@ -91,7 +91,7 @@ module Cheffish
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def json_differences_internal(old_json, new_json, print_values, name, result)
|
94
|
-
if old_json.
|
94
|
+
if old_json.is_a?(Hash) && new_json.is_a?(Hash)
|
95
95
|
removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
|
96
96
|
new_json.each_pair do |new_key, new_value|
|
97
97
|
if old_json.key?(new_key)
|
@@ -101,18 +101,18 @@ module Cheffish
|
|
101
101
|
end
|
102
102
|
else
|
103
103
|
if print_values
|
104
|
-
result << " add #{name ==
|
104
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
|
105
105
|
else
|
106
|
-
result << " add #{name ==
|
106
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"}"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
110
|
removed_keys.keys.each do |removed_key|
|
111
|
-
result << " remove #{name ==
|
111
|
+
result << " remove #{name == "" ? removed_key : "#{name}.#{removed_key}"}"
|
112
112
|
end
|
113
113
|
else
|
114
|
-
old_json = old_json.to_s if old_json.
|
115
|
-
new_json = new_json.to_s if new_json.
|
114
|
+
old_json = old_json.to_s if old_json.is_a?(Symbol)
|
115
|
+
new_json = new_json.to_s if new_json.is_a?(Symbol)
|
116
116
|
if old_json != new_json
|
117
117
|
if print_values
|
118
118
|
result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
|
@@ -134,8 +134,8 @@ module Cheffish
|
|
134
134
|
end
|
135
135
|
|
136
136
|
modifiers.each do |path, value|
|
137
|
-
path = [path]
|
138
|
-
path = path.map
|
137
|
+
path = [path] unless path.is_a?(Array)
|
138
|
+
path = path.map(&:to_s)
|
139
139
|
parent = 0.upto(path.size - 2).inject(json) do |hash, index|
|
140
140
|
if hash.nil?
|
141
141
|
nil
|
@@ -148,6 +148,7 @@ module Cheffish
|
|
148
148
|
if !parent.nil? && !parent.is_a?(Hash)
|
149
149
|
raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash"
|
150
150
|
end
|
151
|
+
|
151
152
|
existing_value = parent ? parent[path[-1]] : nil
|
152
153
|
|
153
154
|
if value.is_a?(Proc)
|
@@ -158,7 +159,7 @@ module Cheffish
|
|
158
159
|
else
|
159
160
|
# Create parent if necessary, overwriting values
|
160
161
|
parent = path[0..-2].inject(json) do |hash, path_part|
|
161
|
-
hash[path_part] = {}
|
162
|
+
hash[path_part] = {} unless hash[path_part]
|
162
163
|
hash[path_part]
|
163
164
|
end
|
164
165
|
if path.size > 0
|
@@ -173,6 +174,7 @@ module Cheffish
|
|
173
174
|
|
174
175
|
def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
|
175
176
|
return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
|
177
|
+
|
176
178
|
delete_from_run_list ||= []
|
177
179
|
add_to_run_list ||= []
|
178
180
|
|
@@ -191,7 +193,7 @@ module Cheffish
|
|
191
193
|
# because found_desired will be less than add_to_run_list_index. The result will
|
192
194
|
# be X, A, B, Y, Z.
|
193
195
|
if found_desired >= add_to_run_list_index
|
194
|
-
result += add_to_run_list[add_to_run_list_index..found_desired].map
|
196
|
+
result += add_to_run_list[add_to_run_list_index..found_desired].map(&:to_s)
|
195
197
|
add_to_run_list_index = found_desired + 1
|
196
198
|
end
|
197
199
|
else
|
@@ -204,7 +206,7 @@ module Cheffish
|
|
204
206
|
end
|
205
207
|
|
206
208
|
# Copy any remaining desired items at the end
|
207
|
-
result += add_to_run_list[add_to_run_list_index..-1].map
|
209
|
+
result += add_to_run_list[add_to_run_list_index..-1].map(&:to_s)
|
208
210
|
result
|
209
211
|
end
|
210
212
|
|
@@ -5,7 +5,7 @@ require "chef/event_dispatch/dispatcher"
|
|
5
5
|
require "chef/node"
|
6
6
|
require "chef/run_context"
|
7
7
|
require "chef/runner"
|
8
|
-
require "forwardable"
|
8
|
+
require "forwardable" unless defined?(Forwardable)
|
9
9
|
require "chef/providers"
|
10
10
|
require "chef/resources"
|
11
11
|
|
@@ -14,7 +14,7 @@ module Cheffish
|
|
14
14
|
include Chef::DSL::Recipe
|
15
15
|
|
16
16
|
def initialize(node = nil, events = nil, **chef_config)
|
17
|
-
|
17
|
+
unless node
|
18
18
|
node = Chef::Node.new
|
19
19
|
node.name "basic_chef_client"
|
20
20
|
node.automatic[:platform] = "basic_chef_client"
|
@@ -31,7 +31,7 @@ module Cheffish
|
|
31
31
|
case events
|
32
32
|
when Array
|
33
33
|
events.each { |e| dispatcher.register(e) } if events
|
34
|
-
when !nil
|
34
|
+
when !nil # rubocop: disable Lint/LiteralAsCondition
|
35
35
|
dispatcher.register(events)
|
36
36
|
end
|
37
37
|
@run_context = Chef::RunContext.new(node, {}, dispatcher)
|
@@ -80,12 +80,11 @@ module Cheffish
|
|
80
80
|
# add_resource() method.
|
81
81
|
def self.build_resource(type, name, created_at = nil, &resource_attrs_block)
|
82
82
|
created_at ||= caller[0]
|
83
|
-
|
83
|
+
BasicChefClient.new.tap do |client|
|
84
84
|
client.with_chef_config do
|
85
85
|
client.build_resource(type, name, created_at, &resource_attrs_block)
|
86
86
|
end
|
87
87
|
end
|
88
|
-
result
|
89
88
|
end
|
90
89
|
|
91
90
|
def self.inline_resource(provider, provider_action, *resources, &block)
|
@@ -24,9 +24,10 @@ module Cheffish
|
|
24
24
|
end
|
25
25
|
else
|
26
26
|
# Create the actor if it's missing
|
27
|
-
|
27
|
+
unless new_public_key
|
28
28
|
raise "You must specify a public key to create a #{actor_type}! Use the private_key resource to create a key, and pass it in with source_key_path."
|
29
29
|
end
|
30
|
+
|
30
31
|
description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
31
32
|
converge_by description do
|
32
33
|
result = rest.post((actor_path).to_s, normalize_for_post(new_json))
|
@@ -118,7 +119,7 @@ module Cheffish
|
|
118
119
|
begin
|
119
120
|
json = rest.get("#{actor_path}/#{new_resource.name}")
|
120
121
|
@current_resource = json_to_resource(json)
|
121
|
-
rescue Net::
|
122
|
+
rescue Net::HTTPClientException => e
|
122
123
|
if e.response.code == "404"
|
123
124
|
@current_resource = not_found_resource
|
124
125
|
else
|
data/lib/cheffish/chef_run.rb
CHANGED
@@ -34,15 +34,14 @@ module Cheffish
|
|
34
34
|
def client
|
35
35
|
@client ||= begin
|
36
36
|
chef_config = self.chef_config.dup
|
37
|
-
chef_config[:log_level] ||= :debug
|
38
|
-
chef_config[:verbose_logging] = false
|
37
|
+
chef_config[:log_level] ||= :debug unless chef_config.key?(:log_level)
|
38
|
+
chef_config[:verbose_logging] = false unless chef_config.key?(:verbose_logging)
|
39
39
|
chef_config[:stdout] = StringIOTee.new(chef_config[:stdout])
|
40
40
|
chef_config[:stderr] = StringIOTee.new(chef_config[:stderr])
|
41
41
|
chef_config[:log_location] = StringIOTee.new(chef_config[:log_location])
|
42
42
|
@client = ::Cheffish::BasicChefClient.new(nil,
|
43
43
|
[ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ],
|
44
|
-
chef_config
|
45
|
-
)
|
44
|
+
chef_config)
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
@@ -125,14 +124,14 @@ module Cheffish
|
|
125
124
|
message << "--- Chef Client Output ---\n"
|
126
125
|
message << "--- ---\n"
|
127
126
|
message << stdout
|
128
|
-
message << "\n"
|
127
|
+
message << "\n" unless stdout.end_with?("\n")
|
129
128
|
end
|
130
129
|
if stderr && !stderr.empty?
|
131
130
|
message << "--- ---\n"
|
132
131
|
message << "--- Chef Client Error Output ---\n"
|
133
132
|
message << "--- ---\n"
|
134
133
|
message << stderr
|
135
|
-
message << "\n"
|
134
|
+
message << "\n" unless stderr.end_with?("\n")
|
136
135
|
end
|
137
136
|
if logs && !logs.empty?
|
138
137
|
message << "--- ---\n"
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require "openssl"
|
2
|
-
require "net/ssh"
|
3
|
-
require "etc"
|
4
|
-
require "socket"
|
1
|
+
require "openssl" unless defined?(OpenSSL)
|
2
|
+
require "net/ssh" unless defined?(Net::SSH)
|
3
|
+
require "etc" unless defined?(Etc)
|
4
|
+
require "socket" unless defined?(Socket)
|
5
5
|
require "digest/md5"
|
6
6
|
require "base64"
|
7
7
|
|
@@ -55,15 +55,7 @@ module Cheffish
|
|
55
55
|
hexes = Digest::MD5.hexdigest(data)
|
56
56
|
hexes.scan(/../).join(":")
|
57
57
|
when :pkcs8sha1fingerprint
|
58
|
-
|
59
|
-
raise "PKCS8 SHA1 not supported in Ruby #{RUBY_VERSION}"
|
60
|
-
end
|
61
|
-
require "openssl_pkcs8"
|
62
|
-
pkcs8_pem = key.to_pem_pkcs8
|
63
|
-
pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ }
|
64
|
-
pkcs8_data = Base64.decode64(pkcs8_base64.join)
|
65
|
-
hexes = Digest::SHA1.hexdigest(pkcs8_data)
|
66
|
-
hexes.scan(/../).join(":")
|
58
|
+
raise "PKCS8 SHA1 not supported by Ruby 2.0 and later"
|
67
59
|
else
|
68
60
|
raise "Unrecognized key format #{format}"
|
69
61
|
end
|