diff options
author | Stefan Eissing <icing@apache.org> | 2021-11-10 16:54:27 +0100 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2021-11-10 16:54:27 +0100 |
commit | 7840e7d212ce12442c48ce6e7e56414d25e17132 (patch) | |
tree | e448f08be385096fd441ce4df816b85adae8da14 /test/pyhttpd/certs.py | |
parent | * test HTTP/2: also run core tests and worker mpm (diff) | |
download | apache2-7840e7d212ce12442c48ce6e7e56414d25e17132.tar.xz apache2-7840e7d212ce12442c48ce6e7e56414d25e17132.zip |
* testsuite: possible now to issue client certificates and the chain file for them
* testsuite: handling of cert+key in same file improved
* testsuite: using 'stop' configuration to terminate server in case test cases
leave borked test configs lying around.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1894919 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/pyhttpd/certs.py')
-rw-r--r-- | test/pyhttpd/certs.py | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/test/pyhttpd/certs.py b/test/pyhttpd/certs.py index 2ce93c07b2..5519f16188 100644 --- a/test/pyhttpd/certs.py +++ b/test/pyhttpd/certs.py @@ -70,13 +70,24 @@ class CertificateSpec: return self.domains[0] return None + @property + def type(self) -> Optional[str]: + if self.domains and len(self.domains): + return "server" + elif self.client: + return "client" + elif self.name: + return "ca" + return None + class Credentials: - def __init__(self, name: str, cert: Any, pkey: Any): + def __init__(self, name: str, cert: Any, pkey: Any, issuer: 'Credentials' = None): self._name = name self._cert = cert self._pkey = pkey + self._issuer = issuer self._cert_file = None self._pkey_file = None self._store = None @@ -117,6 +128,10 @@ class Credentials: PrivateFormat.TraditionalOpenSSL if self.key_type.startswith('rsa') else PrivateFormat.PKCS8, NoEncryption()) + @property + def issuer(self) -> Optional['Credentials']: + return self._issuer + def set_store(self, store: 'CertStore'): self._store = store @@ -145,13 +160,17 @@ class Credentials: def issue_cert(self, spec: CertificateSpec, chain: List['Credentials'] = None) -> 'Credentials': key_type = spec.key_type if spec.key_type else self.key_type - creds = self._store.load_credentials(name=spec.name, key_type=key_type, single_file=spec.single_file) \ - if self._store else None + creds = None + if self._store: + creds = self._store.load_credentials( + name=spec.name, key_type=key_type, single_file=spec.single_file, issuer=self) if creds is None: creds = HttpdTestCA.create_credentials(spec=spec, issuer=self, key_type=key_type, valid_from=spec.valid_from, valid_to=spec.valid_to) if self._store: self._store.save(creds, single_file=spec.single_file) + if spec.type == "ca": + self._store.save_chain(creds, "ca", with_root=True) if spec.sub_specs: if self._store: @@ -196,6 +215,19 @@ class CertStore: creds.set_files(cert_file, pkey_file) self._add_credentials(name, creds) + def save_chain(self, creds: Credentials, infix: str, with_root=False): + name = creds.name + chain = [creds] + while creds.issuer is not None: + creds = creds.issuer + chain.append(creds) + if not with_root and len(chain) > 1: + chain = chain[:-1] + chain_file = os.path.join(self._store_dir, f'{name}-{infix}.pem') + with open(chain_file, "wb") as fd: + for c in chain: + fd.write(c.cert_pem) + def _add_credentials(self, name: str, creds: Credentials): if name not in self._creds_by_name: self._creds_by_name[name] = [] @@ -220,13 +252,13 @@ class CertStore: with open(fpath) as fd: return load_pem_private_key("".join(fd.readlines()).encode(), password=None) - def load_credentials(self, name: str, key_type=None, single_file: bool = False): + def load_credentials(self, name: str, key_type=None, single_file: bool = False, issuer: Credentials = None): cert_file = self.get_cert_file(name=name, key_type=key_type) pkey_file = cert_file if single_file else self.get_pkey_file(name=name, key_type=key_type) if os.path.isfile(cert_file) and os.path.isfile(pkey_file): cert = self.load_pem_cert(cert_file) pkey = self.load_pem_pkey(pkey_file) - creds = Credentials(name=name, cert=cert, pkey=pkey) + creds = Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) creds.set_store(self) creds.set_files(cert_file, pkey_file) self._add_credentials(name, creds) @@ -239,7 +271,7 @@ class HttpdTestCA: @classmethod def create_root(cls, name: str, store_dir: str, key_type: str = "rsa2048") -> Credentials: store = CertStore(fpath=store_dir) - creds = store.load_credentials(name="ca", key_type=key_type) + creds = store.load_credentials(name="ca", key_type=key_type, issuer=None) if creds is None: creds = HttpdTestCA._make_ca_credentials(name=name, key_type=key_type) store.save(creds, name="ca") @@ -405,7 +437,7 @@ class HttpdTestCA: cert = csr.sign(private_key=issuer_key, algorithm=hashes.SHA256(), backend=default_backend()) - return Credentials(name=name, cert=cert, pkey=pkey) + return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) @staticmethod def _make_server_credentials(name: str, domains: List[str], issuer: Credentials, @@ -423,7 +455,7 @@ class HttpdTestCA: cert = csr.sign(private_key=issuer.private_key, algorithm=hashes.SHA256(), backend=default_backend()) - return Credentials(name=name, cert=cert, pkey=pkey) + return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) @staticmethod def _make_client_credentials(name: str, @@ -441,4 +473,4 @@ class HttpdTestCA: cert = csr.sign(private_key=issuer.private_key, algorithm=hashes.SHA256(), backend=default_backend()) - return Credentials(name=name, cert=cert, pkey=pkey) + return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer) |