leap_cli 1.5.6 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/leap +29 -6
- data/lib/leap/platform.rb +36 -1
- data/lib/leap_cli/commands/ca.rb +97 -20
- data/lib/leap_cli/commands/compile.rb +49 -8
- data/lib/leap_cli/commands/db.rb +13 -4
- data/lib/leap_cli/commands/deploy.rb +138 -29
- data/lib/leap_cli/commands/env.rb +76 -0
- data/lib/leap_cli/commands/facts.rb +10 -3
- data/lib/leap_cli/commands/inspect.rb +2 -2
- data/lib/leap_cli/commands/list.rb +10 -10
- data/lib/leap_cli/commands/node.rb +7 -132
- data/lib/leap_cli/commands/node_init.rb +169 -0
- data/lib/leap_cli/commands/pre.rb +4 -27
- data/lib/leap_cli/commands/ssh.rb +152 -0
- data/lib/leap_cli/commands/test.rb +22 -13
- data/lib/leap_cli/commands/user.rb +12 -4
- data/lib/leap_cli/commands/vagrant.rb +4 -4
- data/lib/leap_cli/config/filter.rb +175 -0
- data/lib/leap_cli/config/manager.rb +130 -61
- data/lib/leap_cli/config/node.rb +32 -0
- data/lib/leap_cli/config/object.rb +69 -44
- data/lib/leap_cli/config/object_list.rb +44 -39
- data/lib/leap_cli/config/secrets.rb +24 -12
- data/lib/leap_cli/config/tag.rb +7 -0
- data/lib/{core_ext → leap_cli/core_ext}/boolean.rb +0 -0
- data/lib/{core_ext → leap_cli/core_ext}/hash.rb +0 -0
- data/lib/{core_ext → leap_cli/core_ext}/json.rb +0 -0
- data/lib/{core_ext → leap_cli/core_ext}/nil.rb +0 -0
- data/lib/{core_ext → leap_cli/core_ext}/string.rb +0 -0
- data/lib/leap_cli/core_ext/yaml.rb +29 -0
- data/lib/leap_cli/exceptions.rb +24 -0
- data/lib/leap_cli/leapfile.rb +60 -10
- data/lib/{lib_ext → leap_cli/lib_ext}/capistrano_connections.rb +0 -0
- data/lib/{lib_ext → leap_cli/lib_ext}/gli.rb +0 -0
- data/lib/leap_cli/log.rb +1 -1
- data/lib/leap_cli/logger.rb +18 -1
- data/lib/leap_cli/markdown_document_listener.rb +1 -1
- data/lib/leap_cli/override/json.rb +11 -0
- data/lib/leap_cli/path.rb +20 -6
- data/lib/leap_cli/remote/leap_plugin.rb +2 -2
- data/lib/leap_cli/remote/puppet_plugin.rb +1 -1
- data/lib/leap_cli/remote/rsync_plugin.rb +1 -1
- data/lib/leap_cli/remote/tasks.rb +1 -1
- data/lib/leap_cli/ssh_key.rb +63 -1
- data/lib/leap_cli/util/remote_command.rb +19 -2
- data/lib/leap_cli/util/secret.rb +1 -1
- data/lib/leap_cli/util/x509.rb +3 -2
- data/lib/leap_cli/util.rb +11 -3
- data/lib/leap_cli/version.rb +2 -2
- data/lib/leap_cli.rb +24 -14
- data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +85 -29
- data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +5 -0
- data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +406 -41
- data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +0 -34
- data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +6 -0
- data/vendor/certificate_authority/lib/certificate_authority/signing_request.rb +36 -1
- metadata +25 -24
- data/lib/leap_cli/commands/shell.rb +0 -89
- data/lib/leap_cli/config/macros.rb +0 -430
- data/lib/leap_cli/constants.rb +0 -7
- data/lib/leap_cli/requirements.rb +0 -19
- data/lib/lib_ext/markdown_document_listener.rb +0 -122
@@ -33,7 +33,7 @@ module CertificateAuthority
|
|
33
33
|
self.serial_number = SerialNumber.new
|
34
34
|
self.key_material = MemoryKeyMaterial.new
|
35
35
|
self.not_before = Time.now
|
36
|
-
self.not_after = Time.now + 60 * 60 * 24 * 365 #One year
|
36
|
+
self.not_after = Time.now + 60 * 60 * 24 * 365 # One year
|
37
37
|
self.parent = self
|
38
38
|
self.extensions = load_extensions()
|
39
39
|
|
@@ -41,12 +41,31 @@ module CertificateAuthority
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
+
=begin
|
45
|
+
def self.from_openssl openssl_cert
|
46
|
+
unless openssl_cert.is_a? OpenSSL::X509::Certificate
|
47
|
+
raise "Can only construct from an OpenSSL::X509::Certificate"
|
48
|
+
end
|
49
|
+
|
50
|
+
certificate = Certificate.new
|
51
|
+
# Only subject, key_material, and body are used for signing
|
52
|
+
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
|
53
|
+
certificate.key_material.public_key = openssl_cert.public_key
|
54
|
+
certificate.openssl_body = openssl_cert
|
55
|
+
certificate.serial_number.number = openssl_cert.serial.to_i
|
56
|
+
certificate.not_before = openssl_cert.not_before
|
57
|
+
certificate.not_after = openssl_cert.not_after
|
58
|
+
# TODO extensions
|
59
|
+
certificate
|
60
|
+
end
|
61
|
+
=end
|
62
|
+
|
44
63
|
def sign!(signing_profile={})
|
45
64
|
raise "Invalid certificate #{self.errors.full_messages}" unless valid?
|
46
65
|
merge_profile_with_extensions(signing_profile)
|
47
66
|
|
48
67
|
openssl_cert = OpenSSL::X509::Certificate.new
|
49
|
-
openssl_cert.version
|
68
|
+
openssl_cert.version = 2
|
50
69
|
openssl_cert.not_before = self.not_before
|
51
70
|
openssl_cert.not_after = self.not_after
|
52
71
|
openssl_cert.public_key = self.key_material.public_key
|
@@ -58,7 +77,6 @@ module CertificateAuthority
|
|
58
77
|
|
59
78
|
require 'tempfile'
|
60
79
|
t = Tempfile.new("bullshit_conf")
|
61
|
-
# t = File.new("/tmp/openssl.cnf")
|
62
80
|
## The config requires a file even though we won't use it
|
63
81
|
openssl_config = OpenSSL::Config.new(t.path)
|
64
82
|
|
@@ -85,7 +103,7 @@ module CertificateAuthority
|
|
85
103
|
self.extensions.keys.sort{|a,b| b<=>a}.each do |k|
|
86
104
|
e = extensions[k]
|
87
105
|
next if e.to_s.nil? or e.to_s == "" ## If the extension returns an empty string we won't include it
|
88
|
-
ext = factory.create_ext(e.openssl_identifier, e.to_s)
|
106
|
+
ext = factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
89
107
|
openssl_cert.add_extension(ext)
|
90
108
|
end
|
91
109
|
|
@@ -94,9 +112,10 @@ module CertificateAuthority
|
|
94
112
|
else
|
95
113
|
digest = OpenSSL::Digest::Digest.new(signing_profile["digest"])
|
96
114
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
115
|
+
|
116
|
+
self.openssl_body = openssl_cert.sign(parent.key_material.private_key, digest)
|
117
|
+
ensure
|
118
|
+
t.close! if t # We can get rid of the ridiculous temp file
|
100
119
|
end
|
101
120
|
|
102
121
|
def is_signing_entity?
|
@@ -116,6 +135,34 @@ module CertificateAuthority
|
|
116
135
|
self.openssl_body.to_pem
|
117
136
|
end
|
118
137
|
|
138
|
+
def to_csr
|
139
|
+
csr = SigningRequest.new
|
140
|
+
csr.distinguished_name = self.distinguished_name
|
141
|
+
csr.key_material = self.key_material
|
142
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
143
|
+
exts = []
|
144
|
+
self.extensions.keys.each do |k|
|
145
|
+
## Don't copy over key identifiers for CSRs
|
146
|
+
next if k == "subjectKeyIdentifier" || k == "authorityKeyIdentifier"
|
147
|
+
e = extensions[k]
|
148
|
+
## If the extension returns an empty string we won't include it
|
149
|
+
next if e.to_s.nil? or e.to_s == ""
|
150
|
+
exts << factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
151
|
+
end
|
152
|
+
attrval = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(exts)])
|
153
|
+
attrs = [
|
154
|
+
OpenSSL::X509::Attribute.new("extReq", attrval),
|
155
|
+
OpenSSL::X509::Attribute.new("msExtReq", attrval)
|
156
|
+
]
|
157
|
+
csr.attributes = attrs
|
158
|
+
csr
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.from_x509_cert(raw_cert)
|
162
|
+
openssl_cert = OpenSSL::X509::Certificate.new(raw_cert)
|
163
|
+
Certificate.from_openssl(openssl_cert)
|
164
|
+
end
|
165
|
+
|
119
166
|
def is_root_entity?
|
120
167
|
self.parent == self && is_signing_entity?
|
121
168
|
end
|
@@ -134,6 +181,16 @@ module CertificateAuthority
|
|
134
181
|
items = signing_config[k]
|
135
182
|
items.keys.each do |profile_item_key|
|
136
183
|
if extension.respond_to?("#{profile_item_key}=".to_sym)
|
184
|
+
if k == 'subjectAltName' && profile_item_key == 'emails'
|
185
|
+
items[profile_item_key].map do |email|
|
186
|
+
if email == 'email:copy'
|
187
|
+
fail "no email address provided for subject: #{subject.to_x509_name}" unless subject.email_address
|
188
|
+
"email:#{subject.email_address}"
|
189
|
+
else
|
190
|
+
email
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
137
194
|
extension.send("#{profile_item_key}=".to_sym, items[profile_item_key] )
|
138
195
|
else
|
139
196
|
p "Tried applying '#{profile_item_key}' to #{extension.class} but it doesn't respond!"
|
@@ -142,30 +199,25 @@ module CertificateAuthority
|
|
142
199
|
end
|
143
200
|
end
|
144
201
|
|
202
|
+
# Enumeration of the extensions. Not the worst option since
|
203
|
+
# the likelihood of these needing to be updated is low at best.
|
204
|
+
EXTENSIONS = [
|
205
|
+
CertificateAuthority::Extensions::BasicConstraints,
|
206
|
+
CertificateAuthority::Extensions::CrlDistributionPoints,
|
207
|
+
CertificateAuthority::Extensions::SubjectKeyIdentifier,
|
208
|
+
CertificateAuthority::Extensions::AuthorityKeyIdentifier,
|
209
|
+
CertificateAuthority::Extensions::AuthorityInfoAccess,
|
210
|
+
CertificateAuthority::Extensions::KeyUsage,
|
211
|
+
CertificateAuthority::Extensions::ExtendedKeyUsage,
|
212
|
+
CertificateAuthority::Extensions::SubjectAlternativeName,
|
213
|
+
CertificateAuthority::Extensions::CertificatePolicies
|
214
|
+
]
|
215
|
+
|
145
216
|
def load_extensions
|
146
217
|
extension_hash = {}
|
147
218
|
|
148
|
-
|
149
|
-
|
150
|
-
temp_extensions << basic_constraints
|
151
|
-
crl_distribution_points = CertificateAuthority::Extensions::CrlDistributionPoints.new
|
152
|
-
temp_extensions << crl_distribution_points
|
153
|
-
subject_key_identifier = CertificateAuthority::Extensions::SubjectKeyIdentifier.new
|
154
|
-
temp_extensions << subject_key_identifier
|
155
|
-
authority_key_identifier = CertificateAuthority::Extensions::AuthorityKeyIdentifier.new
|
156
|
-
temp_extensions << authority_key_identifier
|
157
|
-
authority_info_access = CertificateAuthority::Extensions::AuthorityInfoAccess.new
|
158
|
-
temp_extensions << authority_info_access
|
159
|
-
key_usage = CertificateAuthority::Extensions::KeyUsage.new
|
160
|
-
temp_extensions << key_usage
|
161
|
-
extended_key_usage = CertificateAuthority::Extensions::ExtendedKeyUsage.new
|
162
|
-
temp_extensions << extended_key_usage
|
163
|
-
subject_alternative_name = CertificateAuthority::Extensions::SubjectAlternativeName.new
|
164
|
-
temp_extensions << subject_alternative_name
|
165
|
-
certificate_policies = CertificateAuthority::Extensions::CertificatePolicies.new
|
166
|
-
temp_extensions << certificate_policies
|
167
|
-
|
168
|
-
temp_extensions.each do |extension|
|
219
|
+
EXTENSIONS.each do |klass|
|
220
|
+
extension = klass.new
|
169
221
|
extension_hash[extension.openssl_identifier] = extension
|
170
222
|
end
|
171
223
|
|
@@ -192,7 +244,11 @@ module CertificateAuthority
|
|
192
244
|
certificate.serial_number.number = openssl_cert.serial.to_i
|
193
245
|
certificate.not_before = openssl_cert.not_before
|
194
246
|
certificate.not_after = openssl_cert.not_after
|
195
|
-
|
247
|
+
EXTENSIONS.each do |klass|
|
248
|
+
_,v,c = (openssl_cert.extensions.detect { |e| e.to_a.first == klass::OPENSSL_IDENTIFIER } || []).to_a
|
249
|
+
certificate.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v
|
250
|
+
end
|
251
|
+
|
196
252
|
certificate
|
197
253
|
end
|
198
254
|
|
@@ -32,11 +32,16 @@ module CertificateAuthority
|
|
32
32
|
alias :emailAddress :email_address
|
33
33
|
alias :emailAddress= :email_address=
|
34
34
|
|
35
|
+
attr_accessor :serial_number
|
36
|
+
alias :serialNumber :serial_number
|
37
|
+
alias :serialNumber= :serial_number=
|
38
|
+
|
35
39
|
def to_x509_name
|
36
40
|
raise "Invalid Distinguished Name" unless valid?
|
37
41
|
|
38
42
|
# NB: the capitalization in the strings counts
|
39
43
|
name = OpenSSL::X509::Name.new
|
44
|
+
name.add_entry("serialNumber", serial_number) unless serial_number.blank?
|
40
45
|
name.add_entry("C", country) unless country.blank?
|
41
46
|
name.add_entry("ST", state) unless state.blank?
|
42
47
|
name.add_entry("L", locality) unless locality.blank?
|