cheffish 1.3.1 → 1.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +120 -117
  4. data/Rakefile +23 -23
  5. data/lib/chef/provider/chef_acl.rb +439 -434
  6. data/lib/chef/provider/chef_client.rb +53 -48
  7. data/lib/chef/provider/chef_container.rb +55 -50
  8. data/lib/chef/provider/chef_data_bag.rb +55 -50
  9. data/lib/chef/provider/chef_data_bag_item.rb +278 -273
  10. data/lib/chef/provider/chef_environment.rb +83 -78
  11. data/lib/chef/provider/chef_group.rb +83 -78
  12. data/lib/chef/provider/chef_mirror.rb +169 -164
  13. data/lib/chef/provider/chef_node.rb +87 -82
  14. data/lib/chef/provider/chef_organization.rb +155 -150
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -41
  16. data/lib/chef/provider/chef_role.rb +84 -79
  17. data/lib/chef/provider/chef_user.rb +59 -54
  18. data/lib/chef/provider/private_key.rb +225 -220
  19. data/lib/chef/provider/public_key.rb +88 -82
  20. data/lib/chef/resource/chef_acl.rb +69 -65
  21. data/lib/chef/resource/chef_client.rb +48 -44
  22. data/lib/chef/resource/chef_container.rb +22 -18
  23. data/lib/chef/resource/chef_data_bag.rb +22 -18
  24. data/lib/chef/resource/chef_data_bag_item.rb +121 -114
  25. data/lib/chef/resource/chef_environment.rb +77 -71
  26. data/lib/chef/resource/chef_group.rb +53 -49
  27. data/lib/chef/resource/chef_mirror.rb +52 -48
  28. data/lib/chef/resource/chef_node.rb +22 -18
  29. data/lib/chef/resource/chef_organization.rb +69 -64
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -31
  31. data/lib/chef/resource/chef_role.rb +110 -104
  32. data/lib/chef/resource/chef_user.rb +56 -52
  33. data/lib/chef/resource/private_key.rb +48 -44
  34. data/lib/chef/resource/public_key.rb +25 -21
  35. data/lib/cheffish.rb +235 -233
  36. data/lib/cheffish/actor_provider_base.rb +131 -131
  37. data/lib/cheffish/basic_chef_client.rb +184 -184
  38. data/lib/cheffish/chef_provider_base.rb +246 -246
  39. data/lib/cheffish/chef_run.rb +162 -155
  40. data/lib/cheffish/chef_run_data.rb +19 -19
  41. data/lib/cheffish/chef_run_listener.rb +30 -30
  42. data/lib/cheffish/key_formatter.rb +113 -113
  43. data/lib/cheffish/merged_config.rb +94 -94
  44. data/lib/cheffish/recipe_dsl.rb +157 -157
  45. data/lib/cheffish/rspec.rb +8 -8
  46. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  47. data/lib/cheffish/rspec/matchers.rb +4 -4
  48. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  49. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  50. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  51. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  52. data/lib/cheffish/rspec/recipe_run_wrapper.rb +59 -47
  53. data/lib/cheffish/rspec/repository_support.rb +108 -108
  54. data/lib/cheffish/server_api.rb +52 -52
  55. data/lib/cheffish/version.rb +3 -3
  56. data/lib/cheffish/with_pattern.rb +21 -21
  57. data/spec/functional/fingerprint_spec.rb +64 -64
  58. data/spec/functional/merged_config_spec.rb +19 -19
  59. data/spec/functional/server_api_spec.rb +13 -13
  60. data/spec/integration/chef_acl_spec.rb +879 -879
  61. data/spec/integration/chef_client_spec.rb +105 -105
  62. data/spec/integration/chef_container_spec.rb +33 -33
  63. data/spec/integration/chef_group_spec.rb +309 -309
  64. data/spec/integration/chef_mirror_spec.rb +491 -491
  65. data/spec/integration/chef_node_spec.rb +786 -786
  66. data/spec/integration/chef_organization_spec.rb +226 -226
  67. data/spec/integration/chef_role_spec.rb +78 -0
  68. data/spec/integration/chef_user_spec.rb +85 -85
  69. data/spec/integration/private_key_spec.rb +399 -399
  70. data/spec/integration/recipe_dsl_spec.rb +28 -28
  71. data/spec/integration/rspec/converge_spec.rb +183 -183
  72. data/spec/support/key_support.rb +29 -29
  73. data/spec/support/spec_support.rb +15 -15
  74. data/spec/unit/get_private_key_spec.rb +131 -131
  75. data/spec/unit/recipe_run_wrapper_spec.rb +37 -0
  76. metadata +8 -5
