summaryrefslogtreecommitdiffstats
path: root/test/pyhttpd/certs.py
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2021-11-10 16:54:27 +0100
committerStefan Eissing <icing@apache.org>2021-11-10 16:54:27 +0100
commit7840e7d212ce12442c48ce6e7e56414d25e17132 (patch)
treee448f08be385096fd441ce4df816b85adae8da14 /test/pyhttpd/certs.py
parent * test HTTP/2: also run core tests and worker mpm (diff)
downloadapache2-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.py50
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)