mirror of
https://github.com/moepman/acertmgr.git
synced 2024-11-13 06:45:24 +01:00
acertmgr: change the way the issuer CA is fetched
This changes the way the issuer CA is retrieved if no static_ca file is used. Previously we would always download the CA using the AIA Info but API v2 provides normally the full chain PEM upon certificate retrieval and does not need this step. For the APIv2 case we now use the CA provided with the certificate which required some changes to the basic handling of CA files. APIv1 has been adapted to this new handling. APIv2 has a fallback option to the way APIv1 handles it in case no CA has been provided.
This commit is contained in:
parent
316ecdba2e
commit
c054ecebe9
@ -86,7 +86,7 @@ def cert_get(settings):
|
||||
cr = tools.new_cert_request(settings['domainlist'], key)
|
||||
print("Reading account key...")
|
||||
acme.register_account()
|
||||
crt = acme.get_crt_from_csr(cr, settings['domainlist'], challenge_handlers)
|
||||
crt, ca = acme.get_crt_from_csr(cr, settings['domainlist'], challenge_handlers)
|
||||
with io.open(crt_file, "w") as crt_fd:
|
||||
crt_fd.write(tools.convert_cert_to_pem(crt))
|
||||
|
||||
@ -95,10 +95,9 @@ def cert_get(settings):
|
||||
crt_final = settings['cert_file']
|
||||
shutil.copy2(crt_file, crt_final)
|
||||
os.chmod(crt_final, stat.S_IREAD)
|
||||
# download current ca file for the new certificate if no static ca is configured
|
||||
if "static_ca" in settings and not settings['static_ca']:
|
||||
tools.download_issuer_ca(crt_final, settings['ca_file'])
|
||||
|
||||
with io.open(settings['ca_file'], "w") as ca_fd:
|
||||
ca_fd.write(tools.convert_cert_to_pem(ca))
|
||||
finally:
|
||||
os.remove(csr_file)
|
||||
os.remove(crt_file)
|
||||
|
@ -97,7 +97,7 @@ class ACMEAuthority(AbstractACMEAuthority):
|
||||
# @param csr the certificate signing request in pyopenssl format
|
||||
# @param domains list of domains in the certificate, first is CN
|
||||
# @param challenge_handlers a dict containing challenge for all given domains
|
||||
# @return the certificate in pyopenssl format
|
||||
# @return the certificate and corresponding ca as a tuple
|
||||
# @note algorithm and parts of the code are from acme-tiny
|
||||
def get_crt_from_csr(self, csr, domains, challenge_handlers):
|
||||
header = self._prepare_header()
|
||||
@ -194,4 +194,4 @@ class ACMEAuthority(AbstractACMEAuthority):
|
||||
# return signed certificate!
|
||||
print("Certificate signed!")
|
||||
cert = x509.load_der_x509_certificate(result, default_backend())
|
||||
return cert
|
||||
return cert, tools.download_issuer_ca(cert)
|
||||
|
@ -146,7 +146,7 @@ class ACMEAuthority(AbstractACMEAuthority):
|
||||
# @param csr the certificate signing request in pyopenssl format
|
||||
# @param domains list of domains in the certificate, first is CN
|
||||
# @param challenge_handlers a dict containing challenge for all given domains
|
||||
# @return the certificate
|
||||
# @return the certificate and corresponding ca as a tuple
|
||||
# @note algorithm and parts of the code are from acme-tiny
|
||||
def get_crt_from_csr(self, csr, domains, challenge_handlers):
|
||||
accountkey_json = json.dumps(self.account_protected['jwk'], sort_keys=True, separators=(',', ':'))
|
||||
@ -239,7 +239,7 @@ class ACMEAuthority(AbstractACMEAuthority):
|
||||
time.sleep(5)
|
||||
code, order, _ = self._request_url(order_url)
|
||||
if code >= 400:
|
||||
raise ValueError("Order is still pending: {0} {1}".format(code, order))
|
||||
raise ValueError("Order is still not ready to be finalized: {0} {1}".format(code, order))
|
||||
|
||||
# get the new certificate
|
||||
print("Finalizing certificate")
|
||||
@ -257,6 +257,15 @@ class ACMEAuthority(AbstractACMEAuthority):
|
||||
# return certificate
|
||||
code, certificate, _ = self._request_url(finalize['certificate'], raw_result=True)
|
||||
if code >= 400:
|
||||
raise ValueError("Error downloading certificate: {0} {1}".format(code, certificate))
|
||||
cert = x509.load_pem_x509_certificate(certificate, default_backend())
|
||||
return cert
|
||||
raise ValueError("Error downloading certificate chain: {0} {1}".format(code, certificate))
|
||||
|
||||
cert_dict = re.match(("(?P<cert>-----BEGIN CERTIFICATE-----[^\-]+-----END CERTIFICATE-----)\n\n"
|
||||
"(?P<ca>-----BEGIN CERTIFICATE-----[^\-]+-----END CERTIFICATE-----)?"),
|
||||
certificate.decode('utf-8'), re.DOTALL).groupdict()
|
||||
cert = x509.load_pem_x509_certificate(cert_dict['cert'].encode('utf-8'), default_backend())
|
||||
if cert_dict['ca'] is None:
|
||||
ca = tools.download_issuer_ca(cert)
|
||||
else:
|
||||
ca = x509.load_pem_x509_certificate(cert_dict['ca'].encode('utf-8'), default_backend())
|
||||
|
||||
return cert, ca
|
||||
|
@ -103,14 +103,10 @@ def new_rsa_key(path, key_size=4096):
|
||||
|
||||
|
||||
# @brief download the issuer ca for a given certificate
|
||||
# @param cert_file certificate file
|
||||
# @param ca_file destination for the ca file
|
||||
def download_issuer_ca(cert_file, ca_file):
|
||||
with io.open(cert_file, 'r') as f:
|
||||
cert_data = f.read().encode('utf-8')
|
||||
cert = x509.load_pem_x509_certificate(cert_data, default_backend())
|
||||
# @param cert certificate data
|
||||
# @returns ca certificate data
|
||||
def download_issuer_ca(cert):
|
||||
aia = cert.extensions.get_extension_for_oid(ExtensionOID.AUTHORITY_INFORMATION_ACCESS)
|
||||
|
||||
ca_issuers = None
|
||||
for data in aia.value:
|
||||
if data.access_method == x509.OID_CA_ISSUERS:
|
||||
@ -118,14 +114,11 @@ def download_issuer_ca(cert_file, ca_file):
|
||||
break
|
||||
|
||||
if not ca_issuers:
|
||||
raise Exception("Could not determine issuer CA for {}".format(cert_file))
|
||||
raise Exception("Could not determine issuer CA for given certificate: {}".format(cert))
|
||||
|
||||
print("Downloading CA certificate from {} to {}".format(ca_issuers, ca_file))
|
||||
print("Downloading CA certificate from {}".format(ca_issuers))
|
||||
cadata = urlopen(ca_issuers).read()
|
||||
cacert = x509.load_der_x509_certificate(cadata, default_backend())
|
||||
pem = cacert.public_bytes(encoding=serialization.Encoding.PEM)
|
||||
with io.open(ca_file, 'wb') as pem_out:
|
||||
pem_out.write(pem)
|
||||
return x509.load_der_x509_certificate(cadata, default_backend())
|
||||
|
||||
|
||||
# @brief convert certificate to PEM format
|
||||
|
Loading…
Reference in New Issue
Block a user