Skip to content

Commit

Permalink
(PUP-2606) Add EC private key support
Browse files Browse the repository at this point in the history
Adds two Puppet settings `key_type` and `named_curve`. If the `key_type` is set
to `ec` then the agent will generate an elliptic curve (EC) private key, but
only if it doesn't have a key yet. If it has a previously saved RSA key, then
this commit has no effect.

Puppet defaults to the elliptic curve 'prime256v1', but alternate curves may be
specified using the `named_curve` setting, provided OpenSSL and ruby support it.
For example, ruby does not yet support X25519[1]. The list of currently
supported curves is available from `OpenSSL::PKey::EC.builtin_curves`.

The `named_curve` setting only affects how EC keys are generated (and the
resulting client certificate, since the public key is embedded in the cert), but
not the list of supported curves in TLS[2], which are configurable via
`OpenSSL::SSL::SSLContext#ecdh_curves=`.

Note it is perfectly acceptable for an agent to use EC keys, while puppetserver
uses RSA, provided the server supports `ECDHE_RSA` or `ECDH_RSA` key exchange.

Since the saved private key can be either RSA or EC, use the more
generic `OpenSSL::PKey.read` method which returns the appropriate class
of private key. However, JRuby's implementation is broken, so check for
EC or fallback to RSA.

Ruby modified the EC class extensively in 2.4 so that it followed the generic
OpenSSL::PKey interface. To ensure compatibility across different ruby versions
this commit monkey patches the `EC#private_key?` and `EC.generate` methods,
but only if the methods are not defined.

[1] ruby/openssl#117
[2] https://tools.ietf.org/html/rfc4492#section-5.1.1
  • Loading branch information
joshcooper committed Apr 24, 2019
1 parent 81aa35e commit 9a471bf
Show file tree
Hide file tree
Showing 38 changed files with 990 additions and 747 deletions.
9 changes: 7 additions & 2 deletions lib/puppet/application/ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,13 @@ def main
def submit_request(ssl_context)
key = @cert_provider.load_private_key(Puppet[:certname])
unless key
Puppet.info _("Creating a new SSL key for %{name}") % { name: Puppet[:certname] }
key = OpenSSL::PKey::RSA.new(Puppet[:keylength].to_i)
if Puppet[:key_type] == 'ec'
Puppet.info _("Creating a new EC SSL key for %{name} using curve %{curve}") % { name: Puppet[:certname], curve: Puppet[:named_curve] }
key = OpenSSL::PKey::EC.generate(Puppet[:named_curve])
else
Puppet.info _("Creating a new SSL key for %{name}") % { name: Puppet[:certname] }
key = OpenSSL::PKey::RSA.new(Puppet[:keylength].to_i)
end
@cert_provider.save_private_key(Puppet[:certname], key)
end

