Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nethsm for openSUSE:Factory checked in at 2026-05-13 17:22:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nethsm (Old) and /work/SRC/openSUSE:Factory/.python-nethsm.new.1966 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nethsm" Wed May 13 17:22:01 2026 rev:11 rq:1352916 version:2.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nethsm/python-nethsm.changes 2026-04-01 19:53:28.188211332 +0200 +++ /work/SRC/openSUSE:Factory/.python-nethsm.new.1966/python-nethsm.changes 2026-05-13 17:23:56.914765622 +0200 @@ -1,0 +2,7 @@ +Wed May 13 04:47:40 UTC 2026 - Johannes Kastl <[email protected]> + +- update to 2.1.1: + * Bugfixes + - Fix endpoint path in NetHSM.set_cluster_ca_certificate + +------------------------------------------------------------------- Old: ---- nethsm-2.1.0.tar.gz New: ---- nethsm-2.1.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nethsm.spec ++++++ --- /var/tmp/diff_new_pack.CHzoft/_old 2026-05-13 17:23:57.634795489 +0200 +++ /var/tmp/diff_new_pack.CHzoft/_new 2026-05-13 17:23:57.646795987 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-nethsm -Version: 2.1.0 +Version: 2.1.1 Release: 0 Summary: Python Library to manage NetHSM(s) License: Apache-2.0 @@ -132,6 +132,7 @@ IGNORED_CHECKS="${IGNORED_CHECKS} or test_namespace_tag_delete" IGNORED_CHECKS="${IGNORED_CHECKS} or test_namespace_tag_readd" IGNORED_CHECKS="${IGNORED_CHECKS} or test_delete_prefix" +IGNORED_CHECKS="${IGNORED_CHECKS} or test_cluster_ca_certificate" %pytest -k "not (${IGNORED_CHECKS})" ++++++ nethsm-2.1.0.tar.gz -> nethsm-2.1.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nethsm-sdk-py-2.1.0/CHANGELOG.md new/nethsm-sdk-py-2.1.1/CHANGELOG.md --- old/nethsm-sdk-py-2.1.0/CHANGELOG.md 2026-03-26 16:07:56.000000000 +0100 +++ new/nethsm-sdk-py-2.1.1/CHANGELOG.md 2026-05-12 10:00:43.000000000 +0200 @@ -4,7 +4,15 @@ - -[All Changes](https://github.com/Nitrokey/nethsm-sdk-py/compare/v2.1.0...HEAD) +[All Changes](https://github.com/Nitrokey/nethsm-sdk-py/compare/v2.1.1...HEAD) + +## [v2.1.1](https://github.com/Nitrokey/nethsm-sdk-py/releases/tag/v2.1.1) (2026-05-11) + +### Bugfixes + +- Fix endpoint path in `NetHSM.set_cluster_ca_certificate` + +[All Changes](https://github.com/Nitrokey/nethsm-sdk-py/compare/v2.1.0...v2.1.1) ## [v2.1.0](https://github.com/Nitrokey/nethsm-sdk-py/releases/tag/v2.1.0) (2026-03-25) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nethsm-sdk-py-2.1.0/nethsm/__init__.py new/nethsm-sdk-py-2.1.1/nethsm/__init__.py --- old/nethsm-sdk-py-2.1.0/nethsm/__init__.py 2026-03-26 16:07:56.000000000 +0100 +++ new/nethsm-sdk-py-2.1.1/nethsm/__init__.py 2026-05-12 10:00:43.000000000 +0200 @@ -1803,7 +1803,9 @@ def set_cluster_ca_certificate(self, cert: Bytes) -> None: try: - self._request("PUT", "config/tls/ca.pem", data=cert, mime_type="application/x-pem-file") + self._request( + "PUT", "config/tls/cluster-ca.pem", data=cert, mime_type="application/x-pem-file" + ) except Exception as e: _handle_exception(e, state=State.OPERATIONAL, roles=[Role.ADMINISTRATOR]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nethsm-sdk-py-2.1.0/pyproject.toml new/nethsm-sdk-py-2.1.1/pyproject.toml --- old/nethsm-sdk-py-2.1.0/pyproject.toml 2026-03-26 16:07:56.000000000 +0100 +++ new/nethsm-sdk-py-2.1.1/pyproject.toml 2026-05-12 10:00:43.000000000 +0200 @@ -4,7 +4,7 @@ [project] name = "nethsm" -version = "2.1.0" +version = "2.1.1" description = "Python Library to manage NetHSM(s)" authors = [{ name = "Nitrokey", email = "[email protected]" },] readme = "README.md" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nethsm-sdk-py-2.1.0/tests/test_nethsm_config.py new/nethsm-sdk-py-2.1.1/tests/test_nethsm_config.py --- old/nethsm-sdk-py-2.1.0/tests/test_nethsm_config.py 2026-03-26 16:07:56.000000000 +0100 +++ new/nethsm-sdk-py-2.1.1/tests/test_nethsm_config.py 2026-05-12 10:00:43.000000000 +0200 @@ -1,6 +1,7 @@ import datetime import ipaddress import secrets +import time from tempfile import NamedTemporaryFile import pytest @@ -119,15 +120,22 @@ ) self.int_cert = builder.sign(self.ca_key, hashes.SHA256()) - def sign(self, csr: x509.CertificateSigningRequest) -> bytes: + def sign(self, csr: x509.CertificateSigningRequest, intermediate: bool = True) -> bytes: import datetime + if intermediate: + issuer_cert = self.int_cert + issuer_key = self.int_key + else: + issuer_cert = self.ca_cert + issuer_key = self.ca_key + now = datetime.datetime.now(datetime.timezone.utc) ip = x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")) builder = x509.CertificateBuilder() builder = builder.subject_name(csr.subject) - builder = builder.issuer_name(self.int_cert.subject) + builder = builder.issuer_name(issuer_cert.subject) builder = builder.public_key(csr.public_key()) builder = builder.serial_number(x509.random_serial_number()) builder = builder.not_valid_before(now) @@ -161,20 +169,25 @@ ) builder = builder.add_extension( x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( - self.int_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value + issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value ), critical=False, ) - cert = builder.sign(self.int_key, hashes.SHA256()) + cert = builder.sign(issuer_key, hashes.SHA256()) # sanity check store = x509.verification.Store([self.ca_cert]) verifier = x509.verification.PolicyBuilder().store(store).build_server_verifier(ip) - verifier.verify(cert, [self.int_cert]) - - return cert.public_bytes(serialization.Encoding.PEM) + self.int_cert.public_bytes( - serialization.Encoding.PEM - ) + intermediates = [] + if intermediate: + intermediates = [issuer_cert] + verifier.verify(cert, intermediates) + + cert_bytes = cert.public_bytes(serialization.Encoding.PEM) + if intermediate: + return cert_bytes + self.int_cert.public_bytes(serialization.Encoding.PEM) + else: + return cert_bytes @property def ca_cert_pem(self) -> bytes: @@ -480,13 +493,51 @@ C.UNLOCK_PASSPHRASE_CHANGED, current_passphrase=C.UNLOCK_PASSPHRASE ) + assert nethsm.get_state() == State.OPERATIONAL lock(nethsm) + assert nethsm.get_state() == State.LOCKED unlock(nethsm, C.UNLOCK_PASSPHRASE_CHANGED) + assert nethsm.get_state() == State.OPERATIONAL - with pytest.raises(nethsm_module.NetHSMError): - lock(nethsm) + lock(nethsm) + assert nethsm.get_state() == State.LOCKED + + with pytest.raises(nethsm_module.NetHSMError, match="Access denied -- wrong unlock passphrase"): nethsm.unlock(C.UNLOCK_PASSPHRASE_WRONG) + assert nethsm.get_state() == State.LOCKED + + time.sleep(1) - with pytest.raises(nethsm_module.NetHSMError): - lock(nethsm) + with pytest.raises(nethsm_module.NetHSMError, match="Access denied -- wrong unlock passphrase"): nethsm.unlock(C.UNLOCK_PASSPHRASE_WRONG_CASE) + assert nethsm.get_state() == State.LOCKED + + time.sleep(1) + + unlock(nethsm, C.UNLOCK_PASSPHRASE_CHANGED) + assert nethsm.get_state() == State.OPERATIONAL + + +def test_cluster_ca_certificate(nethsm: NetHSM) -> None: + with pytest.raises(nethsm_module.NetHSMError, match="404: Not Found"): + ca_cert = nethsm.get_cluster_ca_certificate() + + ca = CA() + + csr_pem = nethsm.csr( + country=C.COUNTRY, + state_or_province=C.STATE_OR_PROVINCE, + locality=C.LOCALITY, + organization=C.ORGANIZATION, + organizational_unit=C.ORGANIZATIONAL_UNIT, + common_name=C.COMMON_NAME, + email_address=C.EMAIL_ADDRESS, + ) + csr = x509.load_pem_x509_csr(csr_pem.encode()) + cert = ca.sign(csr, intermediate=False) + nethsm.set_certificate(cert) + + nethsm.set_cluster_ca_certificate(ca.ca_cert_pem) + + ca_cert = nethsm.get_cluster_ca_certificate() + assert ca_cert == ca.ca_cert_pem.decode("utf-8")
