Merge "Support ICA signed certificate installation"
This commit is contained in:
commit
273a5b5fe5
|
@ -348,12 +348,43 @@ class CertificateController(rest.RestController):
|
|||
LOG.info(msg)
|
||||
return dict(success="", error=msg)
|
||||
|
||||
for cert in certs:
|
||||
hash_issuers = []
|
||||
for index, cert in enumerate(certs):
|
||||
msg = self._check_cert_validity(cert)
|
||||
if msg is not True:
|
||||
return dict(success="", error=msg)
|
||||
|
||||
if mode == constants.CERT_MODE_OPENSTACK:
|
||||
# validation checking for ssl, tpm_mode, docker_registry
|
||||
# and openstack certficcates
|
||||
if mode in [constants.CERT_MODE_SSL,
|
||||
constants.CERT_MODE_TPM,
|
||||
constants.CERT_MODE_DOCKER_REGISTRY,
|
||||
constants.CERT_MODE_OPENSTACK,
|
||||
]:
|
||||
try:
|
||||
hash_issuers.append(cutils.get_cert_issuer_hash(cert))
|
||||
if index == 0:
|
||||
if cutils.is_ca_cert(cert):
|
||||
msg = "The first cert in the file should not be " \
|
||||
"a CA cert"
|
||||
return dict(success="", error=msg)
|
||||
else:
|
||||
if not cutils.is_ca_cert(cert):
|
||||
msg = "Number %s cert in the file should be a " \
|
||||
"CA cert" % (index + 1)
|
||||
return dict(success="", error=msg)
|
||||
hash_subject = cutils.get_cert_subject_hash(cert)
|
||||
if hash_subject != hash_issuers[index - 1]:
|
||||
msg = "Number %s cert in the file is not " \
|
||||
"signing cert of the preceding one. Check " \
|
||||
"certs order in the file." % (index + 1)
|
||||
return dict(success="", error=msg)
|
||||
except Exception as e:
|
||||
msg = "No certificates have been added, exception " \
|
||||
"occured on cert %s: %s" % (index, e)
|
||||
return dict(success="", error=msg)
|
||||
|
||||
if mode == constants.CERT_MODE_OPENSTACK and index == 0:
|
||||
domain, msg = _check_endpoint_domain_exists()
|
||||
if domain:
|
||||
msg = _check_cert_dns_name(cert, domain)
|
||||
|
@ -412,6 +443,16 @@ class CertificateController(rest.RestController):
|
|||
# information returned from conductor manager.
|
||||
certificate_dicts = []
|
||||
for inv_cert in inv_certs:
|
||||
# for ssl, tmp_mode, docker_registry and openstack certs, if the
|
||||
# cert is ICA signed cert (ie, the pem_contents contains
|
||||
# intermediate CA certs), skip these intermediate CA certs.
|
||||
if mode in [constants.CERT_MODE_SSL,
|
||||
constants.CERT_MODE_TPM,
|
||||
constants.CERT_MODE_DOCKER_REGISTRY,
|
||||
constants.CERT_MODE_OPENSTACK] \
|
||||
and inv_cert.get('is_ca', None):
|
||||
continue
|
||||
|
||||
values = {
|
||||
'certtype': mode,
|
||||
'signature': inv_cert.get('signature'),
|
||||
|
|
|
@ -31,6 +31,8 @@ import collections
|
|||
import contextlib
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from OpenSSL import crypto
|
||||
import datetime
|
||||
import errno
|
||||
import functools
|
||||
|
@ -2210,10 +2212,70 @@ def extract_certs_from_pem(pem_contents):
|
|||
"Failed to load pem x509 certificate"))
|
||||
|
||||
certs.append(cert)
|
||||
start = start + index + len(marker)
|
||||
start = index + len(marker)
|
||||
return certs
|
||||
|
||||
|
||||
def is_ca_cert(cert):
|
||||
"""
|
||||
Check if the certificate is a CA certficate
|
||||
|
||||
:param cert: the certificate to be checked
|
||||
:return: True is the certificate is a CA certificate, otherwise
|
||||
False
|
||||
"""
|
||||
# extract "ca" value from cert extensions
|
||||
is_ca = False
|
||||
try:
|
||||
basic_constraints = cert.extensions.get_extension_for_oid(
|
||||
x509.ExtensionOID.BASIC_CONSTRAINTS)
|
||||
value = getattr(basic_constraints, 'value', None)
|
||||
if value:
|
||||
is_ca = getattr(value, 'ca', False)
|
||||
except x509.ExtensionNotFound:
|
||||
LOG.debug("The cert doesn't have BASIC_CONSTRAINTS extension")
|
||||
pass
|
||||
return is_ca
|
||||
|
||||
|
||||
def get_cert_issuer_hash(cert):
|
||||
"""
|
||||
Get the hash value of the cert's issuer DN
|
||||
|
||||
:param cert: the certificate to get issuer from
|
||||
:return: The hash value of the cert's issuer DN
|
||||
"""
|
||||
try:
|
||||
public_bytes = cert.public_bytes(encoding=serialization.Encoding.PEM)
|
||||
cert_c = crypto.load_certificate(crypto.FILETYPE_PEM, public_bytes)
|
||||
hash_issuer = cert_c.get_issuer().hash()
|
||||
except Exception:
|
||||
LOG.exception()
|
||||
raise exception.SysinvException(_(
|
||||
"Failed to get certificate issuer hash."))
|
||||
|
||||
return hash_issuer
|
||||
|
||||
|
||||
def get_cert_subject_hash(cert):
|
||||
"""
|
||||
Get the hash value of the cert's subject DN
|
||||
|
||||
:param cert: the certificate to get subject from
|
||||
:return: The hash value of the cert's subject DN
|
||||
"""
|
||||
try:
|
||||
public_bytes = cert.public_bytes(encoding=serialization.Encoding.PEM)
|
||||
cert_c = crypto.load_certificate(crypto.FILETYPE_PEM, public_bytes)
|
||||
hash_subject = cert_c.get_subject().hash()
|
||||
except Exception:
|
||||
LOG.exception()
|
||||
raise exception.SysinvException(_(
|
||||
"Failed to get certificate subject hash."))
|
||||
|
||||
return hash_subject
|
||||
|
||||
|
||||
def format_image_filename(device_image):
|
||||
""" Format device image filename """
|
||||
return "{}-{}-{}-{}.bit".format(device_image.bitstream_type,
|
||||
|
|
|
@ -10311,7 +10311,7 @@ class ConductorManager(service.PeriodicService):
|
|||
:param cert_format: serialization.PrivateFormat
|
||||
:param passphrase: passphrase for PEM file
|
||||
|
||||
:returns: A list of {cert, private_bytes, public_bytes, signature}
|
||||
:returns: A list of {cert, public_bytes, signature}, and private key.
|
||||
"""
|
||||
|
||||
if passphrase:
|
||||
|
@ -10353,7 +10353,7 @@ class ConductorManager(service.PeriodicService):
|
|||
% e))
|
||||
|
||||
certs = cutils.extract_certs_from_pem(temp_pem_contents)
|
||||
key_list = []
|
||||
cert_list = []
|
||||
for cert in certs:
|
||||
# format=serialization.PrivateFormat.TraditionalOpenSSL,
|
||||
try:
|
||||
|
@ -10364,40 +10364,49 @@ class ConductorManager(service.PeriodicService):
|
|||
"bytes from PEM data: %s"
|
||||
% e))
|
||||
|
||||
# check if the cert is a CA cert
|
||||
is_ca = cutils.is_ca_cert(cert)
|
||||
|
||||
signature = mode + '_' + str(cert.serial_number)
|
||||
if len(signature) > 255:
|
||||
LOG.info("Truncating certificate serial no %s" % signature)
|
||||
signature = signature[:255]
|
||||
LOG.info("config_certificate signature=%s" % signature)
|
||||
|
||||
key_list.append({'cert': cert,
|
||||
'private_bytes': private_bytes,
|
||||
cert_list.append({'cert': cert,
|
||||
'is_ca': is_ca,
|
||||
'public_bytes': public_bytes,
|
||||
'signature': signature})
|
||||
|
||||
return key_list
|
||||
return cert_list, private_bytes
|
||||
|
||||
@staticmethod
|
||||
def _get_public_bytes_one(key_list):
|
||||
"""Get exactly one public bytes entry from key list"""
|
||||
def _get_public_bytes(cert_list):
|
||||
"""Get all public bytes from cert list"""
|
||||
|
||||
if len(key_list) != 1:
|
||||
msg = "There should be exactly one certificate " \
|
||||
"(ie, public_bytes) in the pem contents."
|
||||
if len(cert_list) < 1:
|
||||
msg = "There should be at least one certificate " \
|
||||
"in the pem contents."
|
||||
LOG.error(msg)
|
||||
raise exception.SysinvException(_(msg))
|
||||
return key_list[0].get('public_bytes')
|
||||
|
||||
# Concatenate all the public bytes together, as the pem contents
|
||||
# may contain intermediate CA certs in it.
|
||||
public_bytes = ''
|
||||
for cert in cert_list:
|
||||
public_bytes += cert.get('public_bytes', '')
|
||||
|
||||
return public_bytes
|
||||
|
||||
@staticmethod
|
||||
def _get_private_bytes_one(key_list):
|
||||
"""Get exactly one private bytes entry from key list"""
|
||||
def _get_private_bytes_one(private_key):
|
||||
"""Get exactly one private bytes entry from private key"""
|
||||
|
||||
if len(key_list) != 1:
|
||||
msg = "There should be exactly one private key " \
|
||||
"(ie, private_bytes) in the pem contents."
|
||||
if not private_key:
|
||||
msg = "No private key found in the pem contents."
|
||||
LOG.error(msg)
|
||||
raise exception.SysinvException(_(msg))
|
||||
return key_list[0].get('private_bytes')
|
||||
return private_key
|
||||
|
||||
@staticmethod
|
||||
def _consolidate_cert_files():
|
||||
|
@ -10486,7 +10495,7 @@ class ConductorManager(service.PeriodicService):
|
|||
|
||||
LOG.info("config_certificate mode=%s" % mode)
|
||||
|
||||
key_list = \
|
||||
cert_list, private_key = \
|
||||
self._extract_keys_from_pem(mode, pem_contents,
|
||||
serialization.PrivateFormat.PKCS8,
|
||||
passphrase)
|
||||
|
@ -10499,8 +10508,8 @@ class ConductorManager(service.PeriodicService):
|
|||
pass
|
||||
|
||||
if mode == constants.CERT_MODE_TPM:
|
||||
private_bytes = self._get_private_bytes_one(key_list)
|
||||
public_bytes = self._get_public_bytes_one(key_list)
|
||||
private_bytes = self._get_private_bytes_one(private_key)
|
||||
public_bytes = self._get_public_bytes(cert_list)
|
||||
self._perform_config_certificate_tpm_mode(
|
||||
context, tpm, private_bytes, public_bytes)
|
||||
|
||||
|
@ -10514,8 +10523,8 @@ class ConductorManager(service.PeriodicService):
|
|||
|
||||
elif mode == constants.CERT_MODE_SSL:
|
||||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
private_bytes = self._get_private_bytes_one(key_list)
|
||||
public_bytes = self._get_public_bytes_one(key_list)
|
||||
private_bytes = self._get_private_bytes_one(private_key)
|
||||
public_bytes = self._get_public_bytes(cert_list)
|
||||
file_content = private_bytes + public_bytes
|
||||
config_dict = {
|
||||
'personalities': personalities,
|
||||
|
@ -10557,23 +10566,23 @@ class ConductorManager(service.PeriodicService):
|
|||
# The list of the actual CA certs as files in FS
|
||||
certs_file = os.listdir(constants.SSL_CERT_CA_LIST_SHARED_DIR)
|
||||
|
||||
# Remove these already installed from the key list
|
||||
key_list_c = key_list[:]
|
||||
for key in key_list_c:
|
||||
if key.get('signature') in certs_inv \
|
||||
and key.get('signature') in certs_file:
|
||||
key_list.remove(key)
|
||||
# Remove these already installed from the cert list
|
||||
cert_list_c = cert_list[:]
|
||||
for cert in cert_list_c:
|
||||
if cert.get('signature') in certs_inv \
|
||||
and cert.get('signature') in certs_file:
|
||||
cert_list.remove(cert)
|
||||
|
||||
# Save certs in files and cat them into ca-cert.pem to apply to the
|
||||
# system.
|
||||
if key_list:
|
||||
if cert_list:
|
||||
# Save each cert in a separate file with signature as its name
|
||||
try:
|
||||
for key in key_list:
|
||||
file_content = key.get('public_bytes')
|
||||
for cert in cert_list:
|
||||
file_content = cert.get('public_bytes')
|
||||
file_name = \
|
||||
os.path.join(constants.SSL_CERT_CA_LIST_SHARED_DIR,
|
||||
key.get('signature'))
|
||||
cert.get('signature'))
|
||||
with os.fdopen(
|
||||
os.open(file_name,
|
||||
os.O_CREAT | os.O_TRUNC | os.O_WRONLY,
|
||||
|
@ -10583,7 +10592,7 @@ class ConductorManager(service.PeriodicService):
|
|||
except Exception as e:
|
||||
msg = "Failed to save cert file: %s" % str(e)
|
||||
LOG.warn(msg)
|
||||
raise exception.SysinvException(_(msg))
|
||||
raise exception.SysinvException(msg)
|
||||
|
||||
# consolidate the CA cert files into ca-cert.pem to update
|
||||
# system CA certs.
|
||||
|
@ -10604,11 +10613,12 @@ class ConductorManager(service.PeriodicService):
|
|||
elif mode == constants.CERT_MODE_DOCKER_REGISTRY:
|
||||
LOG.info("Docker registry certificate install")
|
||||
# docker registry requires a PKCS1 key for the token server
|
||||
key_list_pkcs1 = \
|
||||
_, private_key_pkcs1 = \
|
||||
self._extract_keys_from_pem(mode, pem_contents,
|
||||
serialization.PrivateFormat
|
||||
.TraditionalOpenSSL, passphrase)
|
||||
pkcs1_private_bytes = self._get_private_bytes_one(key_list_pkcs1)
|
||||
pkcs1_private_bytes = \
|
||||
self._get_private_bytes_one(private_key_pkcs1)
|
||||
|
||||
# install certificate, key, and pkcs1 key to controllers
|
||||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
|
@ -10616,8 +10626,8 @@ class ConductorManager(service.PeriodicService):
|
|||
cert_path = constants.DOCKER_REGISTRY_CERT_FILE
|
||||
pkcs1_key_path = constants.DOCKER_REGISTRY_PKCS1_KEY_FILE
|
||||
|
||||
private_bytes = self._get_private_bytes_one(key_list)
|
||||
public_bytes = self._get_public_bytes_one(key_list)
|
||||
private_bytes = self._get_private_bytes_one(private_key)
|
||||
public_bytes = self._get_public_bytes(cert_list)
|
||||
|
||||
config_dict = {
|
||||
'personalities': personalities,
|
||||
|
@ -10677,8 +10687,8 @@ class ConductorManager(service.PeriodicService):
|
|||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
key_path = constants.OPENSTACK_CERT_KEY_FILE
|
||||
cert_path = constants.OPENSTACK_CERT_FILE
|
||||
private_bytes = self._get_private_bytes_one(key_list)
|
||||
public_bytes = self._get_public_bytes_one(key_list)
|
||||
private_bytes = self._get_private_bytes_one(private_key)
|
||||
public_bytes = self._get_public_bytes(cert_list)
|
||||
|
||||
config_dict = {
|
||||
'personalities': personalities,
|
||||
|
@ -10716,9 +10726,7 @@ class ConductorManager(service.PeriodicService):
|
|||
|
||||
elif mode == constants.CERT_MODE_OPENSTACK_CA:
|
||||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
file_content = ''
|
||||
for key in key_list:
|
||||
file_content += key.get('public_bytes', '')
|
||||
file_content = self._get_public_bytes(cert_list)
|
||||
config_dict = {
|
||||
'personalities': personalities,
|
||||
'file_names': [constants.OPENSTACK_CERT_CA_FILE],
|
||||
|
@ -10749,10 +10757,11 @@ class ConductorManager(service.PeriodicService):
|
|||
raise exception.SysinvException(_(msg))
|
||||
|
||||
inv_certs = []
|
||||
for key in key_list:
|
||||
inv_cert = {'signature': key.get('signature'),
|
||||
'not_valid_before': key.get('cert').not_valid_before,
|
||||
'not_valid_after': key.get('cert').not_valid_after}
|
||||
for cert in cert_list:
|
||||
inv_cert = {'signature': cert.get('signature'),
|
||||
'is_ca': cert.get('is_ca'),
|
||||
'not_valid_before': cert.get('cert').not_valid_before,
|
||||
'not_valid_after': cert.get('cert').not_valid_after}
|
||||
inv_certs.append(inv_cert)
|
||||
|
||||
return inv_certs
|
||||
|
@ -10775,7 +10784,7 @@ class ConductorManager(service.PeriodicService):
|
|||
|
||||
LOG.info("_config_selfsigned_certificate mode=%s file=%s" % (mode, certificate_file))
|
||||
|
||||
key_list = \
|
||||
cert_list, private_key = \
|
||||
self._extract_keys_from_pem(mode, pem_contents,
|
||||
serialization.PrivateFormat.PKCS8,
|
||||
passphrase)
|
||||
|
@ -10783,8 +10792,8 @@ class ConductorManager(service.PeriodicService):
|
|||
personalities = [constants.CONTROLLER]
|
||||
|
||||
config_uuid = self._config_update_hosts(context, personalities)
|
||||
private_bytes = self._get_private_bytes_one(key_list)
|
||||
public_bytes = self._get_public_bytes_one(key_list)
|
||||
private_bytes = self._get_private_bytes_one(private_key)
|
||||
public_bytes = self._get_public_bytes(cert_list)
|
||||
file_content = private_bytes + public_bytes
|
||||
config_dict = {
|
||||
'personalities': personalities,
|
||||
|
@ -10802,7 +10811,7 @@ class ConductorManager(service.PeriodicService):
|
|||
'wb') as f:
|
||||
f.write(file_content)
|
||||
|
||||
return key_list[0].get('signature')
|
||||
return cert_list[0].get('signature')
|
||||
|
||||
def delete_certificate(self, context, mode, signature):
|
||||
"""Delete a certificate by its mode and signature.
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAxKPRDBjPM/vnwuKojBwzL0KG7jvdm7XWzbafGR3kM2kXPMQB
|
||||
OtCaIHesVn573VZdfAA1w20p/l2uX+ArQEuqt3qgI1aq1+cPVg0QLkrbeYCQYz/S
|
||||
/wbTIRU4jYXOFEbotvqNrfhOo1thevhSZB+9nmjx/fPv3smhzsEGyzmLunN60zaj
|
||||
9zkBpJJkGtuyczn11qe9yARUvRlSqUjaXUF/DmP7vAGPTpQttD93xoPOb14onC3W
|
||||
K8DC5kCpCHbhYNNNWq+KYjsvmdd6/ZzIw9rHTjXuj39nyp80rqk/jFknJWASt/Qu
|
||||
q18Fkm/i4BB5QocSJ0dnV2GvA7W48n84+INhEQIDAQABAoIBADhDp00OzDrTmTzq
|
||||
Hc/5QawEHReNiZtELHIwDtXg96q+Jyf77V4m0fL4Sxd0mXx7ecRBSyDf22Qs6fgE
|
||||
7Fs5S1+0dp2l7rxYIMs+caLNSH87ihTb7kOKcF7G86eK4axrnaq9hkyA//895maJ
|
||||
Jwn/CwKIhLVlVv0oNGQ0Vv1POevfHlbP+KSK8dDRgkStfP+mM3T9yyWttr37RHmv
|
||||
uvg+R0tL9eZetc8QvEmCy3WnCslfJ9g3NxBjKgxWyQIw99w0IDtQv+uPtNHOvM4w
|
||||
08zNW//foV0QvhhHbejrjyTTp2LVQ97wOz0S5GfnbmwsfYQagaP735DXzoTWC1mm
|
||||
SWESkAECgYEA7+Chlop04bf+xLxAPE49tca1+I8ESu4FsEvHs1k1/58BlopGOqiD
|
||||
/Uf/N0aySNmzv+/CU3klsmnpTZYmY/Su+ELjhY9GC1KLFghHBRVU+cIX53VYY7ca
|
||||
q69FjxcA8BZjTdYe5hPTHbiWXvzUYOK22XjaI6Hm03atdcd6oW6hUtkCgYEA0ds7
|
||||
uNSwmP4Bc2FzP1uMlxAlUWhHS513NG1keXk3MKtofrgA1/Sb1FLs9lYQbHWjnvZD
|
||||
HF5e2opPM8nExqKV9vUNnObW/kBClX3i189Fdt5OgJgoZH/Imc/cXvqMeLepPL4s
|
||||
TFeScDjsbqaUpUDnu8KOatpLP6M/9aEqjrNwrPkCgYEAoKy8T9PqOo8+TZUzCbH2
|
||||
z92MYjOZ0n7gvJfl6hIlg1WEgMuaAwyBbJRfNS1bmkSIjFYSukr5nyomJdwfVvC8
|
||||
inpzYDD53/eoRlfBCnyhcLI7xMPrMs+hQ8KhOxlTfX3hgm+cPsykqtHLl1CPCV6S
|
||||
z9SNeTSnIpnp0myNjbhGwvECgYAJL9TEeaMlf3Em0OxPqL1V26IWlz8Pw1v1kphk
|
||||
bPcKjWZsrbdzvMSZneu7uPbNGLVJ/zPe6Q6z+HwRI1MW8wUno4CuDrj4tm1zx+gH
|
||||
VI6Q7ph3LrIN/D4W5a+bBNLjcf7ZpuWfjfHeMc+/5FD7jwTWBmVfriC/L3FcWmrX
|
||||
hml3WQKBgGUH5mJIVEbxxe6HaMXlJ6T+Z6Vtx98Q5DC2NvukGiH35WCB/itwy8Se
|
||||
UGZ9t+gXvSIyktQcQHDHKOIHdQvWPSLCN2jBWhRN8LtxTP1HaBRn6QX99PQ/K7AF
|
||||
V9O/MHuLI0Ph1brfvSlPTjxXwtqHLZe3dUlfXkaiBWYwFFgrAk0C
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC2jCCAcKgAwIBAgIRAJx+0xv3wyTCGC/hqxY6aMYwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEAwwHcm9vdF9jYTAeFw0yMDA2MjUxNTEwMDBaFw0yMTA2MjUxNTEw
|
||||
MDBaMBoxGDAWBgNVBAMMD2ludGVybWVkaWF0ZV9jYTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMk0swFLA2iI4MI6QWyi6K3QzPSVUNIw8UHtSi6U3O5s
|
||||
q750DY2NLfBJwKpROjqwKbG7lwcYG3qDKFK3E1YR5H4q66WT+8J6DyP5poouOwvP
|
||||
Gn9GYqb+nGbePyL/woFPFmaXGUZpTQTUn5UwyNFX9APkoGqJR0RpW5o5E1Hhx2Nn
|
||||
8DEzuUc4r45YCChK0NaeW2EobNhGWsNxOypBcXSDwj+zXNdxoToR7By6uScPdO1l
|
||||
qNetjGq+RCUCYj70+oYDwiIPetF/kkj0rjLO2GxVvLJMAYDO5lBwQRfaIMJF2wNB
|
||||
yHecVJHAq5CZLHbkIqnilRiPQaJWdTuqn5YPGUzRejECAwEAAaMjMCEwDgYDVR0P
|
||||
AQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEbA
|
||||
gaZW06bMjPMKyZ0tRDryQ5ctdRBTOs1SQtu/24DUsKU7wkX9Is06v45RpLlVoSG8
|
||||
vRz9mLxDOf7T21aKgVs58lq4FAdi+zVfba5vs9e3WLKpvj/C3fSN3KROSEXRxbHR
|
||||
bBeBZYD+xjKvKd0Zvkyaqg6JdwhUWwdegbAZkD/LDRIuktmO4kUXJtsN5TPp2GTJ
|
||||
H/Hw9zu36kGXBxXN+l/KVkqgltENlw/pvlDNKa4IPER3uNOLcJgXvBVCLs80haq2
|
||||
ZQaESInzOXjaN3P93H6Qw+ob+7+/s6h6qEuTl5X/awjeEYCcufBUzpAi42wFL/Nk
|
||||
DA0ylFDBpdwidpPo2hQ=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFzCCAf+gAwIBAgIQNr/QDnePc/YH4DjC6I0osjANBgkqhkiG9w0BAQsFADAa
|
||||
MRgwFgYDVQQDDA9pbnRlcm1lZGlhdGVfY2EwHhcNMjAwNjI1MTgwMjQyWhcNMjAx
|
||||
MjIyMTgwMjQyWjAaMRgwFgYDVQQDEw8xMjguMjI0LjE1MS4yNDMwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEo9EMGM8z++fC4qiMHDMvQobuO92btdbN
|
||||
tp8ZHeQzaRc8xAE60Jogd6xWfnvdVl18ADXDbSn+Xa5f4CtAS6q3eqAjVqrX5w9W
|
||||
DRAuStt5gJBjP9L/BtMhFTiNhc4URui2+o2t+E6jW2F6+FJkH72eaPH98+/eyaHO
|
||||
wQbLOYu6c3rTNqP3OQGkkmQa27JzOfXWp73IBFS9GVKpSNpdQX8OY/u8AY9OlC20
|
||||
P3fGg85vXiicLdYrwMLmQKkIduFg001ar4piOy+Z13r9nMjD2sdONe6Pf2fKnzSu
|
||||
qT+MWSclYBK39C6rXwWSb+LgEHlChxInR2dXYa8Dtbjyfzj4g2ERAgMBAAGjWTBX
|
||||
MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMDcGA1UdEQQwMC6CDnJlZ2lz
|
||||
dHJ5LmxvY2FsghByZWdpc3RyeS5jZW50cmFshwTAqMwBhwSA4JfzMA0GCSqGSIb3
|
||||
DQEBCwUAA4IBAQC4GwZR1hg6NHOcRRhpoDaqTrMl1wtUCb//b2tr3h/vyw319hiW
|
||||
yVdgQNob9D+VdRo9moX2bOCiMbXHUaabk0fFxPXwaGVkotC/RDLQS+Hol60kdTNu
|
||||
Ph1TBsuszu9qZyEp+9qyqyOXpiIlpN8RehOuc8L3qUoix/eb9EqvYS9/L27YXkne
|
||||
qVisVfbnsPivyU9mm/fERvgdrTua2Fi3JvdyJOr4HNO7T8SCGPOnWg+sz4+35CCS
|
||||
HFK/FNoFnfDgeCj0sHl3Sv2/nZDSG+N98zUaqNTrkXLeUREiaEf9cO0FLEoNBo2R
|
||||
nJl8zUCPJ8OzOMRD7/fTuOTtmOcWzlFHuTzJ
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,64 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAxKPRDBjPM/vnwuKojBwzL0KG7jvdm7XWzbafGR3kM2kXPMQB
|
||||
OtCaIHesVn573VZdfAA1w20p/l2uX+ArQEuqt3qgI1aq1+cPVg0QLkrbeYCQYz/S
|
||||
/wbTIRU4jYXOFEbotvqNrfhOo1thevhSZB+9nmjx/fPv3smhzsEGyzmLunN60zaj
|
||||
9zkBpJJkGtuyczn11qe9yARUvRlSqUjaXUF/DmP7vAGPTpQttD93xoPOb14onC3W
|
||||
K8DC5kCpCHbhYNNNWq+KYjsvmdd6/ZzIw9rHTjXuj39nyp80rqk/jFknJWASt/Qu
|
||||
q18Fkm/i4BB5QocSJ0dnV2GvA7W48n84+INhEQIDAQABAoIBADhDp00OzDrTmTzq
|
||||
Hc/5QawEHReNiZtELHIwDtXg96q+Jyf77V4m0fL4Sxd0mXx7ecRBSyDf22Qs6fgE
|
||||
7Fs5S1+0dp2l7rxYIMs+caLNSH87ihTb7kOKcF7G86eK4axrnaq9hkyA//895maJ
|
||||
Jwn/CwKIhLVlVv0oNGQ0Vv1POevfHlbP+KSK8dDRgkStfP+mM3T9yyWttr37RHmv
|
||||
uvg+R0tL9eZetc8QvEmCy3WnCslfJ9g3NxBjKgxWyQIw99w0IDtQv+uPtNHOvM4w
|
||||
08zNW//foV0QvhhHbejrjyTTp2LVQ97wOz0S5GfnbmwsfYQagaP735DXzoTWC1mm
|
||||
SWESkAECgYEA7+Chlop04bf+xLxAPE49tca1+I8ESu4FsEvHs1k1/58BlopGOqiD
|
||||
/Uf/N0aySNmzv+/CU3klsmnpTZYmY/Su+ELjhY9GC1KLFghHBRVU+cIX53VYY7ca
|
||||
q69FjxcA8BZjTdYe5hPTHbiWXvzUYOK22XjaI6Hm03atdcd6oW6hUtkCgYEA0ds7
|
||||
uNSwmP4Bc2FzP1uMlxAlUWhHS513NG1keXk3MKtofrgA1/Sb1FLs9lYQbHWjnvZD
|
||||
HF5e2opPM8nExqKV9vUNnObW/kBClX3i189Fdt5OgJgoZH/Imc/cXvqMeLepPL4s
|
||||
TFeScDjsbqaUpUDnu8KOatpLP6M/9aEqjrNwrPkCgYEAoKy8T9PqOo8+TZUzCbH2
|
||||
z92MYjOZ0n7gvJfl6hIlg1WEgMuaAwyBbJRfNS1bmkSIjFYSukr5nyomJdwfVvC8
|
||||
inpzYDD53/eoRlfBCnyhcLI7xMPrMs+hQ8KhOxlTfX3hgm+cPsykqtHLl1CPCV6S
|
||||
z9SNeTSnIpnp0myNjbhGwvECgYAJL9TEeaMlf3Em0OxPqL1V26IWlz8Pw1v1kphk
|
||||
bPcKjWZsrbdzvMSZneu7uPbNGLVJ/zPe6Q6z+HwRI1MW8wUno4CuDrj4tm1zx+gH
|
||||
VI6Q7ph3LrIN/D4W5a+bBNLjcf7ZpuWfjfHeMc+/5FD7jwTWBmVfriC/L3FcWmrX
|
||||
hml3WQKBgGUH5mJIVEbxxe6HaMXlJ6T+Z6Vtx98Q5DC2NvukGiH35WCB/itwy8Se
|
||||
UGZ9t+gXvSIyktQcQHDHKOIHdQvWPSLCN2jBWhRN8LtxTP1HaBRn6QX99PQ/K7AF
|
||||
V9O/MHuLI0Ph1brfvSlPTjxXwtqHLZe3dUlfXkaiBWYwFFgrAk0C
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFzCCAf+gAwIBAgIQNr/QDnePc/YH4DjC6I0osjANBgkqhkiG9w0BAQsFADAa
|
||||
MRgwFgYDVQQDDA9pbnRlcm1lZGlhdGVfY2EwHhcNMjAwNjI1MTgwMjQyWhcNMjAx
|
||||
MjIyMTgwMjQyWjAaMRgwFgYDVQQDEw8xMjguMjI0LjE1MS4yNDMwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEo9EMGM8z++fC4qiMHDMvQobuO92btdbN
|
||||
tp8ZHeQzaRc8xAE60Jogd6xWfnvdVl18ADXDbSn+Xa5f4CtAS6q3eqAjVqrX5w9W
|
||||
DRAuStt5gJBjP9L/BtMhFTiNhc4URui2+o2t+E6jW2F6+FJkH72eaPH98+/eyaHO
|
||||
wQbLOYu6c3rTNqP3OQGkkmQa27JzOfXWp73IBFS9GVKpSNpdQX8OY/u8AY9OlC20
|
||||
P3fGg85vXiicLdYrwMLmQKkIduFg001ar4piOy+Z13r9nMjD2sdONe6Pf2fKnzSu
|
||||
qT+MWSclYBK39C6rXwWSb+LgEHlChxInR2dXYa8Dtbjyfzj4g2ERAgMBAAGjWTBX
|
||||
MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMDcGA1UdEQQwMC6CDnJlZ2lz
|
||||
dHJ5LmxvY2FsghByZWdpc3RyeS5jZW50cmFshwTAqMwBhwSA4JfzMA0GCSqGSIb3
|
||||
DQEBCwUAA4IBAQC4GwZR1hg6NHOcRRhpoDaqTrMl1wtUCb//b2tr3h/vyw319hiW
|
||||
yVdgQNob9D+VdRo9moX2bOCiMbXHUaabk0fFxPXwaGVkotC/RDLQS+Hol60kdTNu
|
||||
Ph1TBsuszu9qZyEp+9qyqyOXpiIlpN8RehOuc8L3qUoix/eb9EqvYS9/L27YXkne
|
||||
qVisVfbnsPivyU9mm/fERvgdrTua2Fi3JvdyJOr4HNO7T8SCGPOnWg+sz4+35CCS
|
||||
HFK/FNoFnfDgeCj0sHl3Sv2/nZDSG+N98zUaqNTrkXLeUREiaEf9cO0FLEoNBo2R
|
||||
nJl8zUCPJ8OzOMRD7/fTuOTtmOcWzlFHuTzJ
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC2jCCAcKgAwIBAgIRAJx+0xv3wyTCGC/hqxY6aMYwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEAwwHcm9vdF9jYTAeFw0yMDA2MjUxNTEwMDBaFw0yMTA2MjUxNTEw
|
||||
MDBaMBoxGDAWBgNVBAMMD2ludGVybWVkaWF0ZV9jYTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMk0swFLA2iI4MI6QWyi6K3QzPSVUNIw8UHtSi6U3O5s
|
||||
q750DY2NLfBJwKpROjqwKbG7lwcYG3qDKFK3E1YR5H4q66WT+8J6DyP5poouOwvP
|
||||
Gn9GYqb+nGbePyL/woFPFmaXGUZpTQTUn5UwyNFX9APkoGqJR0RpW5o5E1Hhx2Nn
|
||||
8DEzuUc4r45YCChK0NaeW2EobNhGWsNxOypBcXSDwj+zXNdxoToR7By6uScPdO1l
|
||||
qNetjGq+RCUCYj70+oYDwiIPetF/kkj0rjLO2GxVvLJMAYDO5lBwQRfaIMJF2wNB
|
||||
yHecVJHAq5CZLHbkIqnilRiPQaJWdTuqn5YPGUzRejECAwEAAaMjMCEwDgYDVR0P
|
||||
AQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEbA
|
||||
gaZW06bMjPMKyZ0tRDryQ5ctdRBTOs1SQtu/24DUsKU7wkX9Is06v45RpLlVoSG8
|
||||
vRz9mLxDOf7T21aKgVs58lq4FAdi+zVfba5vs9e3WLKpvj/C3fSN3KROSEXRxbHR
|
||||
bBeBZYD+xjKvKd0Zvkyaqg6JdwhUWwdegbAZkD/LDRIuktmO4kUXJtsN5TPp2GTJ
|
||||
H/Hw9zu36kGXBxXN+l/KVkqgltENlw/pvlDNKa4IPER3uNOLcJgXvBVCLs80haq2
|
||||
ZQaESInzOXjaN3P93H6Qw+ob+7+/s6h6qEuTl5X/awjeEYCcufBUzpAi42wFL/Nk
|
||||
DA0ylFDBpdwidpPo2hQ=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,63 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAkKELpZl5mPAgALbxnL7ywdlCUp8TpGJklozGkTcDaDJ3umOS
|
||||
S8Eu0lQJmTRb8FUaYXAgi5BtTj1rx9Z7HyxbZa58cMB842ZrmXhX0rzNReTdGLhr
|
||||
hJxmd7UBLcw9CGtHSUkwlsjQzWxAlDXLp9t+vj1pScJQEumxNftqIWYIuX5Ck67X
|
||||
Q0SSq4zdqdNhaGwCxWkQvDwIoUVX6nYwtFfxPju4WhjnG14AubNlxCU47DK7l6Bc
|
||||
147cywhu0hCFGGkpBjROoD3JDR0L4hwkvzH/2uMe9zfL1MV13JV6cK/FeCuhc/O2
|
||||
S3SzI1FY5H8I013rvyBwYU0zNtpQ86l1OzhLuwIDAQABAoIBAC2c7OxsS+JFEQLI
|
||||
r8isnCkw2O7vxqUYdvrYKSPRQtzQ1dvN3WzQ33BsGp7b2Ychf/FtCIabpS2Ax4Y+
|
||||
CZSaS7T048A3pOue+J5tSt1muCKr/GL4fshS/yoPxvBnsnP+SXw+ffmAGgI/etqD
|
||||
YNhurDlZauRdSR294CrTQPSJloTRaNSyfr71HfcZ5tmDKvz9/2W3Tz1e+Gsyid57
|
||||
HzgQPaPxAnupZkLvQEMEVbGhg/ywhVax+XbNV/vhkIgwUcNmsmxjj23rhR5lrnRm
|
||||
10/BsEVVGCwSsjeQQEDh9YidfyoCFnCHR8IHWXZaeAGj2Jiv8sds4Q9DUbkov80U
|
||||
iDJUVfkCgYEAwMK6Qa6jX7ATCFQHmgaDtr1USu8Vjro672UphZGaA3Yv3wPz4FME
|
||||
DLnr/rgB2QBN3dwPUkWVwOZyiwEBCI/6fUVNmEf9iuzBrCNf+AWrGx0p+ySdHn6l
|
||||
lpUKYJaYTNa2nyIJD2a8VQONaaCdm3ZL1KIF8uRkjGO5he2BjoQdVDUCgYEAwBPr
|
||||
vESVJhk3MuqVzuLeEu/iFBuS7Y7eDeTxJFPVR5Anag4ZNiQyhuo7mKo6BT5D1t5K
|
||||
zM41BW9SxEX4j6XEsRc3pIc0rIiVxj+BaHpyUg6Y5/Xkh4g02xdo76JkkAI2BbGT
|
||||
J+L8H63Xsp+ZNzTo0+d9cic7c0HTW7Ds/c3NPi8CgYBOkdDLnvx2r1VCqsWicY9U
|
||||
eB2YoZU+5QfKtohTKkMFsDHZDEpmoE/hRBM+cxBFvEsA6IbSOQzOYOBFanZaYB1w
|
||||
3EPBk250JwbWPGEMvnq9BYksFgN4/5RNKZjeP+P6RfaQLJZW0cBoQpdse4xiZriI
|
||||
Bja4h4G4e5mOTn3lclJmFQKBgGXkq3NONojla4DZLOt5MjF9i8L69bCLz4QzZTDO
|
||||
QCAceqwqGnm8LgmgDElqVCkf5MEBX1DSOxJNAe0Y6UjauULwfBYNm4XDVyC5455X
|
||||
Bno9QCQdL0Qun0tyWbp1vT8fzSSsFNJd+T2c7QXW4GKG8NQow0VhRopX6xWC/9WL
|
||||
7UsFAoGAY8agTn3py7aNgK05rW3m/yQ7418nEWT2DxIMc97EAVsXyyEXkLeqiqfB
|
||||
rUwWqyeLrUVNLa/E1PuK+KEqQQUNuj/Rczo8Y2qSi4GIl5HAocz72jdfCk9L+2NM
|
||||
/V5umqflAPn0m4Le/qZXP6AsW792HW4oeAiQEsD1xW15kPa0c1Q=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC2jCCAcKgAwIBAgIRAJx+0xv3wyTCGC/hqxY6aMYwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEAwwHcm9vdF9jYTAeFw0yMDA2MjUxNTEwMDBaFw0yMTA2MjUxNTEw
|
||||
MDBaMBoxGDAWBgNVBAMMD2ludGVybWVkaWF0ZV9jYTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMk0swFLA2iI4MI6QWyi6K3QzPSVUNIw8UHtSi6U3O5s
|
||||
q750DY2NLfBJwKpROjqwKbG7lwcYG3qDKFK3E1YR5H4q66WT+8J6DyP5poouOwvP
|
||||
Gn9GYqb+nGbePyL/woFPFmaXGUZpTQTUn5UwyNFX9APkoGqJR0RpW5o5E1Hhx2Nn
|
||||
8DEzuUc4r45YCChK0NaeW2EobNhGWsNxOypBcXSDwj+zXNdxoToR7By6uScPdO1l
|
||||
qNetjGq+RCUCYj70+oYDwiIPetF/kkj0rjLO2GxVvLJMAYDO5lBwQRfaIMJF2wNB
|
||||
yHecVJHAq5CZLHbkIqnilRiPQaJWdTuqn5YPGUzRejECAwEAAaMjMCEwDgYDVR0P
|
||||
AQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEbA
|
||||
gaZW06bMjPMKyZ0tRDryQ5ctdRBTOs1SQtu/24DUsKU7wkX9Is06v45RpLlVoSG8
|
||||
vRz9mLxDOf7T21aKgVs58lq4FAdi+zVfba5vs9e3WLKpvj/C3fSN3KROSEXRxbHR
|
||||
bBeBZYD+xjKvKd0Zvkyaqg6JdwhUWwdegbAZkD/LDRIuktmO4kUXJtsN5TPp2GTJ
|
||||
H/Hw9zu36kGXBxXN+l/KVkqgltENlw/pvlDNKa4IPER3uNOLcJgXvBVCLs80haq2
|
||||
ZQaESInzOXjaN3P93H6Qw+ob+7+/s6h6qEuTl5X/awjeEYCcufBUzpAi42wFL/Nk
|
||||
DA0ylFDBpdwidpPo2hQ=
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC3jCCAcagAwIBAgIQWzdMuPwZZbFPButb9XkiazANBgkqhkiG9w0BAQsFADAa
|
||||
MRgwFgYDVQQDDA9pbnRlcm1lZGlhdGVfY2EwHhcNMjAwNjI1MTUxMDAxWhcNMjAx
|
||||
MjIyMTUxMDAxWjAaMRgwFgYDVQQDEw8xMjguMjI0LjE1MS4yNDMwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQoQulmXmY8CAAtvGcvvLB2UJSnxOkYmSW
|
||||
jMaRNwNoMne6Y5JLwS7SVAmZNFvwVRphcCCLkG1OPWvH1nsfLFtlrnxwwHzjZmuZ
|
||||
eFfSvM1F5N0YuGuEnGZ3tQEtzD0Ia0dJSTCWyNDNbECUNcun236+PWlJwlAS6bE1
|
||||
+2ohZgi5fkKTrtdDRJKrjN2p02FobALFaRC8PAihRVfqdjC0V/E+O7haGOcbXgC5
|
||||
s2XEJTjsMruXoFzXjtzLCG7SEIUYaSkGNE6gPckNHQviHCS/Mf/a4x73N8vUxXXc
|
||||
lXpwr8V4K6Fz87ZLdLMjUVjkfwjTXeu/IHBhTTM22lDzqXU7OEu7AgMBAAGjIDAe
|
||||
MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQBu0Uzfpw/pX5IgkKMW+Dq3cUWr/tyJen9BLQQ0ryH6AqBSdjOt0Dfof/S9RyBQ
|
||||
Pj1xPCMRjGz8qcQYRUPg6pgnq/k3kNIgbZf4V+p+9y/bWsEICwinyWDFWH260MIA
|
||||
Kckeq6Jf3gLWCrPzZ4hASVMcS+0YA4BaxS/EuX0lRn4O2sf2fMb1VKdPqDmWg/Se
|
||||
IOm6fKO6zQmnvTFKOPwHUX0ZgUiTEEDqzgeeVcmZhM8ZBb8IQbZIwtvgOOeAg98B
|
||||
tQcpipGjv4Oq1FsoQ395qasf562ZittlaX7NLbMQef8KiiuYieXYAMqQID+hf3sH
|
||||
DQih77e2tY88orfCKunGt++R
|
||||
-----END CERTIFICATE-----
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,63 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAkKELpZl5mPAgALbxnL7ywdlCUp8TpGJklozGkTcDaDJ3umOS
|
||||
S8Eu0lQJmTRb8FUaYXAgi5BtTj1rx9Z7HyxbZa58cMB842ZrmXhX0rzNReTdGLhr
|
||||
hJxmd7UBLcw9CGtHSUkwlsjQzWxAlDXLp9t+vj1pScJQEumxNftqIWYIuX5Ck67X
|
||||
Q0SSq4zdqdNhaGwCxWkQvDwIoUVX6nYwtFfxPju4WhjnG14AubNlxCU47DK7l6Bc
|
||||
147cywhu0hCFGGkpBjROoD3JDR0L4hwkvzH/2uMe9zfL1MV13JV6cK/FeCuhc/O2
|
||||
S3SzI1FY5H8I013rvyBwYU0zNtpQ86l1OzhLuwIDAQABAoIBAC2c7OxsS+JFEQLI
|
||||
r8isnCkw2O7vxqUYdvrYKSPRQtzQ1dvN3WzQ33BsGp7b2Ychf/FtCIabpS2Ax4Y+
|
||||
CZSaS7T048A3pOue+J5tSt1muCKr/GL4fshS/yoPxvBnsnP+SXw+ffmAGgI/etqD
|
||||
YNhurDlZauRdSR294CrTQPSJloTRaNSyfr71HfcZ5tmDKvz9/2W3Tz1e+Gsyid57
|
||||
HzgQPaPxAnupZkLvQEMEVbGhg/ywhVax+XbNV/vhkIgwUcNmsmxjj23rhR5lrnRm
|
||||
10/BsEVVGCwSsjeQQEDh9YidfyoCFnCHR8IHWXZaeAGj2Jiv8sds4Q9DUbkov80U
|
||||
iDJUVfkCgYEAwMK6Qa6jX7ATCFQHmgaDtr1USu8Vjro672UphZGaA3Yv3wPz4FME
|
||||
DLnr/rgB2QBN3dwPUkWVwOZyiwEBCI/6fUVNmEf9iuzBrCNf+AWrGx0p+ySdHn6l
|
||||
lpUKYJaYTNa2nyIJD2a8VQONaaCdm3ZL1KIF8uRkjGO5he2BjoQdVDUCgYEAwBPr
|
||||
vESVJhk3MuqVzuLeEu/iFBuS7Y7eDeTxJFPVR5Anag4ZNiQyhuo7mKo6BT5D1t5K
|
||||
zM41BW9SxEX4j6XEsRc3pIc0rIiVxj+BaHpyUg6Y5/Xkh4g02xdo76JkkAI2BbGT
|
||||
J+L8H63Xsp+ZNzTo0+d9cic7c0HTW7Ds/c3NPi8CgYBOkdDLnvx2r1VCqsWicY9U
|
||||
eB2YoZU+5QfKtohTKkMFsDHZDEpmoE/hRBM+cxBFvEsA6IbSOQzOYOBFanZaYB1w
|
||||
3EPBk250JwbWPGEMvnq9BYksFgN4/5RNKZjeP+P6RfaQLJZW0cBoQpdse4xiZriI
|
||||
Bja4h4G4e5mOTn3lclJmFQKBgGXkq3NONojla4DZLOt5MjF9i8L69bCLz4QzZTDO
|
||||
QCAceqwqGnm8LgmgDElqVCkf5MEBX1DSOxJNAe0Y6UjauULwfBYNm4XDVyC5455X
|
||||
Bno9QCQdL0Qun0tyWbp1vT8fzSSsFNJd+T2c7QXW4GKG8NQow0VhRopX6xWC/9WL
|
||||
7UsFAoGAY8agTn3py7aNgK05rW3m/yQ7418nEWT2DxIMc97EAVsXyyEXkLeqiqfB
|
||||
rUwWqyeLrUVNLa/E1PuK+KEqQQUNuj/Rczo8Y2qSi4GIl5HAocz72jdfCk9L+2NM
|
||||
/V5umqflAPn0m4Le/qZXP6AsW792HW4oeAiQEsD1xW15kPa0c1Q=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC3jCCAcagAwIBAgIQWzdMuPwZZbFPButb9XkiazANBgkqhkiG9w0BAQsFADAa
|
||||
MRgwFgYDVQQDDA9pbnRlcm1lZGlhdGVfY2EwHhcNMjAwNjI1MTUxMDAxWhcNMjAx
|
||||
MjIyMTUxMDAxWjAaMRgwFgYDVQQDEw8xMjguMjI0LjE1MS4yNDMwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQoQulmXmY8CAAtvGcvvLB2UJSnxOkYmSW
|
||||
jMaRNwNoMne6Y5JLwS7SVAmZNFvwVRphcCCLkG1OPWvH1nsfLFtlrnxwwHzjZmuZ
|
||||
eFfSvM1F5N0YuGuEnGZ3tQEtzD0Ia0dJSTCWyNDNbECUNcun236+PWlJwlAS6bE1
|
||||
+2ohZgi5fkKTrtdDRJKrjN2p02FobALFaRC8PAihRVfqdjC0V/E+O7haGOcbXgC5
|
||||
s2XEJTjsMruXoFzXjtzLCG7SEIUYaSkGNE6gPckNHQviHCS/Mf/a4x73N8vUxXXc
|
||||
lXpwr8V4K6Fz87ZLdLMjUVjkfwjTXeu/IHBhTTM22lDzqXU7OEu7AgMBAAGjIDAe
|
||||
MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQBu0Uzfpw/pX5IgkKMW+Dq3cUWr/tyJen9BLQQ0ryH6AqBSdjOt0Dfof/S9RyBQ
|
||||
Pj1xPCMRjGz8qcQYRUPg6pgnq/k3kNIgbZf4V+p+9y/bWsEICwinyWDFWH260MIA
|
||||
Kckeq6Jf3gLWCrPzZ4hASVMcS+0YA4BaxS/EuX0lRn4O2sf2fMb1VKdPqDmWg/Se
|
||||
IOm6fKO6zQmnvTFKOPwHUX0ZgUiTEEDqzgeeVcmZhM8ZBb8IQbZIwtvgOOeAg98B
|
||||
tQcpipGjv4Oq1FsoQ395qasf562ZittlaX7NLbMQef8KiiuYieXYAMqQID+hf3sH
|
||||
DQih77e2tY88orfCKunGt++R
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC2jCCAcKgAwIBAgIRAJx+0xv3wyTCGC/hqxY6aMYwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEAwwHcm9vdF9jYTAeFw0yMDA2MjUxNTEwMDBaFw0yMTA2MjUxNTEw
|
||||
MDBaMBoxGDAWBgNVBAMMD2ludGVybWVkaWF0ZV9jYTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMk0swFLA2iI4MI6QWyi6K3QzPSVUNIw8UHtSi6U3O5s
|
||||
q750DY2NLfBJwKpROjqwKbG7lwcYG3qDKFK3E1YR5H4q66WT+8J6DyP5poouOwvP
|
||||
Gn9GYqb+nGbePyL/woFPFmaXGUZpTQTUn5UwyNFX9APkoGqJR0RpW5o5E1Hhx2Nn
|
||||
8DEzuUc4r45YCChK0NaeW2EobNhGWsNxOypBcXSDwj+zXNdxoToR7By6uScPdO1l
|
||||
qNetjGq+RCUCYj70+oYDwiIPetF/kkj0rjLO2GxVvLJMAYDO5lBwQRfaIMJF2wNB
|
||||
yHecVJHAq5CZLHbkIqnilRiPQaJWdTuqn5YPGUzRejECAwEAAaMjMCEwDgYDVR0P
|
||||
AQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEbA
|
||||
gaZW06bMjPMKyZ0tRDryQ5ctdRBTOs1SQtu/24DUsKU7wkX9Is06v45RpLlVoSG8
|
||||
vRz9mLxDOf7T21aKgVs58lq4FAdi+zVfba5vs9e3WLKpvj/C3fSN3KROSEXRxbHR
|
||||
bBeBZYD+xjKvKd0Zvkyaqg6JdwhUWwdegbAZkD/LDRIuktmO4kUXJtsN5TPp2GTJ
|
||||
H/Hw9zu36kGXBxXN+l/KVkqgltENlw/pvlDNKa4IPER3uNOLcJgXvBVCLs80haq2
|
||||
ZQaESInzOXjaN3P93H6Qw+ob+7+/s6h6qEuTl5X/awjeEYCcufBUzpAi42wFL/Nk
|
||||
DA0ylFDBpdwidpPo2hQ=
|
||||
-----END CERTIFICATE-----
|
|
@ -216,7 +216,7 @@ class ApiCertificateTestCaseMixin(object):
|
|||
cert = x509.load_pem_x509_certificate(pem_contents[index::],
|
||||
default_backend())
|
||||
certs.append(cert)
|
||||
start = start + index + len(marker)
|
||||
start = index + len(marker)
|
||||
return certs
|
||||
|
||||
@staticmethod
|
||||
|
@ -351,6 +351,169 @@ class ApiCertificatePostTestSuite(ApiCertificateTestCaseMixin,
|
|||
found_match = True
|
||||
self.assertTrue(found_match)
|
||||
|
||||
# Test successful POST operation to install ssl certificate signed by
|
||||
# intermediate CA
|
||||
def test_install_2xcert_1xkey_ssl_certificate(self):
|
||||
mode = 'ssl'
|
||||
certfile = os.path.join(os.path.dirname(__file__), "data",
|
||||
'ssl-cert-2xcert-1xkey-with-key.pem')
|
||||
|
||||
in_certs = self.extract_certs_from_pem_file(certfile)
|
||||
fake_config_certificate_return = []
|
||||
for index, in_cert in enumerate(in_certs):
|
||||
is_ca = False if index == 0 else True
|
||||
fake_config_certificate_return.append(
|
||||
{'signature': self.get_cert_signature(mode, in_cert),
|
||||
'not_valid_before': in_cert.not_valid_before,
|
||||
'not_valid_after': in_cert.not_valid_after,
|
||||
'is_ca': is_ca})
|
||||
self.fake_conductor_api.\
|
||||
setup_config_certificate(fake_config_certificate_return)
|
||||
|
||||
data = {'mode': mode}
|
||||
files = [('file', certfile)]
|
||||
response = self.post_with_files('%s/%s' % (self.API_PREFIX, 'certificate_install'),
|
||||
data,
|
||||
upload_files=files,
|
||||
headers=self.API_HEADERS,
|
||||
expect_errors=False)
|
||||
|
||||
self.assertEqual(response.status_code, http_client.OK)
|
||||
resp = json.loads(response.body)
|
||||
self.assertIn('certificates', resp)
|
||||
ret_certs = resp.get('certificates')
|
||||
|
||||
# The installed cert contains the server cert and the intermediate
|
||||
# CA cert but the API returns only the server cert, which should match
|
||||
# the server cert in the cert file (the first one).
|
||||
self.assertEqual(len(ret_certs), 1)
|
||||
ret_cert = ret_certs[0]
|
||||
in_cert = in_certs[0]
|
||||
|
||||
self.assertIn('certtype', ret_cert)
|
||||
self.assertEqual(ret_cert.get('certtype'), mode)
|
||||
self.assertIn('signature', ret_cert)
|
||||
self.assertIn('start_date', ret_cert)
|
||||
self.assertIn('expiry_date', ret_cert)
|
||||
|
||||
ret_cert_start_date = str(ret_cert.get('start_date'))
|
||||
ret_cert_start_date = ret_cert_start_date.replace('+00:00', '')
|
||||
ret_cert_expiry_date = str(ret_cert.get('expiry_date'))
|
||||
ret_cert_expiry_date = ret_cert_expiry_date.replace('+00:00', '')
|
||||
found_match = False
|
||||
if ret_cert.get('signature') == \
|
||||
self.get_cert_signature(mode, in_cert) and \
|
||||
ret_cert_start_date == \
|
||||
str(in_cert.not_valid_before) and \
|
||||
ret_cert_expiry_date == \
|
||||
str(in_cert.not_valid_after):
|
||||
found_match = True
|
||||
self.assertTrue(found_match)
|
||||
|
||||
# Test POST operation to install ssl certificate signed by intermediate CA,
|
||||
# but the server cert and intermediate cert in the file is in wrong order.
|
||||
def test_install_2xcert_1xkey_ssl_certificate_wrong_order(self):
|
||||
mode = 'ssl'
|
||||
certfile = os.path.join(os.path.dirname(__file__), "data",
|
||||
'ssl-cert-2xcert-1xkey-with-key-wrong-order.pem')
|
||||
|
||||
data = {'mode': mode}
|
||||
files = [('file', certfile)]
|
||||
response = self.post_with_files('%s/%s' % (self.API_PREFIX, 'certificate_install'),
|
||||
data,
|
||||
upload_files=files,
|
||||
headers=self.API_HEADERS,
|
||||
expect_errors=True)
|
||||
|
||||
self.assertTrue(response.body)
|
||||
resp = json.loads(response.body)
|
||||
self.assertTrue(resp.get('error'))
|
||||
fault_string_expected = 'The first cert in the file should not be a ' \
|
||||
'CA cert'
|
||||
self.assertIn(fault_string_expected, str(resp.get('error')))
|
||||
|
||||
# Test successful POST operation to install docker_registry certificate
|
||||
# signed by intermediate CA
|
||||
def test_install_2xcert_1xkey_docker_registry_certificate(self):
|
||||
mode = 'docker_registry'
|
||||
certfile = os.path.join(os.path.dirname(__file__), "data",
|
||||
'docker_registry-cert-2xcert-1xkey-with-key.pem')
|
||||
|
||||
in_certs = self.extract_certs_from_pem_file(certfile)
|
||||
fake_config_certificate_return = []
|
||||
for index, in_cert in enumerate(in_certs):
|
||||
is_ca = False if index == 0 else True
|
||||
fake_config_certificate_return.append(
|
||||
{'signature': self.get_cert_signature(mode, in_cert),
|
||||
'not_valid_before': in_cert.not_valid_before,
|
||||
'not_valid_after': in_cert.not_valid_after,
|
||||
'is_ca': is_ca})
|
||||
self.fake_conductor_api.\
|
||||
setup_config_certificate(fake_config_certificate_return)
|
||||
|
||||
data = {'mode': mode}
|
||||
files = [('file', certfile)]
|
||||
response = self.post_with_files('%s/%s' % (self.API_PREFIX, 'certificate_install'),
|
||||
data,
|
||||
upload_files=files,
|
||||
headers=self.API_HEADERS,
|
||||
expect_errors=False)
|
||||
|
||||
self.assertEqual(response.status_code, http_client.OK)
|
||||
resp = json.loads(response.body)
|
||||
self.assertIn('certificates', resp)
|
||||
ret_certs = resp.get('certificates')
|
||||
|
||||
# The installed cert contains the server cert and the intermediate
|
||||
# CA cert but the API returns only the server cert, which should match
|
||||
# the server cert in the cert file (the first one).
|
||||
self.assertEqual(len(ret_certs), 1)
|
||||
ret_cert = ret_certs[0]
|
||||
in_cert = in_certs[0]
|
||||
|
||||
self.assertIn('certtype', ret_cert)
|
||||
self.assertEqual(ret_cert.get('certtype'), mode)
|
||||
self.assertIn('signature', ret_cert)
|
||||
self.assertIn('start_date', ret_cert)
|
||||
self.assertIn('expiry_date', ret_cert)
|
||||
|
||||
ret_cert_start_date = str(ret_cert.get('start_date'))
|
||||
ret_cert_start_date = ret_cert_start_date.replace('+00:00', '')
|
||||
ret_cert_expiry_date = str(ret_cert.get('expiry_date'))
|
||||
ret_cert_expiry_date = ret_cert_expiry_date.replace('+00:00', '')
|
||||
found_match = False
|
||||
if ret_cert.get('signature') == \
|
||||
self.get_cert_signature(mode, in_cert) and \
|
||||
ret_cert_start_date == \
|
||||
str(in_cert.not_valid_before) and \
|
||||
ret_cert_expiry_date == \
|
||||
str(in_cert.not_valid_after):
|
||||
found_match = True
|
||||
self.assertTrue(found_match)
|
||||
|
||||
# Test POST operation to install docker_registry certificate signed by
|
||||
# intermediate CA, but the server cert and intermediate cert in the file
|
||||
# is in wrong order.
|
||||
def test_install_2xcert_1xkey_docker_registry_certificate_wrong_order(self):
|
||||
mode = 'docker_registry'
|
||||
certfile = os.path.join(os.path.dirname(__file__), "data",
|
||||
'docker_registry-cert-2xcert-1xkey-with-key-wrong-order.pem')
|
||||
|
||||
data = {'mode': mode}
|
||||
files = [('file', certfile)]
|
||||
response = self.post_with_files('%s/%s' % (self.API_PREFIX, 'certificate_install'),
|
||||
data,
|
||||
upload_files=files,
|
||||
headers=self.API_HEADERS,
|
||||
expect_errors=True)
|
||||
|
||||
self.assertTrue(response.body)
|
||||
resp = json.loads(response.body)
|
||||
self.assertTrue(resp.get('error'))
|
||||
fault_string_expected = 'The first cert in the file should not be a ' \
|
||||
'CA cert'
|
||||
self.assertIn(fault_string_expected, str(resp.get('error')))
|
||||
|
||||
|
||||
class ApiCertificateDeleteTestSuite(ApiCertificateTestCaseMixin,
|
||||
base.FunctionalTest):
|
||||
|
|
Loading…
Reference in New Issue