121 lines
4.2 KiB
Python
121 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import base64
|
|
import json
|
|
from pathlib import Path
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
from jsonschema import Draft202012Validator, FormatChecker
|
|
|
|
|
|
META_ROOT = Path(__file__).resolve().parents[1]
|
|
GENERATOR = META_ROOT / "tools" / "assessments" / "generate-authority-keypair.py"
|
|
|
|
|
|
class AssessmentAuthorityKeypairTests(unittest.TestCase):
|
|
def test_generates_schema_valid_scoped_proof_authority(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
output_dir = Path(temp_dir)
|
|
output_dir.chmod(0o700)
|
|
private_path = output_dir / "target.pem"
|
|
keyring_path = output_dir / "target.json"
|
|
|
|
result = subprocess.run(
|
|
(
|
|
sys.executable,
|
|
str(GENERATOR),
|
|
"--purpose",
|
|
"proof",
|
|
"--key-id",
|
|
"authority:target-2026",
|
|
"--scope",
|
|
"target_environment",
|
|
"--scope",
|
|
"operations",
|
|
"--private-key",
|
|
str(private_path),
|
|
"--keyring",
|
|
str(keyring_path),
|
|
),
|
|
check=False,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
self.assertEqual(0, result.returncode, result.stderr)
|
|
self.assertEqual(0o600, stat.S_IMODE(private_path.stat().st_mode))
|
|
self.assertEqual(0o600, stat.S_IMODE(keyring_path.stat().st_mode))
|
|
keyring = json.loads(keyring_path.read_text(encoding="utf-8"))
|
|
schema = json.loads(
|
|
(
|
|
META_ROOT
|
|
/ "docs"
|
|
/ "capability-fit-proof-authority-keyring.schema.json"
|
|
).read_text(encoding="utf-8")
|
|
)
|
|
errors = tuple(
|
|
Draft202012Validator(
|
|
schema, format_checker=FormatChecker()
|
|
).iter_errors(keyring)
|
|
)
|
|
self.assertEqual((), errors)
|
|
self.assertEqual(
|
|
["target_environment", "operations"],
|
|
keyring["keys"][0]["allowed_scopes"],
|
|
)
|
|
private_key = serialization.load_pem_private_key(
|
|
private_path.read_bytes(), password=None
|
|
)
|
|
self.assertIsInstance(private_key, Ed25519PrivateKey)
|
|
public_key = base64.b64encode(
|
|
private_key.public_key().public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw,
|
|
)
|
|
).decode("ascii")
|
|
self.assertEqual(public_key, keyring["keys"][0]["public_key"])
|
|
|
|
def test_installer_authority_uses_fixed_scope_and_refuses_overwrite(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
output_dir = Path(temp_dir)
|
|
output_dir.chmod(0o700)
|
|
private_path = output_dir / "installer.pem"
|
|
keyring_path = output_dir / "installer.json"
|
|
command = (
|
|
sys.executable,
|
|
str(GENERATOR),
|
|
"--purpose",
|
|
"installer",
|
|
"--key-id",
|
|
"authority:installer-2026",
|
|
"--private-key",
|
|
str(private_path),
|
|
"--keyring",
|
|
str(keyring_path),
|
|
)
|
|
|
|
first = subprocess.run(
|
|
command, check=False, capture_output=True, text=True
|
|
)
|
|
second = subprocess.run(
|
|
command, check=False, capture_output=True, text=True
|
|
)
|
|
|
|
self.assertEqual(0, first.returncode, first.stderr)
|
|
self.assertNotEqual(0, second.returncode)
|
|
keyring = json.loads(keyring_path.read_text(encoding="utf-8"))
|
|
self.assertEqual(
|
|
["installed_release_origin"],
|
|
keyring["keys"][0]["allowed_scopes"],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|