Expand Down
13 changes: 13 additions & 0 deletions lib/puppet/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,19 @@ def self.default_vendormoduledir
certificate revocation checking and does not attempt to download the CRL.
EOT
},
:key_type => {
:default => 'rsa',
:type => :enum,
:values => %w[rsa ec],
:desc => "The type of private key. Valid values are `rsa` and `ec`. Default is `rsa`."
},
:named_curve => {
:default => 'prime256v1',
:type => :string,
:desc => "The short name for the EC curve used to generate the EC private key. Valid
values must be one of the curves in `OpenSSL::PKey::EC.builtin_curves`.
Default is `prime256v1`."
},
:digest_algorithm => {
:default => lambda { default_digest_algorithm },
:type => :enum,
Expand Down
14 changes: 12 additions & 2 deletions lib/puppet/ssl/certificate_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@ def generate(key, options = {})
csr = OpenSSL::X509::Request.new
csr.version = 0
csr.subject = OpenSSL::X509::Name.new([["CN", common_name]])
csr.public_key = key.public_key

csr.public_key = if key.is_a?(OpenSSL::PKey::EC)
# EC#public_key doesn't following the PKey API,
# see https://github.com/ruby/openssl/issues/29
point = key.public_key
pubkey = OpenSSL::PKey::EC.new(point.group)
pubkey.public_key = point
pubkey
else
key.public_key
end

if options[:csr_attributes]
add_csr_attributes(csr, options[:csr_attributes])
Expand All @@ -88,7 +98,7 @@ def generate(key, options = {})
signer = Puppet::SSL::CertificateSigner.new
signer.sign(csr, key)

raise Puppet::Error, _("CSR sign verification failed; you need to clean the certificate request for %{name} on the server") % { name: name } unless csr.verify(key.public_key)
raise Puppet::Error, _("CSR sign verification failed; you need to clean the certificate request for %{name} on the server") % { name: name } unless csr.verify(csr.public_key)

@content = csr

Expand Down
6 changes: 3 additions & 3 deletions lib/puppet/ssl/ssl_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def create_root_context(cacerts:, crls: [], revocation: Puppet[:certificate_revo
#
# @param cacerts [Array<OpenSSL::X509::Certificate>] Array of trusted CA certs
# @param crls [Array<OpenSSL::X509::CRL>] Array of CRLs
# @param private_key [OpenSSL::PKey::RSA] client's private key
# @param private_key [OpenSSL::PKey::RSA, OpenSSL::PKey::EC] client's private key
# @param client_cert [OpenSSL::X509::Certificate] client's cert whose public
# key matches the `private_key`
# @param revocation [:chain, :leaf, false] revocation mode
Expand All @@ -70,7 +70,7 @@ def create_context(cacerts:, crls:, private_key:, client_cert:, revocation: Pupp
store = create_x509_store(cacerts, crls, revocation)
client_chain = verify_cert_with_store(store, client_cert)

unless private_key.is_a?(OpenSSL::PKey::RSA)
unless private_key.is_a?(OpenSSL::PKey::RSA) || private_key.is_a?(OpenSSL::PKey::EC)
raise Puppet::SSL::SSLError, _("Unsupported key '%{type}'") % { type: private_key.class.name }
end

Expand Down Expand Up @@ -116,7 +116,7 @@ def load_context(certname: Puppet[:certname], revocation: Puppet[:certificate_re
# of the private key, and that it hasn't been tampered with since.
#
# @param csr [OpenSSL::X509::Request] certificate signing request
# @param public_key [OpenSSL::PKey::RSA] public key
# @param public_key [OpenSSL::PKey::RSA, OpenSSL::PKey::EC] public key
# @raise [Puppet::SSL:SSLError] The private_key for the given `public_key` was
# not used to sign the CSR.
# @api private
Expand Down
9 changes: 7 additions & 2 deletions lib/puppet/ssl/state_machine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,13 @@ def next_state
return Done.new(@machine, next_ctx)
end
else
Puppet.info _("Creating a new SSL key for %{name}") % { name: Puppet[:certname] }
key = OpenSSL::PKey::RSA.new(Puppet[:keylength].to_i)
if Puppet[:key_type] == 'ec'
Puppet.info _("Creating a new EC SSL key for %{name} using curve %{curve}") % { name: Puppet[:certname], curve: Puppet[:named_curve] }
key = OpenSSL::PKey::EC.generate(Puppet[:named_curve])
else
Puppet.info _("Creating a new RSA SSL key for %{name}") % { name: Puppet[:certname] }
key = OpenSSL::PKey::RSA.new(Puppet[:keylength].to_i)
end
@cert_provider.save_private_key(Puppet[:certname], key)
end

Expand Down
17 changes: 17 additions & 0 deletions lib/puppet/util/monkey_patches.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ def to_utf8
end
end

unless OpenSSL::PKey::EC.instance_methods.include?(:private?)
class OpenSSL::PKey::EC
# Added in ruby 2.4.0 in https://github.com/ruby/ruby/commit/7c971e61f04
alias :private? :private_key?
end
end

unless OpenSSL::PKey::EC.singleton_methods.include?(:generate)
class OpenSSL::PKey::EC
# Added in ruby 2.4.0 in https://github.com/ruby/ruby/commit/85500b66342
def self.generate(string)
ec = OpenSSL::PKey::EC.new(string)
ec.generate_key
end
end
end

# The Enumerable#uniq method was added in Ruby 2.4.0 (https://bugs.ruby-lang.org/issues/11090)
# This is a backport to earlier Ruby versions.
#
Expand Down
26 changes: 23 additions & 3 deletions lib/puppet/x509/cert_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Puppet::X509::CertProvider
VALID_CERTNAME = /\A[ -.0-~]+\Z/
CERT_DELIMITERS = /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
CRL_DELIMITERS = /-----BEGIN X509 CRL-----.*?-----END X509 CRL-----/m
EC_HEADER = /-----BEGIN EC PRIVATE KEY-----/

def initialize(capath: Puppet[:localcacert],
crlpath: Puppet[:hostcrl],
Expand Down Expand Up @@ -146,14 +147,33 @@ def load_private_key(name, required: false)
# Load a PEM encoded private key.
#
# @param pem [String] PEM encoded private key
# @return [OpenSSL::PKey::RSA] The private key
# @raise [OpenSSL::PKey::RSAError] The `pem` text does not contain a valid key
# @return [OpenSSL::PKey::RSA, OpenSSL::PKey::EC] The private key
# @raise [OpenSSL::PKey::PKeyError] The `pem` text does not contain a valid key
# @api private
def load_private_key_from_pem(pem)
# set a non-nil passphrase to ensure openssl doesn't prompt
# but ruby 2.4.0 & 2.4.1 require at least 4 bytes, see
# https://github.com/ruby/ruby/commit/f012932218fd609f75f9268812df61fb26e2d0f1#diff-40e4270ec386990ac60d7ab5ff8045a4
OpenSSL::PKey::RSA.new(pem, ' ')
if Puppet::Util::Platform.jruby?
begin
if pem =~ EC_HEADER
OpenSSL::PKey::EC.new(pem, ' ')
else
OpenSSL::PKey::RSA.new(pem, ' ')
end
rescue OpenSSL::PKey::PKeyError => e
if e.message =~ /Neither PUB key nor PRIV key/
raise OpenSSL::PKey::PKeyError, "Could not parse PKey: no start line"
else
raise e
end
end
else
OpenSSL::PKey.read(pem, ' ')
end
rescue ArgumentError => e
# handle EC keys on ruby <= 2.3
raise OpenSSL::PKey::PKeyError, e.message
end

# Save a named client cert to the configured `certdir`.
Expand Down
112 changes: 56 additions & 56 deletions spec/fixtures/ssl/127.0.0.1-key.pem
Original file line number Diff line number Diff line change
@@ -1,67 +1,67 @@
Private-Key: (1024 bit)
modulus:
00:bb:e1:47:40:df:d0:06:c2:ef:5b:0b:41:41:01:
f8:a3:68:fe:18:82:21:5b:97:b5:7c:25:f2:31:b9:
50:09:a8:56:71:4c:81:e5:fe:e0:2b:f3:8d:38:e8:
fd:15:c2:a3:5a:db:56:5d:29:49:4d:75:e5:ae:69:
a7:a3:ac:19:c6:23:cb:1a:23:57:15:aa:ca:e1:e1:
78:79:af:49:15:bf:7d:9a:42:16:bc:b1:18:61:68:
d8:e1:34:57:4e:73:a0:90:3e:1f:8a:56:fd:0c:eb:
f0:fb:03:fd:ec:1b:ff:15:1f:d7:3e:5c:73:09:15:
48:83:e5:ff:4e:b3:ea:3a:a9
00:98:34:bb:6c:44:52:00:23:29:ae:bb:7c:c9:91:
ec:6b:1c:83:b1:db:6c:b6:1b:12:fb:e3:f4:e4:20:
27:6c:c7:50:f9:ac:ef:f8:7a:de:00:4a:01:cb:ba:
9b:be:35:3c:e5:33:ef:32:79:61:1c:a6:70:23:19:
16:19:ae:33:e5:96:0a:70:3d:81:2f:b3:59:64:89:
45:ef:86:97:4d:00:9b:1d:68:9e:8d:5e:75:fb:69:
c0:1b:b2:06:1d:97:1a:27:30:38:3e:4f:11:04:70:
70:98:c1:6a:fc:93:a5:17:0f:fb:fe:42:31:af:f3:
6a:bc:51:dc:33:86:be:5f:c9
publicExponent: 65537 (0x10001)
privateExponent:
22:7d:7d:b6:24:20:2d:4d:95:e1:31:d4:bd:d9:5d:
ca:a9:d8:93:a9:37:f4:77:8a:42:8b:38:c5:f6:0e:
02:67:db:ce:9a:cb:f1:eb:f3:3d:3e:4d:bb:97:d1:
f6:2f:b0:0b:5a:de:a4:e5:92:66:5c:f1:58:2e:5f:
2f:05:c6:09:30:2e:77:0c:07:64:ea:9e:c2:f4:72:
b0:f9:31:36:af:45:7e:a5:44:bf:b8:f9:1c:0d:fc:
9f:8e:41:08:c4:8e:d0:8d:4e:de:2d:f3:42:c3:d0:
6e:ca:70:21:bb:f5:c4:e2:67:13:21:10:5a:0b:68:
7b:5d:9f:ea:08:f0:12:3d
6a:b3:cd:10:c1:74:9b:14:0b:8c:ab:73:77:fc:0c:
b9:aa:6b:c8:ac:03:32:47:18:af:ed:c7:28:86:42:
1d:48:3d:c4:4b:30:90:09:d2:c8:71:19:81:31:79:
2d:87:35:01:99:be:fe:ab:89:21:04:ad:68:6d:95:
c8:bb:0f:35:b7:84:83:ce:32:fe:9e:98:b5:71:a0:
67:30:e5:17:1d:d9:c3:48:9b:a7:c1:f4:17:f8:4a:
bb:88:1b:94:2c:cc:5d:90:92:f8:6e:93:36:eb:42:
63:d0:c9:6f:04:e5:c1:2f:dc:a8:1f:19:ed:e5:b0:
45:23:ab:82:d4:0b:69:81
prime1:
00:e3:d5:5c:8e:b9:31:28:ce:d3:c0:78:0d:b2:12:
0e:14:95:a4:b8:48:20:82:2f:27:37:f5:b8:6e:b4:
ec:57:7f:92:c4:23:15:5b:d1:b6:35:20:60:49:36:
fb:63:8d:df:34:45:af:07:80:a7:9b:05:2f:43:5e:
af:9a:bc:9b:43
00:c8:90:0e:0f:a2:ab:82:a7:e5:3a:69:dd:3a:e7:
a2:80:ef:b2:12:c5:fb:4b:a2:cf:b6:9a:41:8c:d8:
b5:76:05:c5:d3:c6:0e:1d:c6:1e:14:9f:14:21:53:
15:08:42:70:12:12:36:1e:0d:be:b8:5d:ce:46:66:
0b:fc:1a:dd:95
prime2:
00:d3:1b:70:e1:ff:2d:af:09:a9:3e:65:04:58:3d:
65:11:bd:98:7e:39:26:ab:33:98:37:cf:46:13:2e:
6f:dd:48:0e:0c:bb:ee:3a:a7:91:60:81:6f:9f:54:
65:2c:cd:8a:6f:27:a5:6a:72:f1:3d:44:9c:b3:eb:
b8:56:6f:b5:a3
00:c2:46:ec:9d:fc:0b:1c:e7:c4:b3:2a:eb:ff:64:
8e:2d:32:f7:f5:9c:bf:60:46:ca:46:db:91:33:fb:
47:8a:c4:2c:c7:4a:b0:34:cb:34:1b:93:bd:aa:3a:
3a:a4:b8:f6:4e:4b:b7:23:03:bb:07:43:6e:39:31:
61:ce:0c:24:65
exponent1:
00:b4:ef:ca:4c:f2:98:2e:ef:6a:cd:8c:ca:5b:a3:
e9:18:c1:eb:0a:0b:05:fe:3d:92:68:e7:b5:2b:fe:
75:3f:db:e9:e3:e8:74:da:f1:c6:41:94:cf:c2:f5:
6e:5a:16:de:af:75:b3:d6:42:7f:59:26:99:ed:67:
f2:0f:f2:3f:5f
14:08:5f:7f:2c:4e:59:44:8f:de:df:c8:1b:24:1b:
d5:29:1b:ee:48:1c:2b:97:dd:8b:6d:a8:f2:7a:8a:
d5:79:0a:23:76:fa:dd:fa:75:f2:b5:58:fb:63:23:
0c:aa:26:2b:87:ea:23:e2:57:94:6e:ba:35:c9:e7:
94:8c:d2:69
exponent2:
10:8b:45:fd:70:12:14:75:9d:5d:d6:6c:d0:bd:7e:
fe:34:ed:8e:76:cc:20:fe:9a:1f:45:8f:28:51:ab:
52:9c:22:fd:bc:7c:9e:fc:22:d8:7d:4c:52:20:3b:
0d:97:ce:11:87:f9:de:ad:c3:5a:19:d6:6e:03:3b:
1f:0b:02:21
50:c3:c5:68:64:38:86:7a:bf:a6:30:68:cd:d2:92:
dc:ad:7c:b1:c9:c9:31:90:1c:55:5a:c0:41:98:ec:
03:ff:4c:12:49:b5:79:2d:24:eb:75:fe:fa:3e:9c:
d4:8f:e4:2d:66:82:aa:f6:c9:10:da:f2:7e:aa:4d:
db:a7:e6:95
coefficient:
00:a9:b1:a0:81:72:a1:e9:41:51:3e:32:5a:33:aa:
20:b1:23:bf:ff:62:53:a7:6d:e2:c1:d5:18:11:57:
b6:9e:fd:b2:c5:d8:d8:50:d1:5e:5c:22:ba:14:e3:
36:92:34:4c:29:19:dc:a3:60:a8:01:81:00:5b:c1:
3b:4e:0f:26:23
45:11:a8:a2:ab:92:a6:f2:42:b3:7f:09:8d:ae:45:
25:e5:c6:24:9e:80:ea:58:b5:d7:44:7f:84:47:6b:
4d:da:f0:f3:4c:60:5b:9d:18:64:b2:89:2c:1e:b2:
60:35:58:ef:90:6f:b5:12:d7:0e:d7:7b:4a:62:ac:
38:b4:12:80
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC74UdA39AGwu9bC0FBAfijaP4YgiFbl7V8JfIxuVAJqFZxTIHl
/uAr84046P0VwqNa21ZdKUlNdeWuaaejrBnGI8saI1cVqsrh4Xh5r0kVv32aQha8
sRhhaNjhNFdOc6CQPh+KVv0M6/D7A/3sG/8VH9c+XHMJFUiD5f9Os+o6qQIDAQAB
AoGAIn19tiQgLU2V4THUvdldyqnYk6k39HeKQos4xfYOAmfbzprL8evzPT5Nu5fR
9i+wC1repOWSZlzxWC5fLwXGCTAudwwHZOqewvRysPkxNq9FfqVEv7j5HA38n45B
CMSO0I1O3i3zQsPQbspwIbv1xOJnEyEQWgtoe12f6gjwEj0CQQDj1VyOuTEoztPA
eA2yEg4UlaS4SCCCLyc39bhutOxXf5LEIxVb0bY1IGBJNvtjjd80Ra8HgKebBS9D
Xq+avJtDAkEA0xtw4f8trwmpPmUEWD1lEb2YfjkmqzOYN89GEy5v3UgODLvuOqeR
YIFvn1RlLM2KbyelanLxPUScs+u4Vm+1owJBALTvykzymC7vas2Myluj6RjB6woL
Bf49kmjntSv+dT/b6ePodNrxxkGUz8L1bloW3q91s9ZCf1kmme1n8g/yP18CQBCL
Rf1wEhR1nV3WbNC9fv407Y52zCD+mh9FjyhRq1KcIv28fJ78Ith9TFIgOw2XzhGH
+d6tw1oZ1m4DOx8LAiECQQCpsaCBcqHpQVE+MlozqiCxI7//YlOnbeLB1RgRV7ae
/bLF2NhQ0V5cIroU4zaSNEwpGdyjYKgBgQBbwTtODyYj
MIICWwIBAAKBgQCYNLtsRFIAIymuu3zJkexrHIOx22y2GxL74/TkICdsx1D5rO/4
et4ASgHLupu+NTzlM+8yeWEcpnAjGRYZrjPllgpwPYEvs1lkiUXvhpdNAJsdaJ6N
XnX7acAbsgYdlxonMDg+TxEEcHCYwWr8k6UXD/v+QjGv82q8Udwzhr5fyQIDAQAB
AoGAarPNEMF0mxQLjKtzd/wMuapryKwDMkcYr+3HKIZCHUg9xEswkAnSyHEZgTF5
LYc1AZm+/quJIQStaG2VyLsPNbeEg84y/p6YtXGgZzDlFx3Zw0ibp8H0F/hKu4gb
lCzMXZCS+G6TNutCY9DJbwTlwS/cqB8Z7eWwRSOrgtQLaYECQQDIkA4PoquCp+U6
ad0656KA77ISxftLos+2mkGM2LV2BcXTxg4dxh4UnxQhUxUIQnASEjYeDb64Xc5G
Zgv8Gt2VAkEAwkbsnfwLHOfEsyrr/2SOLTL39Zy/YEbKRtuRM/tHisQsx0qwNMs0
G5O9qjo6pLj2Tku3IwO7B0NuOTFhzgwkZQJAFAhffyxOWUSP3t/IGyQb1Skb7kgc
K5fdi22o8nqK1XkKI3b63fp18rVY+2MjDKomK4fqI+JXlG66NcnnlIzSaQJAUMPF
aGQ4hnq/pjBozdKS3K18scnJMZAcVVrAQZjsA/9MEkm1eS0k63X++j6c1I/kLWaC
qvbJENryfqpN26fmlQJARRGooquSpvJCs38Jja5FJeXGJJ6A6li110R/hEdrTdrw
80xgW50YZLKJLB6yYDVY75BvtRLXDtd7SmKsOLQSgA==
-----END RSA PRIVATE KEY-----
54 changes: 27 additions & 27 deletions spec/fixtures/ssl/127.0.0.1.pem
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,43 @@ Certificate:
Issuer: CN=Test CA
Validity
Not Before: Jan 1 00:00:00 1970 GMT
Not After : Mar 9 21:35:53 2029 GMT
Not After : Apr 19 22:31:22 2029 GMT
Subject: CN=127.0.0.1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:bb:e1:47:40:df:d0:06:c2:ef:5b:0b:41:41:01:
f8:a3:68:fe:18:82:21:5b:97:b5:7c:25:f2:31:b9:
50:09:a8:56:71:4c:81:e5:fe:e0:2b:f3:8d:38:e8:
fd:15:c2:a3:5a:db:56:5d:29:49:4d:75:e5:ae:69:
a7:a3:ac:19:c6:23:cb:1a:23:57:15:aa:ca:e1:e1:
78:79:af:49:15:bf:7d:9a:42:16:bc:b1:18:61:68:
d8:e1:34:57:4e:73:a0:90:3e:1f:8a:56:fd:0c:eb:
f0:fb:03:fd:ec:1b:ff:15:1f:d7:3e:5c:73:09:15:
48:83:e5:ff:4e:b3:ea:3a:a9
00:98:34:bb:6c:44:52:00:23:29:ae:bb:7c:c9:91:
ec:6b:1c:83:b1:db:6c:b6:1b:12:fb:e3:f4:e4:20:
27:6c:c7:50:f9:ac:ef:f8:7a:de:00:4a:01:cb:ba:
9b:be:35:3c:e5:33:ef:32:79:61:1c:a6:70:23:19:
16:19:ae:33:e5:96:0a:70:3d:81:2f:b3:59:64:89:
45:ef:86:97:4d:00:9b:1d:68:9e:8d:5e:75:fb:69:
c0:1b:b2:06:1d:97:1a:27:30:38:3e:4f:11:04:70:
70:98:c1:6a:fc:93:a5:17:0f:fb:fe:42:31:af:f3:
6a:bc:51:dc:33:86:be:5f:c9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:127.0.0.1, DNS:127.0.0.2
Signature Algorithm: sha256WithRSAEncryption
ba:0d:5c:ae:e4:7b:7f:ec:39:f5:e6:29:ab:6a:bf:65:26:87:
04:50:ca:93:f1:ee:7a:65:3a:6b:7c:b2:d7:96:f2:29:19:8a:
0d:ed:e3:3d:ed:d1:5d:72:c2:a6:60:bc:13:c6:c0:92:a8:a2:
23:3b:35:6b:58:a5:c4:7c:74:88:1a:00:bd:47:0f:c8:4b:4d:
f6:2c:16:61:1c:9a:b9:b6:be:28:0e:41:17:df:bc:f3:21:a8:
2c:a3:e2:4b:23:e0:2e:06:f3:b6:0e:90:3d:87:8c:da:a8:66:
14:7e:03:e2:69:85:0d:a7:a9:d9:b6:25:92:fd:13:e1:e9:71:
f9:da
a0:40:1e:cc:ed:75:47:4b:3a:a6:05:fb:a6:29:22:cd:f9:28:
4c:f3:3d:0c:e2:df:6c:91:68:52:1b:df:d4:9d:88:36:e9:db:
ca:94:a4:14:d9:2a:bb:b6:f7:a9:4a:70:f7:db:d7:86:e4:82:
e4:dd:08:77:03:7b:fb:99:24:fd:15:44:b5:05:dd:b3:ff:dc:
e0:b4:e8:92:7f:58:b3:2f:48:ba:80:c9:a6:1c:c8:8e:99:e1:
52:f4:52:90:ad:44:8b:89:39:a1:51:67:15:99:a2:f5:76:75:
b4:12:f5:5e:99:e7:8b:7b:b1:9d:04:63:31:33:36:0d:a8:67:
00:42
-----BEGIN CERTIFICATE-----
MIIBvzCCASigAwIBAgIBAzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdUZXN0
IENBMB4XDTcwMDEwMTAwMDAwMFoXDTI5MDMwOTIxMzU1M1owFDESMBAGA1UEAwwJ
MTI3LjAuMC4xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC74UdA39AGwu9b
C0FBAfijaP4YgiFbl7V8JfIxuVAJqFZxTIHl/uAr84046P0VwqNa21ZdKUlNdeWu
aaejrBnGI8saI1cVqsrh4Xh5r0kVv32aQha8sRhhaNjhNFdOc6CQPh+KVv0M6/D7
A/3sG/8VH9c+XHMJFUiD5f9Os+o6qQIDAQABoyMwITAfBgNVHREEGDAWggkxMjcu
MC4wLjGCCTEyNy4wLjAuMjANBgkqhkiG9w0BAQsFAAOBgQC6DVyu5Ht/7Dn15imr
ar9lJocEUMqT8e56ZTprfLLXlvIpGYoN7eM97dFdcsKmYLwTxsCSqKIjOzVrWKXE
fHSIGgC9Rw/IS032LBZhHJq5tr4oDkEX37zzIagso+JLI+AuBvO2DpA9h4zaqGYU
fgPiaYUNp6nZtiWS/RPh6XH52g==
IENBMB4XDTcwMDEwMTAwMDAwMFoXDTI5MDQxOTIyMzEyMlowFDESMBAGA1UEAwwJ
MTI3LjAuMC4xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYNLtsRFIAIymu
u3zJkexrHIOx22y2GxL74/TkICdsx1D5rO/4et4ASgHLupu+NTzlM+8yeWEcpnAj
GRYZrjPllgpwPYEvs1lkiUXvhpdNAJsdaJ6NXnX7acAbsgYdlxonMDg+TxEEcHCY
wWr8k6UXD/v+QjGv82q8Udwzhr5fyQIDAQABoyMwITAfBgNVHREEGDAWggkxMjcu
MC4wLjGCCTEyNy4wLjAuMjANBgkqhkiG9w0BAQsFAAOBgQCgQB7M7XVHSzqmBfum
KSLN+ShM8z0M4t9skWhSG9/UnYg26dvKlKQU2Sq7tvepSnD329eG5ILk3Qh3A3v7
mST9FUS1Bd2z/9zgtOiSf1izL0i6gMmmHMiOmeFS9FKQrUSLiTmhUWcVmaL1dnW0
EvVemeeLe7GdBGMxMzYNqGcAQg==
-----END CERTIFICATE-----
Loading

0 comments on commit 9a471bf

Please sign in to comment.