chef-ssl-client 0.0.6
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.
- data/README.rdoc +6 -0
- data/Rakefile +8 -0
- data/bin/chef-ssl +7 -0
- data/lib/chef-ssl/client/issued_certificate.rb +69 -0
- data/lib/chef-ssl/client/request.rb +42 -0
- data/lib/chef-ssl/client/signing_authority.rb +83 -0
- data/lib/chef-ssl/client/version.rb +5 -0
- data/lib/chef-ssl/client.rb +64 -0
- data/lib/chef-ssl/command.rb +260 -0
- metadata +177 -0
data/Rakefile
ADDED
data/bin/chef-ssl
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module ChefSSL
|
2
|
+
class Client
|
3
|
+
class CertSaveFailed < StandardError; end
|
4
|
+
|
5
|
+
class IssuedCertificate
|
6
|
+
|
7
|
+
DATABAG = "certificates"
|
8
|
+
|
9
|
+
def initialize(req, cert, ca=nil)
|
10
|
+
@ca = ca
|
11
|
+
@req = req
|
12
|
+
@cert = cert
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_pem
|
16
|
+
@cert.to_pem
|
17
|
+
end
|
18
|
+
|
19
|
+
def sha1_fingerprint
|
20
|
+
@cert.sha1_fingerprint
|
21
|
+
end
|
22
|
+
|
23
|
+
def subject
|
24
|
+
@cert.subject.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def issuer
|
28
|
+
@cert.issuer.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def not_after
|
32
|
+
@cert.not_after
|
33
|
+
end
|
34
|
+
|
35
|
+
def save!
|
36
|
+
begin
|
37
|
+
Spice.create_data_bag(DATABAG)
|
38
|
+
rescue Spice::Error::Conflict
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
data = {
|
43
|
+
:name => DATABAG,
|
44
|
+
:id => @req.id,
|
45
|
+
:dn => @req.subject,
|
46
|
+
:ca => @req.ca,
|
47
|
+
:csr => @req.to_pem,
|
48
|
+
:key => @req.key,
|
49
|
+
:type => @req.type,
|
50
|
+
:date => Time.now.to_s,
|
51
|
+
:host => @req.host,
|
52
|
+
:certificate => @cert.to_pem
|
53
|
+
}
|
54
|
+
unless @ca.nil?
|
55
|
+
data[:cacert] = @ca.certificate.to_pem
|
56
|
+
end
|
57
|
+
|
58
|
+
begin
|
59
|
+
ret = Spice.create_data_bag_item(DATABAG, data)
|
60
|
+
rescue Spice::Error::Conflict
|
61
|
+
raise CertSaveFailed.new("Conflict - certificate data bag exists for #{@req.subject}, id #{@req.id}")
|
62
|
+
rescue Spice::Error::ClientError => e
|
63
|
+
raise CertSaveFailed.new(e.message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ChefSSL
|
2
|
+
class Client
|
3
|
+
class Request
|
4
|
+
|
5
|
+
attr_reader :host, :csr, :type, :ca, :id, :name, :key, :days
|
6
|
+
|
7
|
+
def initialize(host, data, csr=nil)
|
8
|
+
@host = host
|
9
|
+
@csr = csr || EaSSL::SigningRequest.new.load(data['csr'])
|
10
|
+
@type = data['type']
|
11
|
+
@ca = data['ca']
|
12
|
+
@id = data['id']
|
13
|
+
@name = data['name']
|
14
|
+
@key = data['key']
|
15
|
+
@days = data['days'] || (365 * 5)
|
16
|
+
end
|
17
|
+
|
18
|
+
def subject
|
19
|
+
@csr.subject.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_pem
|
23
|
+
@csr.to_pem
|
24
|
+
end
|
25
|
+
|
26
|
+
def issue_certificate(cert_text)
|
27
|
+
cert = EaSSL::Certificate.new({}).load(cert_text)
|
28
|
+
IssuedCertificate.new(self, cert)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create(key, type, options)
|
32
|
+
name = EaSSL::CertificateName.new(options)
|
33
|
+
csr = EaSSL::SigningRequest.new(:name => name, :key => key)
|
34
|
+
|
35
|
+
data = {
|
36
|
+
:type => type
|
37
|
+
}
|
38
|
+
self.new('localhost', data, csr)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module ChefSSL
|
2
|
+
class Client
|
3
|
+
class SigningAuthority
|
4
|
+
|
5
|
+
def self.load(options)
|
6
|
+
ca = EaSSL::CertificateAuthority.load(
|
7
|
+
:ca_path => options[:path],
|
8
|
+
:ca_password => options[:password]
|
9
|
+
)
|
10
|
+
self.new(ca)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(ca)
|
14
|
+
@ca = ca
|
15
|
+
end
|
16
|
+
|
17
|
+
def dn
|
18
|
+
@ca.certificate.subject.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def sign(req)
|
22
|
+
cert = @ca.create_certificate(req.csr, req.type, req.days)
|
23
|
+
IssuedCertificate.new(req, cert, @ca)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.create(name, path, passphrase)
|
27
|
+
config = {
|
28
|
+
:ca_dir => path,
|
29
|
+
:password => passphrase,
|
30
|
+
:ca_rsa_key_length => 1024,
|
31
|
+
:ca_cert_days => 3650,
|
32
|
+
:name => name
|
33
|
+
}
|
34
|
+
config[:serial_file] = File.join(config[:ca_dir], 'serial.txt')
|
35
|
+
config[:keypair_file] = File.join(config[:ca_dir], 'cakey.pem')
|
36
|
+
config[:cert_file] = File.join(config[:ca_dir], 'cacert.pem')
|
37
|
+
|
38
|
+
Dir.mkdir config[:ca_dir]
|
39
|
+
Dir.mkdir File.join(config[:ca_dir], 'private'), 0700
|
40
|
+
Dir.mkdir File.join(config[:ca_dir], 'newcerts')
|
41
|
+
Dir.mkdir File.join(config[:ca_dir], 'crl')
|
42
|
+
|
43
|
+
File.open config[:serial_file], 'w' do |f| f << '1' end
|
44
|
+
|
45
|
+
keypair = OpenSSL::PKey::RSA.new config[:ca_rsa_key_length]
|
46
|
+
|
47
|
+
cert = OpenSSL::X509::Certificate.new
|
48
|
+
cert.subject = cert.issuer = config[:name]
|
49
|
+
cert.not_before = Time.now
|
50
|
+
cert.not_after = Time.now + config[:ca_cert_days] * 24 * 60 * 60
|
51
|
+
cert.public_key = keypair.public_key
|
52
|
+
cert.serial = 0x0
|
53
|
+
cert.version = 2 # X509v3
|
54
|
+
|
55
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
56
|
+
ef.subject_certificate = cert
|
57
|
+
ef.issuer_certificate = cert
|
58
|
+
cert.extensions = [
|
59
|
+
ef.create_extension("basicConstraints", "CA:TRUE", true),
|
60
|
+
ef.create_extension("nsComment", "Ruby/OpenSSL/chef-ssl Generated Certificate"),
|
61
|
+
ef.create_extension("subjectKeyIdentifier", "hash"),
|
62
|
+
ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
|
63
|
+
]
|
64
|
+
cert.add_extension ef.create_extension("authorityKeyIdentifier",
|
65
|
+
"keyid:always,issuer:always")
|
66
|
+
cert.sign keypair, OpenSSL::Digest::SHA1.new
|
67
|
+
|
68
|
+
keypair_export = keypair.export OpenSSL::Cipher::DES.new(:EDE3, :CBC),
|
69
|
+
config[:password]
|
70
|
+
|
71
|
+
File.open config[:keypair_file], "w", 0400 do |fp|
|
72
|
+
fp << keypair_export
|
73
|
+
end
|
74
|
+
|
75
|
+
File.open config[:cert_file], "w", 0644 do |f|
|
76
|
+
f << cert.to_pem
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spice'
|
2
|
+
require 'eassl'
|
3
|
+
require 'json'
|
4
|
+
require 'openssl'
|
5
|
+
require 'digest/sha2'
|
6
|
+
require 'active_support/hash_with_indifferent_access'
|
7
|
+
require 'chef/config'
|
8
|
+
require 'chef/node'
|
9
|
+
|
10
|
+
require 'chef-ssl/client/version'
|
11
|
+
require 'chef-ssl/client/request'
|
12
|
+
require 'chef-ssl/client/signing_authority'
|
13
|
+
require 'chef-ssl/client/issued_certificate'
|
14
|
+
|
15
|
+
module ChefSSL
|
16
|
+
class Client
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
path = File.expand_path('knife.rb', '~/.chef')
|
20
|
+
Chef::Config.from_file(path)
|
21
|
+
Spice.reset
|
22
|
+
Spice.setup do |s|
|
23
|
+
s.server_url = Chef::Config.chef_server_url
|
24
|
+
s.client_name = Chef::Config.node_name
|
25
|
+
s.client_key = Spice.read_key_file(File.expand_path(Chef::Config.client_key))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.load_authority(options)
|
30
|
+
SigningAuthority.load(
|
31
|
+
:path => options[:path],
|
32
|
+
:password => options[:password]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def ca_search(ca=nil)
|
37
|
+
if ca
|
38
|
+
nodes = Spice.nodes("csr_outbox_*_ca:#{ca}")
|
39
|
+
else
|
40
|
+
nodes = Spice.nodes("csr_outbox_*")
|
41
|
+
end
|
42
|
+
nodes.each do |node|
|
43
|
+
node.normal['csr_outbox'].each do |id, data|
|
44
|
+
next if data['csr'].nil? # XXX warn, raise?
|
45
|
+
yield Request.new(node.name, data)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def common_name_search(name)
|
51
|
+
name_sha = Digest::SHA256.new << name
|
52
|
+
cert_id = name_sha.to_s
|
53
|
+
nodes = Spice.nodes("csr_outbox_*_id:#{cert_id}")
|
54
|
+
nodes.each do |node|
|
55
|
+
node.normal['csr_outbox'].each do |id, data|
|
56
|
+
next unless data['id'] == cert_id
|
57
|
+
next if data['csr'].nil? # XXX warn, raise?
|
58
|
+
yield Request.new(node.name, data)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
program :name, "chef-ssl"
|
2
|
+
program :version, ChefSSL::Client::VERSION
|
3
|
+
program :description, "Chef-automated SSL certificate signing tool"
|
4
|
+
program :help_formatter, :compact
|
5
|
+
|
6
|
+
default_command :help
|
7
|
+
|
8
|
+
command :issue do |c|
|
9
|
+
c.syntax = "chef-ssl issue [options]"
|
10
|
+
c.description = "Issue an ad hoc certificate"
|
11
|
+
c.example "Issue cert for www.venda.com",
|
12
|
+
"chef-ssl issue --ca-path ./myCA --dn /CN=foo --type server"
|
13
|
+
|
14
|
+
c.option "--ca-path=STRING", String, "the path to the new CA"
|
15
|
+
c.option "--dn=STRING", String, "the distinguished name for the new certificate"
|
16
|
+
c.option "--type=STRING", String, "the type of certificate, client or server"
|
17
|
+
|
18
|
+
c.action do |args, options|
|
19
|
+
raise "CA path is required" unless options.ca_path
|
20
|
+
raise "DN is required" unless options.dn
|
21
|
+
raise "type is required" unless options.type
|
22
|
+
|
23
|
+
begin
|
24
|
+
dn = OpenSSL::X509::Name.parse(options.dn)
|
25
|
+
rescue NoMethodError
|
26
|
+
raise "--dn is required and must be a distinguished name"
|
27
|
+
rescue TypeError
|
28
|
+
raise "--dn is required and must be a distinguished name"
|
29
|
+
rescue OpenSSL::X509::NameError => e
|
30
|
+
raise "--dn must specify a valid DN: #{e.message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
unless options.type == 'server' || options.type == 'client'
|
34
|
+
raise "type must be server or client"
|
35
|
+
end
|
36
|
+
|
37
|
+
authority = ChefSSL::Client.load_authority(
|
38
|
+
:password => ask("Enter CA passphrase: ") { |q| q.echo = false },
|
39
|
+
:path => options.ca_path
|
40
|
+
)
|
41
|
+
|
42
|
+
key = EaSSL::Key.new
|
43
|
+
|
44
|
+
h = dn.to_a.reduce({}) { |h, elem| h[elem[0]] = elem[1]; h }
|
45
|
+
name = {
|
46
|
+
:city => h['L'],
|
47
|
+
:state => h['ST'],
|
48
|
+
:country => h['C'],
|
49
|
+
:department => h['OU'],
|
50
|
+
:common_name => h['CN'],
|
51
|
+
:organization => h['O'],
|
52
|
+
:email => h['emailAddress']
|
53
|
+
}
|
54
|
+
|
55
|
+
req = ChefSSL::Client::Request.create(key, options.type, name)
|
56
|
+
cert = authority.sign(req)
|
57
|
+
|
58
|
+
puts "#{'Key:'.cyan}"
|
59
|
+
puts HighLine.color(key.private_key.to_s, :bright_black)
|
60
|
+
puts
|
61
|
+
puts "#{'Certificate:'.cyan} SHA1 Fingerprint=#{cert.sha1_fingerprint}"
|
62
|
+
puts HighLine.color(cert.to_pem, :bright_black)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
command :makeca do |c|
|
67
|
+
c.syntax = "chef-ssl makeca [options]"
|
68
|
+
c.description = "Creates a new CA"
|
69
|
+
c.example "Upload cert for CSR www.venda.com",
|
70
|
+
"chef-ssl makeca --ca-name '/CN=My New CA' --ca-path ./newCA"
|
71
|
+
|
72
|
+
c.option "--ca-path=STRING", String, "the path to the new CA"
|
73
|
+
c.option "--ca-name=STRING", String, "the distinguished name of the new CA"
|
74
|
+
|
75
|
+
c.action do |args, options|
|
76
|
+
begin
|
77
|
+
name = OpenSSL::X509::Name.parse(options.ca_name)
|
78
|
+
rescue NoMethodError
|
79
|
+
raise "--ca-name is required and must be a distinguished name"
|
80
|
+
rescue TypeError
|
81
|
+
raise "--ca-name is required and must be a distinguished name"
|
82
|
+
rescue OpenSSL::X509::NameError => e
|
83
|
+
raise "--ca-name must specify a valid DN: #{e.message}"
|
84
|
+
end
|
85
|
+
|
86
|
+
raise "CA path is required" unless options.ca_path
|
87
|
+
raise "CA path must not already exist" if Dir.glob(options.ca_path).length > 0
|
88
|
+
|
89
|
+
puts "#{'New CA DN'.cyan}: #{name.to_s}"
|
90
|
+
puts
|
91
|
+
|
92
|
+
passphrase = ask("Enter new CA passphrase: ") { |q| q.echo = false }
|
93
|
+
passphrase2 = ask("Re-enter new CA passphrase: ") { |q| q.echo = false }
|
94
|
+
raise "passphrases do not match" unless passphrase == passphrase2
|
95
|
+
|
96
|
+
print "\n#{'Creating new CA'.cyan}: "
|
97
|
+
ChefSSL::Client::SigningAuthority.create(name, options.ca_path, passphrase)
|
98
|
+
puts "done"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
command :search do |c|
|
103
|
+
c.syntax = "chef-ssl search [options]"
|
104
|
+
c.description = "Searches for outstanding CSRs"
|
105
|
+
c.example "Search for all CSRs awaiting signing by CA bob",
|
106
|
+
"chef-ssl search --ca-name bob"
|
107
|
+
|
108
|
+
c.option "--ca-name=STRING", String, "a name of a CA to limit the search by"
|
109
|
+
|
110
|
+
c.action do |args, options|
|
111
|
+
client = ChefSSL::Client.new
|
112
|
+
|
113
|
+
puts "#{'Search CA'.cyan}: #{options.ca_name}" if options.ca_name
|
114
|
+
|
115
|
+
client.ca_search(options.ca_name) do |req|
|
116
|
+
puts
|
117
|
+
puts "#{' Node Hostname'.cyan}: #{req.host}"
|
118
|
+
puts "#{' Certificate Type'.cyan}: #{req.type.bold}"
|
119
|
+
puts "#{' Certificate DN'.cyan}: #{req.subject.bold}"
|
120
|
+
puts "#{' Requested CA'.cyan}: #{req.ca.bold}"
|
121
|
+
puts "#{'Requested Validity'.cyan}: #{req.days.to_s.bold} days"
|
122
|
+
puts
|
123
|
+
puts HighLine.color(req.to_pem, :bright_black)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
command :sign do |c|
|
129
|
+
c.syntax = "chef-ssl sign [options]"
|
130
|
+
c.description = "Search for the given CSR by name and provide a signed certificate"
|
131
|
+
c.example "Provide signed cert for CSR www.venda.com",
|
132
|
+
"chef-ssl --name www.venda.com"
|
133
|
+
|
134
|
+
c.option "--name=STRING", String, "common name of the CSR to search for"
|
135
|
+
|
136
|
+
c.action do |args, options|
|
137
|
+
|
138
|
+
raise "--name is required" unless options.name
|
139
|
+
|
140
|
+
client = ChefSSL::Client.new
|
141
|
+
|
142
|
+
puts "#{'Search name'.cyan}: #{options.name}"
|
143
|
+
|
144
|
+
client.common_name_search(options.name) do |req|
|
145
|
+
puts
|
146
|
+
puts "#{' Node Hostname'.cyan}: #{req.host}"
|
147
|
+
puts "#{' Certificate Type'.cyan}: #{req.type.bold}"
|
148
|
+
puts "#{' Certificate DN'.cyan}: #{req.subject.bold}"
|
149
|
+
puts "#{' Requested CA'.cyan}: #{req.ca.bold}"
|
150
|
+
puts "#{'Requested Validity'.cyan}: #{req.days.to_s.bold} days"
|
151
|
+
puts
|
152
|
+
puts HighLine.color(req.to_pem, :bright_black)
|
153
|
+
|
154
|
+
cert = nil
|
155
|
+
|
156
|
+
HighLine.new.choose do |menu|
|
157
|
+
menu.layout = :one_line
|
158
|
+
menu.prompt = "Sign this? "
|
159
|
+
|
160
|
+
menu.choice :yes do
|
161
|
+
cert_text = ask("Paste cert text") do |q|
|
162
|
+
q.gather = ""
|
163
|
+
end
|
164
|
+
cert = req.issue_certificate(cert_text.join("\n"))
|
165
|
+
end
|
166
|
+
menu.choice :no do
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
if cert
|
172
|
+
puts "#{' Signed:'.cyan} SHA1 Fingerprint=#{cert.sha1_fingerprint}"
|
173
|
+
puts "#{'Subject:'.cyan} #{cert.subject}"
|
174
|
+
puts "#{' Issuer:'.cyan} #{cert.issuer}"
|
175
|
+
puts HighLine.color(cert.to_pem, :bright_black)
|
176
|
+
|
177
|
+
unless cert.subject == req.subject
|
178
|
+
puts "#{'WARNING:'.red.bold} #{'Issued certificate DN does not match request DN!'.bold}"
|
179
|
+
end
|
180
|
+
|
181
|
+
HighLine.new.choose do |menu|
|
182
|
+
menu.layout = :one_line
|
183
|
+
menu.prompt = "Save certificate? "
|
184
|
+
|
185
|
+
menu.choice :yes do
|
186
|
+
begin
|
187
|
+
cert.save!
|
188
|
+
puts "Saved OK"
|
189
|
+
rescue ChefSSL::Client::CertSaveFailed => e
|
190
|
+
puts "Error saving: #{e.message}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
menu.choice :no do
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
command :autosign do |c|
|
203
|
+
c.syntax = "chef-ssl autosign [options]"
|
204
|
+
c.description = "Search for CSRs and sign them with the given CA"
|
205
|
+
c.example "Sign with 'CA'",
|
206
|
+
"chef-ssl --ca-path CA --ca-name autoCA"
|
207
|
+
|
208
|
+
c.option "--ca-path=STRING", String, "the path to the signing CA"
|
209
|
+
c.option "--ca-name=STRING", String, "the name of the signing CA"
|
210
|
+
|
211
|
+
c.action do |args, options|
|
212
|
+
|
213
|
+
raise "--ca-path is required" unless options.ca_path
|
214
|
+
raise "--ca-name is required" unless options.ca_name
|
215
|
+
|
216
|
+
authority = ChefSSL::Client.load_authority(
|
217
|
+
:password => ask("Enter CA passphrase: ") { |q| q.echo = false },
|
218
|
+
:path => options.ca_path
|
219
|
+
)
|
220
|
+
|
221
|
+
client = ChefSSL::Client.new
|
222
|
+
|
223
|
+
puts "#{'Search CA'.cyan}: #{options.ca_name}"
|
224
|
+
|
225
|
+
client.ca_search(options.ca_name) do |req|
|
226
|
+
puts
|
227
|
+
puts "#{' Node Hostname'.cyan}: #{req.host}"
|
228
|
+
puts "#{' Certificate Type'.cyan}: #{req.type.bold}"
|
229
|
+
puts "#{' Certificate DN'.cyan}: #{req.subject.bold}"
|
230
|
+
puts "#{' Requested CA'.cyan}: #{req.ca.bold}"
|
231
|
+
puts "#{'Requested Validity'.cyan}: #{req.days.to_s.bold} days"
|
232
|
+
puts
|
233
|
+
puts HighLine.color(req.to_pem, :bright_black)
|
234
|
+
|
235
|
+
HighLine.new.choose do |menu|
|
236
|
+
menu.layout = :one_line
|
237
|
+
menu.prompt = "#{'Sign with'.cyan}: #{HighLine.color(authority.dn, :bold)}\nSign this? "
|
238
|
+
|
239
|
+
menu.choice :yes do
|
240
|
+
cert = authority.sign(req)
|
241
|
+
puts
|
242
|
+
puts "#{'Signed:'.cyan} SHA1 Fingerprint=#{cert.sha1_fingerprint}"
|
243
|
+
puts HighLine.color(cert.to_pem, :bright_black)
|
244
|
+
begin
|
245
|
+
cert.save!
|
246
|
+
puts "Saved OK"
|
247
|
+
rescue ChefSSL::Client::CertSaveFailed => e
|
248
|
+
puts "Error saving: #{e.message}"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
menu.choice :no do
|
253
|
+
nil
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
puts "All CSRs processed."
|
259
|
+
end
|
260
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-ssl-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Venda
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-23 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chef
|
16
|
+
requirement: &2163253520 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.10.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2163253520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: spice
|
27
|
+
requirement: &2163252940 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.3
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2163252940
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: eassl2
|
38
|
+
requirement: &2163252120 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2163252120
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: highline
|
49
|
+
requirement: &2163251220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.6.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2163251220
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: commander
|
60
|
+
requirement: &2163250360 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 4.1.0
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2163250360
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: multi_json
|
71
|
+
requirement: &2163249800 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.0.0
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2163249800
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: activesupport
|
82
|
+
requirement: &2163249120 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 3.1.0
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2163249120
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rspec
|
93
|
+
requirement: &2163248560 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 2.10.0
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *2163248560
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: flexmock
|
104
|
+
requirement: &2163247960 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.9.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *2163247960
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: simplecov
|
115
|
+
requirement: &2163247420 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *2163247420
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: rake
|
126
|
+
requirement: &2163246840 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *2163246840
|
135
|
+
description: A command-line client the ssl cookbook's signing requirements
|
136
|
+
email: auto-ssl@venda.com
|
137
|
+
executables:
|
138
|
+
- chef-ssl
|
139
|
+
extensions: []
|
140
|
+
extra_rdoc_files:
|
141
|
+
- README.rdoc
|
142
|
+
files:
|
143
|
+
- README.rdoc
|
144
|
+
- Rakefile
|
145
|
+
- bin/chef-ssl
|
146
|
+
- lib/chef-ssl/client/issued_certificate.rb
|
147
|
+
- lib/chef-ssl/client/request.rb
|
148
|
+
- lib/chef-ssl/client/signing_authority.rb
|
149
|
+
- lib/chef-ssl/client/version.rb
|
150
|
+
- lib/chef-ssl/client.rb
|
151
|
+
- lib/chef-ssl/command.rb
|
152
|
+
homepage: http://docs.uk.venda.com/vendadocs/TeamAwesome/Project☃/pki
|
153
|
+
licenses: []
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
166
|
+
requirements:
|
167
|
+
- - ! '>='
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 1.8.6
|
173
|
+
signing_key:
|
174
|
+
specification_version: 3
|
175
|
+
summary: A command-line client the ssl cookbook's signing requirements
|
176
|
+
test_files: []
|
177
|
+
has_rdoc: true
|