From 461974a49165d2869fd37e1311baea246f0347fa Mon Sep 17 00:00:00 2001 From: Roland Sommer Date: Mon, 2 Oct 2023 14:35:16 +0200 Subject: [PATCH] Allow setting of cert's notBefore attribute For testing purposes in addition to not_after, not_before is made configurable by this. This is especially useful while testing other certificate handling software in an automated setup. --- src/trustme/__init__.py | 11 ++++++++++- tests/test_trustme.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/trustme/__init__.py b/src/trustme/__init__.py index bd837f8..5fb24fb 100644 --- a/src/trustme/__init__.py +++ b/src/trustme/__init__.py @@ -35,6 +35,8 @@ # ~3001-01-19: # https://github.com/pyca/cryptography/issues/3194 DEFAULT_EXPIRY = datetime.datetime(3000, 1, 1) +DEFAULT_NOT_BEFORE = datetime.datetime(2000, 1, 1) + def _name(name: str, organization_name: Optional[str] = None, common_name: Optional[str] = None) -> x509.Name: name_pieces = [ @@ -64,14 +66,16 @@ def _cert_builder_common( issuer: x509.Name, public_key: CERTIFICATE_PUBLIC_KEY_TYPES, not_after: Optional[datetime.datetime] = None, + not_before: Optional[datetime.datetime] = None, ) -> x509.CertificateBuilder: not_after = not_after if not_after else DEFAULT_EXPIRY + not_before = not_before if not_before else DEFAULT_NOT_BEFORE return ( x509.CertificateBuilder() .subject_name(subject) .issuer_name(issuer) .public_key(public_key) - .not_valid_before(datetime.datetime(2000, 1, 1)) + .not_valid_before(not_before) .not_valid_after(not_after) .serial_number(x509.random_serial_number()) .add_extension( @@ -311,6 +315,7 @@ def issue_cert( common_name: Optional[str] = None, organization_name: Optional[str] = None, organization_unit_name: Optional[str] = None, + not_before: Optional[datetime.datetime] = None, not_after: Optional[datetime.datetime] = None, key_type: KeyType = KeyType.ECDSA, ) -> "LeafCert": @@ -351,6 +356,9 @@ def issue_cert( attribute on the certificate. By default, a random one will be generated. + not_before: Set the validity start date (notBefore) of the certificate. + This argument type is `datetime.datetime`. + not_after: Set the expiry date (notAfter) of the certificate. This argument type is `datetime.datetime`. @@ -380,6 +388,7 @@ def issue_cert( ), self._certificate.subject, key.public_key(), + not_before=not_before, not_after=not_after, ) .add_extension( diff --git a/tests/test_trustme.py b/tests/test_trustme.py index 3360336..1d901ad 100644 --- a/tests/test_trustme.py +++ b/tests/test_trustme.py @@ -171,6 +171,23 @@ def test_issue_cert_custom_not_after() -> None: assert getattr(cert.not_valid_after, t) == getattr(expires, t) +def test_issue_cert_custom_not_before() -> None: + not_before = datetime.datetime(2027, 7, 5, 17, 15, 30) + ca = CA() + + leaf_cert = ca.issue_cert( + "example.org", + organization_name="python-trio", + organization_unit_name="trustme", + not_before=not_before, + ) + + cert = x509.load_pem_x509_certificate(leaf_cert.cert_chain_pems[0].bytes()) + + for t in ["year", "month", "day", "hour", "minute", "second"]: + assert getattr(cert.not_valid_before, t) == getattr(not_before, t) + + def test_intermediate() -> None: ca = CA() ca_cert = x509.load_pem_x509_certificate(ca.cert_pem.bytes())