77 lines
3.5 KiB
Python
77 lines
3.5 KiB
Python
import base64
|
|
import importlib.util
|
|
import json
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
MODULE_PATH = Path(__file__).parents[2] / "autoinstall/offline/verify-python-profile-membership.py"
|
|
SPEC = importlib.util.spec_from_file_location("verify_python_profile_membership", MODULE_PATH)
|
|
MODULE = importlib.util.module_from_spec(SPEC)
|
|
assert SPEC.loader
|
|
SPEC.loader.exec_module(MODULE)
|
|
|
|
|
|
class VerifyPythonProfileMembershipTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
algorithms = subprocess.run(["openssl", "list", "-public-key-algorithms"],
|
|
capture_output=True, text=True)
|
|
if algorithms.returncode != 0 or "ED25519" not in algorithms.stdout.upper():
|
|
raise unittest.SkipTest("OpenSSL build has no Ed25519 support")
|
|
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
root = Path(self.temp.name)
|
|
self.private = root / "test-private.pem"
|
|
self.public = root / "test-public.pem"
|
|
subprocess.run(["openssl", "genpkey", "-algorithm", "ED25519", "-out", self.private], check=True)
|
|
subprocess.run(["openssl", "pkey", "-in", self.private, "-pubout", "-out", self.public], check=True)
|
|
self.manifest = {
|
|
"namespace": "offline-workstation/python-runtime-profiles",
|
|
"profiles": {"cpu-only": {}, "nvidia-cu128": {}},
|
|
}
|
|
body = root / "body"
|
|
signature = root / "signature"
|
|
body.write_bytes(MODULE.canonical(self.manifest))
|
|
subprocess.run(["openssl", "pkeyutl", "-sign", "-inkey", self.private, "-rawin",
|
|
"-in", body, "-out", signature], check=True)
|
|
der = subprocess.run(["openssl", "pkey", "-pubin", "-in", self.public, "-outform", "DER"],
|
|
check=True, capture_output=True).stdout
|
|
self.trust = {"policy_version": "test-v1", "keys": [{
|
|
"key_id": "TEST-PROFILE-KEY", "algorithm": "ed25519",
|
|
"purpose": "profile-membership", "status": "active", "environment": "test",
|
|
"public_key_sha256": MODULE.sha256(der),
|
|
}]}
|
|
self.envelope = {
|
|
"schema": "com.cezen.nexus-one.signature-envelope.v1",
|
|
"manifest_digest": "sha256:" + MODULE.sha256(MODULE.canonical(self.manifest)),
|
|
"algorithm": "ed25519", "key_id": "TEST-PROFILE-KEY",
|
|
"policy_version": "test-v1", "signature": base64.b64encode(signature.read_bytes()).decode(),
|
|
}
|
|
|
|
def tearDown(self):
|
|
self.temp.cleanup()
|
|
|
|
def test_valid_signature_emits_bound_test_receipt(self):
|
|
receipt = MODULE.verify(self.manifest, self.envelope, self.trust, self.public, "test",
|
|
"2026-07-14T00:00:00Z", "f" * 64)
|
|
self.assertEqual(receipt["result"], "verified")
|
|
self.assertEqual(receipt["profiles"], ["cpu-only", "nvidia-cu128"])
|
|
|
|
def test_tamper_and_wrong_environment_fail(self):
|
|
tampered = json.loads(json.dumps(self.manifest))
|
|
tampered["profiles"]["extra"] = {}
|
|
with self.assertRaisesRegex(MODULE.VerificationError, "DIGEST_MISMATCH"):
|
|
MODULE.verify(tampered, self.envelope, self.trust, self.public, "test",
|
|
"2026-07-14T00:00:00Z", "f" * 64)
|
|
with self.assertRaisesRegex(MODULE.VerificationError, "KEY_POLICY_REJECTED"):
|
|
MODULE.verify(self.manifest, self.envelope, self.trust, self.public, "production",
|
|
"2026-07-14T00:00:00Z", "f" * 64)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|