Files
clan-core/pkgs/clan-cli/tests/age_keys.py
Louis Opter 546ed03a90 clan-cli: tests: call SopsSetup.init while setting up fixtures
We do this by introducing `flake_with_sops` fixture, that calls the
init method ahead of the test. We did not want to do this in the `flake`
fixture since not all tests using the `flake` fixture need to have sops
setup.
2025-03-19 10:53:38 +00:00

97 lines
2.9 KiB
Python

import json
import os
from pathlib import Path
import pytest
from clan_cli.secrets.folders import sops_secrets_folder
from helpers import cli
class KeyPair:
def __init__(self, pubkey: str, privkey: str) -> None:
self.pubkey = pubkey
self.privkey = privkey
class SopsSetup:
"""Hold a list of three key pairs and create an "admin" user in the clan.
The first key in the list is used as the admin key and
the private part of the key is exposed in the
`SOPS_AGE_KEY` environment variable, the two others can
be used to add machines or other users.
"""
def __init__(self, keys: list[KeyPair]) -> None:
self.keys = keys
self.user = os.environ.get("USER", "admin")
def init(self, flake_path: Path) -> None:
cli.run(
[
"vars",
"keygen",
"--flake",
str(flake_path),
"--user",
self.user,
]
)
KEYS = [
KeyPair(
"age1dhwqzkah943xzc34tc3dlmfayyevcmdmxzjezdgdy33euxwf59vsp3vk3c",
"AGE-SECRET-KEY-1KF8E3SR3TTGL6M476SKF7EEMR4H9NF7ZWYSLJUAK8JX276JC7KUSSURKFK",
),
KeyPair(
"age14tva0txcrl0zes05x7gkx56qd6wd9q3nwecjac74xxzz4l47r44sv3fz62",
"AGE-SECRET-KEY-1U5ENXZQAY62NC78Y2WC0SEGRRMAEEKH79EYY5TH4GPFWJKEAY0USZ6X7YQ",
),
KeyPair(
"age1dhuh9xtefhgpr2sjjf7gmp9q2pr37z92rv4wsadxuqdx48989g7qj552qp",
"AGE-SECRET-KEY-169N3FT32VNYQ9WYJMLUSVTMA0TTZGVJF7YZWS8AHTWJ5RR9VGR7QCD8SKF",
),
]
@pytest.fixture
def age_keys() -> list[KeyPair]:
return KEYS
@pytest.fixture
def sops_setup(
monkeypatch: pytest.MonkeyPatch,
) -> SopsSetup:
monkeypatch.setenv("SOPS_AGE_KEY", KEYS[0].privkey)
return SopsSetup(KEYS)
# louis@(2025-03-10): right now this is specific to the `sops/secrets` folder,
# but we could make it generic to any sops file if the need arises.
def assert_secrets_file_recipients(
flake_path: Path,
secret_name: str,
expected_age_recipients_keypairs: list["KeyPair"],
err_msg: str | None = None,
) -> None:
"""Checks that the recipients of a secrets file matches expectations.
This looks up the `secret` file for `secret_name` in the `sops` directory
under `flake_path`.
:param err_msg: in case of failure, if you gave an error message then it
will be displayed, otherwise pytest will display the two different sets
of recipients.
"""
sops_file = sops_secrets_folder(flake_path) / secret_name / "secret"
with sops_file.open("rb") as fp:
sops_data = json.load(fp)
age_recipients = {each["recipient"] for each in sops_data["sops"]["age"]}
expected_age_recipients = {pair.pubkey for pair in expected_age_recipients_keypairs}
if not err_msg:
assert age_recipients == expected_age_recipients
return
assert age_recipients == expected_age_recipients, err_msg