diff options
author | Stefan Eissing <icing@apache.org> | 2024-09-17 13:38:19 +0200 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2024-09-17 13:38:19 +0200 |
commit | af10058840e024e6cf2bbdd50cc1dacfe236e6fc (patch) | |
tree | 1bba86e6826aca4314c202ee7b643059d40c36f6 /test/pyhttpd/certs.py | |
parent | removed experimental mod_tls. source, documenation and test cases (diff) | |
download | apache2-af10058840e024e6cf2bbdd50cc1dacfe236e6fc.tar.xz apache2-af10058840e024e6cf2bbdd50cc1dacfe236e6fc.zip |
*) mod_md: update to version 2.4.28
- When the server starts, it looks for new, staged certificates to
activate. If the staged set of files in 'md/staging/<domain>' is messed
up, this could prevent further renewals to happen. Now, when the staging
set is present, but could not be activated due to an error, purge the
whole directory. [icing]
- Fix certificate retrieval on ACME renewal to not require a 'Location:'
header returned by the ACME CA. This was the way it was done in ACME
before it became an IETF standard. Let's Encrypt still supports this,
but other CAs do not. [icing]
- Restore compatibility with OpenSSL < 1.1. [ylavic]
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1920747 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r-- | test/pyhttpd/certs.py | 83 |
1 files changed, 60 insertions, 23 deletions
diff --git a/test/pyhttpd/certs.py b/test/pyhttpd/certs.py index 5519f16188..a08d5e64e4 100644 --- a/test/pyhttpd/certs.py +++ b/test/pyhttpd/certs.py @@ -181,6 +181,14 @@ class Credentials: creds.issue_certs(spec.sub_specs, chain=subchain) return creds + def save_cert_pem(self, fpath): + with open(fpath, "wb") as fd: + fd.write(self.cert_pem) + + def save_pkey_pem(self, fpath): + with open(fpath, "wb") as fd: + fd.write(self.pkey_pem) + class CertStore: @@ -282,6 +290,7 @@ class HttpdTestCA: def create_credentials(spec: CertificateSpec, issuer: Credentials, key_type: Any, valid_from: timedelta = timedelta(days=-1), valid_to: timedelta = timedelta(days=89), + serial: Optional[int] = None, ) -> Credentials: """Create a certificate signed by this CA for the given domains. :returns: the certificate and private key PEM file paths @@ -289,15 +298,18 @@ class HttpdTestCA: if spec.domains and len(spec.domains): creds = HttpdTestCA._make_server_credentials(name=spec.name, domains=spec.domains, issuer=issuer, valid_from=valid_from, - valid_to=valid_to, key_type=key_type) + valid_to=valid_to, key_type=key_type, + serial=serial) elif spec.client: creds = HttpdTestCA._make_client_credentials(name=spec.name, issuer=issuer, email=spec.email, valid_from=valid_from, - valid_to=valid_to, key_type=key_type) + valid_to=valid_to, key_type=key_type, + serial=serial) elif spec.name: creds = HttpdTestCA._make_ca_credentials(name=spec.name, issuer=issuer, valid_from=valid_from, valid_to=valid_to, - key_type=key_type) + key_type=key_type, + serial=serial) else: raise Exception(f"unrecognized certificate specification: {spec}") return creds @@ -320,7 +332,8 @@ class HttpdTestCA: pkey: Any, issuer_subject: Optional[Credentials], valid_from_delta: timedelta = None, - valid_until_delta: timedelta = None + valid_until_delta: timedelta = None, + serial: Optional[int] = None ): pubkey = pkey.public_key() issuer_subject = issuer_subject if issuer_subject is not None else subject @@ -331,7 +344,8 @@ class HttpdTestCA: valid_until = datetime.now() if valid_until_delta is not None: valid_until += valid_until_delta - + if serial is None: + serial = x509.random_serial_number() return ( x509.CertificateBuilder() .subject_name(subject) @@ -339,7 +353,7 @@ class HttpdTestCA: .public_key(pubkey) .not_valid_before(valid_from) .not_valid_after(valid_until) - .serial_number(x509.random_serial_number()) + .serial_number(serial) .add_extension( x509.SubjectKeyIdentifier.from_public_key(pubkey), critical=False, @@ -374,23 +388,28 @@ class HttpdTestCA: @staticmethod def _add_leaf_usages(csr: Any, domains: List[str], issuer: Credentials) -> Any: - return csr.add_extension( + csr = csr.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, - ).add_extension( - x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( - issuer.certificate.extensions.get_extension_for_class( - x509.SubjectKeyIdentifier).value), - critical=False - ).add_extension( + ) + if issuer is not None: + csr = csr.add_extension( + x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( + issuer.certificate.extensions.get_extension_for_class( + x509.SubjectKeyIdentifier).value), + critical=False + ) + csr = csr.add_extension( x509.SubjectAlternativeName([x509.DNSName(domain) for domain in domains]), critical=True, - ).add_extension( + ) + csr = csr.add_extension( x509.ExtendedKeyUsage([ ExtendedKeyUsageOID.SERVER_AUTH, ]), critical=True ) + return csr @staticmethod def _add_client_usages(csr: Any, issuer: Credentials, rfc82name: str = None) -> Any: @@ -421,6 +440,7 @@ class HttpdTestCA: issuer: Credentials = None, valid_from: timedelta = timedelta(days=-1), valid_to: timedelta = timedelta(days=89), + serial: Optional[int] = None, ) -> Credentials: pkey = _private_key(key_type=key_type) if issuer is not None: @@ -432,7 +452,8 @@ class HttpdTestCA: subject = HttpdTestCA._make_x509_name(org_name=name, parent=issuer.subject if issuer else None) csr = HttpdTestCA._make_csr(subject=subject, issuer_subject=issuer_subject, pkey=pkey, - valid_from_delta=valid_from, valid_until_delta=valid_to) + valid_from_delta=valid_from, valid_until_delta=valid_to, + serial=serial) csr = HttpdTestCA._add_ca_usages(csr) cert = csr.sign(private_key=issuer_key, algorithm=hashes.SHA256(), @@ -444,15 +465,23 @@ class HttpdTestCA: key_type: Any, valid_from: timedelta = timedelta(days=-1), valid_to: timedelta = timedelta(days=89), + serial: Optional[int] = None, ) -> Credentials: name = name pkey = _private_key(key_type=key_type) - subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer.subject) + if issuer is not None: + issuer_subject = issuer.certificate.subject + issuer_key = issuer.private_key + else: + issuer_subject = None + issuer_key = pkey + subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer_subject) csr = HttpdTestCA._make_csr(subject=subject, - issuer_subject=issuer.certificate.subject, pkey=pkey, - valid_from_delta=valid_from, valid_until_delta=valid_to) + issuer_subject=issuer_subject, pkey=pkey, + valid_from_delta=valid_from, valid_until_delta=valid_to, + serial=serial) csr = HttpdTestCA._add_leaf_usages(csr, domains=domains, issuer=issuer) - cert = csr.sign(private_key=issuer.private_key, + cert = csr.sign(private_key=issuer_key, algorithm=hashes.SHA256(), backend=default_backend()) return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) @@ -463,14 +492,22 @@ class HttpdTestCA: key_type: Any, valid_from: timedelta = timedelta(days=-1), valid_to: timedelta = timedelta(days=89), + serial: Optional[int] = None, ) -> Credentials: pkey = _private_key(key_type=key_type) - subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer.subject) + if issuer is not None: + issuer_subject = issuer.certificate.subject + issuer_key = issuer.private_key + else: + issuer_subject = None + issuer_key = pkey + subject = HttpdTestCA._make_x509_name(common_name=name, parent=issuer_subject) csr = HttpdTestCA._make_csr(subject=subject, - issuer_subject=issuer.certificate.subject, pkey=pkey, - valid_from_delta=valid_from, valid_until_delta=valid_to) + issuer_subject=issuer_subject, pkey=pkey, + valid_from_delta=valid_from, valid_until_delta=valid_to, + serial=serial) csr = HttpdTestCA._add_client_usages(csr, issuer=issuer, rfc82name=email) - cert = csr.sign(private_key=issuer.private_key, + cert = csr.sign(private_key=issuer_key, algorithm=hashes.SHA256(), backend=default_backend()) return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) |