diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5104697..00eb2b0 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -22,12 +22,13 @@ jobs: - name: Test with pytest and coverage run: | pytest --rootdir=. --cov=./cert_chain_resolver --cov-report term-missing -n auto tests/ + mv .coverage coverage-db - name: Upload coverage artifact if: success() uses: actions/upload-artifact@v4 with: name: coverage-2.7 - path: .coverage + path: coverage-db Test: runs-on: ubuntu-latest @@ -47,12 +48,13 @@ jobs: - name: Test with pytest and coverage run: | pytest --rootdir=. --cov=./cert_chain_resolver --cov-report term-missing -n auto tests/ + mv .coverage coverage-db - name: Upload coverage artifact if: success() uses: actions/upload-artifact@v4 with: name: coverage-${{ matrix.python-version }} - path: .coverage + path: coverage-db combine-coverage: runs-on: ubuntu-latest @@ -75,7 +77,7 @@ jobs: - name: Combine coverage reports run: | set -x - coverage combine coverage-*/.coverage + coverage combine coverage-*/coverage-db coverage report coverage xml -o ./coverage.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f5b60..1a7d173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.4.0 + +* Extended support to python 3.13 +* Cert.not_valid_before returns UTC datetime if cryptography version >= 42 +* Cert.not_valid_after returns UTC datetime if cryptography version >= 42 + ## 1.3.1 * is_issued_by now raises MissingCertProperty if no hash algorithm found. Before it would silently return False diff --git a/cert_chain_resolver/__init__.py b/cert_chain_resolver/__init__.py index d2eaef1..8aa979c 100644 --- a/cert_chain_resolver/__init__.py +++ b/cert_chain_resolver/__init__.py @@ -1,4 +1,4 @@ import sys -__version__ = "1.3.0" +__version__ = "1.4.0" __is_py3__ = sys.version_info >= (3, 0) diff --git a/cert_chain_resolver/models.py b/cert_chain_resolver/models.py index e12deea..3ce2589 100644 --- a/cert_chain_resolver/models.py +++ b/cert_chain_resolver/models.py @@ -135,14 +135,20 @@ def signature_hash_algorithm(self): @property def not_valid_before(self): # type: () -> datetime.datetime - """Date from the underlying :py:class:`cryptography.x509.Certificate` object""" - return self._x509.not_valid_before + """Date from the underlying :py:class:`cryptography.x509.Certificate` object. returns the UTC version if cryptography version is 42.0 or higher""" + if hasattr(self._x509, 'not_valid_before_utc'): + return self._x509.not_valid_before_utc + else: + return self._x509.not_valid_before @property def not_valid_after(self): # type: () -> datetime.datetime - """Date from the underlying :py:class:`cryptography.x509.Certificate` object""" - return self._x509.not_valid_after + """Date from the underlying :py:class:`cryptography.x509.Certificate` object. returns the UTC version if cryptography version is 42.0 or higher""" + if hasattr(self._x509, 'not_valid_after_utc'): + return self._x509.not_valid_after_utc + else: + return self._x509.not_valid_after @property def fingerprint(self): diff --git a/setup.py b/setup.py index 3543e2e..a358d41 100644 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], diff --git a/tests/_utils.py b/tests/_utils.py new file mode 100644 index 0000000..246cd0d --- /dev/null +++ b/tests/_utils.py @@ -0,0 +1,9 @@ +import cryptography +import datetime + +CRYPTOGRAPHY_MAJOR = int(cryptography.__version__.split(".")[0]) + +def make_utc_aware_if_cryptography_above_42(dt): + if CRYPTOGRAPHY_MAJOR >= 42: + return dt.replace(tzinfo=datetime.timezone.utc) + return dt \ No newline at end of file diff --git a/tests/test_cli.py b/tests/test_cli.py index e40ee74..9219d1c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,6 +6,7 @@ from cert_chain_resolver.cli import cli, main, parse_args from cert_chain_resolver.castore.file_system import FileSystemStore +from tests._utils import CRYPTOGRAPHY_MAJOR from .fixtures import BUNDLE_FIXTURES, certfixture_to_id try: @@ -146,8 +147,8 @@ def test_display_flag_is_properly_formatted(capsys): """== Certificate #1 == Subject: CN=github.com,O=GitHub\\, Inc.,L=San Francisco,ST=California,C=US Issuer: CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US -NotBefore: 2020-05-05T00:00:00 -NotAfter: 2022-05-10T12:00:00 +NotBefore: 2020-05-05T00:00:00{tz} +NotAfter: 2022-05-10T12:00:00{tz} Serial: 7101927171473588541993819712332065657 Sha256Fingeprint: b6b9a6af3e866cbe0e6a307e7dda173b372b2d3ac3f06af15f97718773848008 CAIssuerLoc: http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt @@ -162,8 +163,8 @@ def test_display_flag_is_properly_formatted(capsys): == Certificate #2 == Subject: CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US Issuer: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -NotBefore: 2013-10-22T12:00:00 -NotAfter: 2028-10-22T12:00:00 +NotBefore: 2013-10-22T12:00:00{tz} +NotAfter: 2028-10-22T12:00:00{tz} Serial: 6489877074546166222510380951761917343 Sha256Fingeprint: 19400be5b7a31fb733917700789d2f0a2471c0c9d506c0e504c06c16d7cb17c0 @@ -173,7 +174,7 @@ def test_display_flag_is_properly_formatted(capsys): Common name: DigiCert SHA2 High Assurance Server CA """ - ) + ).format(tz="+00:00" if CRYPTOGRAPHY_MAJOR > 42 else "") assert expected == captured diff --git a/tests/test_models.py b/tests/test_models.py index 8fffedc..64e9dbe 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -9,6 +9,8 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 from cryptography.exceptions import InvalidSignature +from ._utils import make_utc_aware_if_cryptography_above_42 + try: @@ -51,8 +53,8 @@ def test_certcontainer_x509_helper_props(cert): assert fixture["ca"] == c.is_ca assert fixture["serial"] == c.serial assert fixture["signature_algorithm"] == c.signature_hash_algorithm - assert fixture["not_before"] == c.not_valid_before - assert fixture["not_after"] == c.not_valid_after + assert make_utc_aware_if_cryptography_above_42(fixture["not_before"]) == c.not_valid_before + assert make_utc_aware_if_cryptography_above_42(fixture["not_after"]) == c.not_valid_after assert fixture["fingerprint_sha256"] == c.fingerprint assert fixture["ca_issuer_access_location"] == c.ca_issuer_access_location