@@ -1,155 +1,162 @@
1
- require 'cheffish/basic_chef_client'
2
-
3
- module Cheffish
4
- class ChefRun
5
- #
6
- # @param chef_config A hash with symbol keys that looks suspiciously similar to `Chef::Config`.
7
- # Some possible options:
8
- # - stdout: <IO object> - where to stream stdout to
9
- # - stderr: <IO object> - where to stream stderr to
10
- # - log_level: :debug|:info|:warn|:error|:fatal
11
- # - log_location: <path|IO object> - where to stream logs to
12
- # - verbose_logging: true|false - true if you want verbose logging in :debug
13
- #
14
- def initialize(chef_config={})
15
- @chef_config = chef_config || {}
16
- end
17
-
18
- attr_reader :chef_config
19
-
20
- class StringIOTee < StringIO
21
- def initialize(*streams)
22
- super()
23
- @streams = streams.flatten.select { |s| !s.nil? }
24
- end
25
-
26
- attr_reader :streams
27
-
28
- def write(*args, &block)
29
- super
30
- streams.each { |s| s.write(*args, &block) }
31
- end
32
- end
33
-
34
- def client
35
- @client ||= begin
36
- chef_config = self.chef_config.dup
37
- chef_config[:log_level] ||= :debug if !chef_config.has_key?(:log_level)
38
- chef_config[:verbose_logging] = false if !chef_config.has_key?(:verbose_logging)
39
- chef_config[:stdout] = StringIOTee.new(chef_config[:stdout])
40
- chef_config[:stderr] = StringIOTee.new(chef_config[:stderr])
41
- chef_config[:log_location] = StringIOTee.new(chef_config[:log_location])
42
- @client = ::Cheffish::BasicChefClient.new(nil,
43
- [ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ],
44
- chef_config
45
- )
46
- end
47
- end
48
-
49
- def event_sink
50
- @event_sink ||= EventSink.new
51
- end
52
-
53
- #
54
- # output
55
- #
56
- def stdout
57
- @client ? client.chef_config[:stdout].string : nil
58
- end
59
- def stderr
60
- @client ? client.chef_config[:stderr].string : nil
61
- end
62
- def logs
63
- @client ? client.chef_config[:log_location].string : nil
64
- end
65
- def logged_warnings
66
- logs.lines.select { |l| l =~ /^\[[^\]]*\] WARN:/ }.join("\n")
67
- end
68
- def logged_errors
69
- logs.lines.select { |l| l =~ /^\[[^\]]*\] ERROR:/ }.join("\n")
70
- end
71
- def logged_info
72
- logs.lines.select { |l| l =~ /^\[[^\]]*\] INFO:/ }.join("\n")
73
- end
74
-
75
- def resources
76
- client.resource_collection
77
- end
78
-
79
- def compile_recipe(&recipe)
80
- client.load_block(&recipe)
81
- end
82
-
83
- def converge
84
- begin
85
- client.converge
86
- @converged = true
87
- rescue RuntimeError => e
88
- @raised_exception = e
89
- raise
90
- end
91
- end
92
-
93
- def reset
94
- @client = nil
95
- @converged = nil
96
- @stdout = nil
97
- @stderr = nil
98
- @logs = nil
99
- @raised_exception = nil
100
- end
101
-
102
- def converged?
103
- !!@converged
104
- end
105
-
106
- def converge_failed?
107
- @raised_exception.nil? ? false : true
108
- end
109
-
110
- def updated?
111
- client.updated?
112
- end
113
-
114
- def up_to_date?
115
- !client.updated?
116
- end
117
-
118
- def output_for_failure_message
119
- message = ""
120
- if stdout && !stdout.empty?
121
- message << "--- ---\n"
122
- message << "--- Chef Client Output ---\n"
123
- message << "--- ---\n"
124
- message << stdout
125
- message << "\n" if !stdout.end_with?("\n")
126
- end
127
- if stderr && !stderr.empty?
128
- message << "--- ---\n"
129
- message << "--- Chef Client Error Output ---\n"
130
- message << "--- ---\n"
131
- message << stderr
132
- message << "\n" if !stderr.end_with?("\n")
133
- end
134
- if logs && !logs.empty?
135
- message << "--- ---\n"
136
- message << "--- Chef Client Logs ---\n"
137
- message << "--- ---\n"
138
- message << logs
139
- end
140
- message
141
- end
142
-
143
- class EventSink
144
- def initialize
145
- @events = []
146
- end
147
-
148
- attr_reader :events
149
-
150
- def method_missing(method, *args)
151
- @events << [ method, *args ]
152
- end
153
- end
154
- end
155
- end
1
+ require 'cheffish/basic_chef_client'
2
+
3
+ module Cheffish
4
+ class ChefRun
5
+ #
6
+ # @param chef_config A hash with symbol keys that looks suspiciously similar to `Chef::Config`.
7
+ # Some possible options:
8
+ # - stdout: <IO object> - where to stream stdout to
9
+ # - stderr: <IO object> - where to stream stderr to
10
+ # - log_level: :debug|:info|:warn|:error|:fatal
11
+ # - log_location: <path|IO object> - where to stream logs to
12
+ # - verbose_logging: true|false - true if you want verbose logging in :debug
13
+ #
14
+ def initialize(chef_config={})
15
+ @chef_config = chef_config || {}
16
+ end
17
+
18
+ attr_reader :chef_config
19
+
20
+ class StringIOTee < StringIO
21
+ def initialize(*streams)
22
+ super()
23
+ @streams = streams.flatten.select { |s| !s.nil? }
24
+ end
25
+
26
+ attr_reader :streams
27
+
28
+ def write(*args, &block)
29
+ super
30
+ streams.each { |s| s.write(*args, &block) }
31
+ end
32
+ end
33
+
34
+ def client
35
+ @client ||= begin
36
+ chef_config = self.chef_config.dup
37
+ chef_config[:log_level] ||= :debug if !chef_config.has_key?(:log_level)
38
+ chef_config[:verbose_logging] = false if !chef_config.has_key?(:verbose_logging)
39
+ chef_config[:stdout] = StringIOTee.new(chef_config[:stdout])
40
+ chef_config[:stderr] = StringIOTee.new(chef_config[:stderr])
41
+ chef_config[:log_location] = StringIOTee.new(chef_config[:log_location])
42
+ @client = ::Cheffish::BasicChefClient.new(nil,
43
+ [ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ],
44
+ chef_config
45
+ )
46
+ end
47
+ end
48
+
49
+ def event_sink
50
+ @event_sink ||= EventSink.new
51
+ end
52
+
53
+ #
54
+ # output
55
+ #
56
+ def stdout
57
+ @client ? client.chef_config[:stdout].string : nil
58
+ end
59
+ def stderr
60
+ @client ? client.chef_config[:stderr].string : nil
61
+ end
62
+ def logs
63
+ @client ? client.chef_config[:log_location].string : nil
64
+ end
65
+ def logged_warnings
66
+ logs.lines.select { |l| l =~ /^\[[^\]]*\] WARN:/ }.join("\n")
67
+ end
68
+ def logged_errors
69
+ logs.lines.select { |l| l =~ /^\[[^\]]*\] ERROR:/ }.join("\n")
70
+ end
71
+ def logged_info
72
+ logs.lines.select { |l| l =~ /^\[[^\]]*\] INFO:/ }.join("\n")
73
+ end
74
+
75
+ def resources
76
+ client.resource_collection
77
+ end
78
+
79
+ def compile_recipe(&recipe)
80
+ client.load_block(&recipe)
81
+ end
82
+
83
+ def converge
84
+ begin
85
+ client.converge
86
+ @converged = true
87
+ rescue RuntimeError => e
88
+ @raised_exception = e
89
+ raise
90
+ end
91
+ end
92
+
93
+ def reset
94
+ @client = nil
95
+ @converged = nil
96
+ @stdout = nil
97
+ @stderr = nil
98
+ @logs = nil
99
+ @raised_exception = nil
100
+ end
101
+
102
+ def converged?
103
+ !!@converged
104
+ end
105
+
106
+ def converge_failed?
107
+ @raised_exception.nil? ? false : true
108
+ end
109
+
110
+ def updated?
111
+ client.updated?
112
+ end
113
+
114
+ def up_to_date?
115
+ !client.updated?
116
+ end
117
+
118
+ def output_for_failure_message
119
+ message = ""
120
+ if stdout && !stdout.empty?
121
+ message << "--- ---\n"
122
+ message << "--- Chef Client Output ---\n"
123
+ message << "--- ---\n"
124
+ message << stdout
125
+ message << "\n" if !stdout.end_with?("\n")
126
+ end
127
+ if stderr && !stderr.empty?
128
+ message << "--- ---\n"
129
+ message << "--- Chef Client Error Output ---\n"
130
+ message << "--- ---\n"
131
+ message << stderr
132
+ message << "\n" if !stderr.end_with?("\n")
133
+ end
134
+ if logs && !logs.empty?
135
+ message << "--- ---\n"
136
+ message << "--- Chef Client Logs ---\n"
137
+ message << "--- ---\n"
138
+ message << logs
139
+ end
140
+ message
141
+ end
142
+
143
+ class EventSink
144
+ def initialize
145
+ @events = []
146
+ end
147
+
148
+ attr_reader :events
149
+
150
+ def method_missing(method, *args)
151
+ @events << [ method, *args ]
152
+ end
153
+
154
+ def respond_to_missing?(method_name, include_private = false)
155
+ # Chef::EventDispatch::Dispatcher calls #respond_to? to see (basically) if we'll accept an event;
156
+ # obviously, per above #method_missing, we'll accept whatever we're given. if there's a problem, it
157
+ # will surface higher up the stack.
158
+ true
159
+ end
160
+ end
161
+ end
162
+ end
@@ -1,19 +1,19 @@
1
- require 'chef/config'
2
- require 'cheffish/with_pattern'
3
-
4
- module Cheffish
5
- class ChefRunData
6
- def initialize(config)
7
- @local_servers = []
8
- @current_chef_server = Cheffish.default_chef_server(config)
9
- end
10
-
11
- extend Cheffish::WithPattern
12
- with :data_bag
13
- with :environment
14
- with :data_bag_item_encryption
15
- with :chef_server
16
-
17
- attr_reader :local_servers
18
- end
19
- end
1
+ require 'chef/config'
2
+ require 'cheffish/with_pattern'
3
+
4
+ module Cheffish
5
+ class ChefRunData
6
+ def initialize(config)
7
+ @local_servers = []
8
+ @current_chef_server = Cheffish.default_chef_server(config)
9
+ end
10
+
11
+ extend Cheffish::WithPattern
12
+ with :data_bag
13
+ with :environment
14
+ with :data_bag_item_encryption
15
+ with :chef_server
16
+
17
+ attr_reader :local_servers
18
+ end
19
+ end
@@ -1,30 +1,30 @@
1
- require 'chef/event_dispatch/base'
2
-
3
- module Cheffish
4
- class ChefRunListener < Chef::EventDispatch::Base
5
- def initialize(node)
6
- @node = node
7
- end
8
-
9
- attr_reader :node
10
-
11
- def run_complete(node)
12
- disconnect
13
- end
14
-
15
- def run_failed(exception)
16
- disconnect
17
- end
18
-
19
- private
20
-
21
- def disconnect
22
- # Stop the servers
23
- if node.run_context
24
- node.run_context.cheffish.local_servers.each do |server|
25
- server.stop
26
- end
27
- end
28
- end
29
- end
30
- end
1
+ require 'chef/event_dispatch/base'
2
+
3
+ module Cheffish
4
+ class ChefRunListener < Chef::EventDispatch::Base
5
+ def initialize(node)
6
+ @node = node
7
+ end
8
+
9
+ attr_reader :node
10
+
11
+ def run_complete(node)
12
+ disconnect
13
+ end
14
+
15
+ def run_failed(exception)
16
+ disconnect
17
+ end
18
+
19
+ private
20
+
21
+ def disconnect
22
+ # Stop the servers
23
+ if node.run_context
24
+ node.run_context.cheffish.local_servers.each do |server|
25
+ server.stop
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,113 +1,113 @@
1
- require 'openssl'
2
- require 'net/ssh'
3
- require 'etc'
4
- require 'socket'
5
- require 'digest/md5'
6
- require 'base64'
7
-
8
- module Cheffish
9
- class KeyFormatter
10
- # Returns nil or key, format
11
- def self.decode(str, pass_phrase=nil, filename='')
12
- key_format = {}
13
- key_format[:format] = format_of(str)
14
-
15
- case key_format[:format]
16
- when :openssh
17
- key = decode_openssh_key(str, filename)
18
- else
19
- begin
20
- key = OpenSSL::PKey.read(str) { pass_phrase }
21
- rescue
22
- return nil
23
- end
24
- end
25
-
26
- key_format[:type] = type_of(key)
27
- key_format[:size] = size_of(key) if size_of(key)
28
- key_format[:pass_phrase] = pass_phrase if pass_phrase
29
- # TODO cipher, exponent
30
-
31
- [key, key_format]
32
- end
33
-
34
- def self.encode(key, key_format)
35
- format = key_format[:format] || :pem
36
- case format
37
- when :openssh
38
- encode_openssh_key(key)
39
- when :pem
40
- if key_format[:pass_phrase]
41
- cipher = key_format[:cipher] || 'DES-EDE3-CBC'
42
- key.to_pem(OpenSSL::Cipher.new(cipher), key_format[:pass_phrase])
43
- else
44
- key.to_pem
45
- end
46
- when :der
47
- key.to_der
48
- when :fingerprint, :pkcs1md5fingerprint
49
- hexes = Digest::MD5.hexdigest(key.to_der)
50
- # Put : between every pair of hexes
51
- hexes.scan(/../).join(':')
52
- when :rfc4716md5fingerprint
53
- type, base64_data, etc = encode_openssh_key(key).split
54
- data = Base64.decode64(base64_data)
55
- hexes = Digest::MD5.hexdigest(data)
56
- hexes.scan(/../).join(':')
57
- when :pkcs8sha1fingerprint
58
- if RUBY_VERSION.to_f >= 2.0
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(':')
67
- else
68
- raise "Unrecognized key format #{format}"
69
- end
70
- end
71
-
72
- private
73
-
74
- def self.encode_openssh_key(key)
75
- # TODO there really isn't a method somewhere in net/ssh or openssl that does this??
76
- type = key.ssh_type
77
- data = [ key.to_blob ].pack('m0')
78
- "#{type} #{data} #{Etc.getlogin}@#{Socket.gethostname}"
79
- end
80
-
81
- def self.decode_openssh_key(str, filename='')
82
- Net::SSH::KeyFactory.load_data_public_key(str, filename)
83
- end
84
-
85
- def self.format_of(key_contents)
86
- if key_contents.start_with?('-----BEGIN ')
87
- :pem
88
- elsif key_contents.start_with?('ssh-rsa ') || key_contents.start_with?('ssh-dss ')
89
- :openssh
90
- else
91
- :der
92
- end
93
- end
94
-
95
- def self.type_of(key)
96
- case key.class
97
- when OpenSSL::PKey::RSA
98
- :rsa
99
- when OpenSSL::PKey::DSA
100
- :dsa
101
- end
102
- end
103
-
104
- def self.size_of(key)
105
- case key.class
106
- when OpenSSL::PKey::RSA
107
- key.n.num_bytes * 8
108
- else
109
- nil
110
- end
111
- end
112
- end
113
- end
1
+ require 'openssl'
2
+ require 'net/ssh'
3
+ require 'etc'
4
+ require 'socket'
5
+ require 'digest/md5'
6
+ require 'base64'
7
+
8
+ module Cheffish
9
+ class KeyFormatter
10
+ # Returns nil or key, format
11
+ def self.decode(str, pass_phrase=nil, filename='')
12
+ key_format = {}
13
+ key_format[:format] = format_of(str)
14
+
15
+ case key_format[:format]
16
+ when :openssh
17
+ key = decode_openssh_key(str, filename)
18
+ else
19
+ begin
20
+ key = OpenSSL::PKey.read(str) { pass_phrase }
21
+ rescue
22
+ return nil
23
+ end
24
+ end
25
+
26
+ key_format[:type] = type_of(key)
27
+ key_format[:size] = size_of(key) if size_of(key)
28
+ key_format[:pass_phrase] = pass_phrase if pass_phrase
29
+ # TODO cipher, exponent
30
+
31
+ [key, key_format]
32
+ end
33
+
34
+ def self.encode(key, key_format)
35
+ format = key_format[:format] || :pem
36
+ case format
37
+ when :openssh
38
+ encode_openssh_key(key)
39
+ when :pem
40
+ if key_format[:pass_phrase]
41
+ cipher = key_format[:cipher] || 'DES-EDE3-CBC'
42
+ key.to_pem(OpenSSL::Cipher.new(cipher), key_format[:pass_phrase])
43
+ else
44
+ key.to_pem
45
+ end
46
+ when :der
47
+ key.to_der
48
+ when :fingerprint, :pkcs1md5fingerprint
49
+ hexes = Digest::MD5.hexdigest(key.to_der)
50
+ # Put : between every pair of hexes
51
+ hexes.scan(/../).join(':')
52
+ when :rfc4716md5fingerprint
53
+ type, base64_data, etc = encode_openssh_key(key).split
54
+ data = Base64.decode64(base64_data)
55
+ hexes = Digest::MD5.hexdigest(data)
56
+ hexes.scan(/../).join(':')
57
+ when :pkcs8sha1fingerprint
58
+ if RUBY_VERSION.to_f >= 2.0
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(':')
67
+ else
68
+ raise "Unrecognized key format #{format}"
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def self.encode_openssh_key(key)
75
+ # TODO there really isn't a method somewhere in net/ssh or openssl that does this??
76
+ type = key.ssh_type
77
+ data = [ key.to_blob ].pack('m0')
78
+ "#{type} #{data} #{Etc.getlogin}@#{Socket.gethostname}"
79
+ end
80
+
81
+ def self.decode_openssh_key(str, filename='')
82
+ Net::SSH::KeyFactory.load_data_public_key(str, filename)
83
+ end
84
+
85
+ def self.format_of(key_contents)
86
+ if key_contents.start_with?('-----BEGIN ')
87
+ :pem
88
+ elsif key_contents.start_with?('ssh-rsa ') || key_contents.start_with?('ssh-dss ')
89
+ :openssh
90
+ else
91
+ :der
92
+ end
93
+ end
94
+
95
+ def self.type_of(key)
96
+ case key.class
97
+ when OpenSSL::PKey::RSA
98
+ :rsa
99
+ when OpenSSL::PKey::DSA
100
+ :dsa
101
+ end
102
+ end
103
+
104
+ def self.size_of(key)
105
+ case key.class
106
+ when OpenSSL::PKey::RSA
107
+ key.n.num_bytes * 8
108
+ else
109
+ nil
110
+ end
111
+ end
112
+ end
113
+ end