"""A run's secrets never reach its output: each line is masked before it is broadcast, written to the log artifact or stored on the run.""" from steward.ansible.executor import MASK, run_secrets, scrub def test_run_secrets_gathers_everything_the_run_is_handed(): secrets = run_secrets( {"become_password": "become-pw", "vault_password": "vault-pw", "ssh_user": "steward"}, {"user": "root", "password": "boot-pw"}, {"db": {"password": "nested-pw"}, "api_keys": ["key-one"], "port": 5432}, ["agent-token-abc"], ) assert set(secrets) == {"become-pw", "vault-pw", "boot-pw", "nested-pw", "key-one", "agent-token-abc"} assert "steward" not in secrets and "root" not in secrets def test_short_values_are_not_masked(): assert run_secrets(None, None, {"flag": "on", "n": "1"}, None) == [] def test_scrub_masks_every_occurrence_longest_first(): secrets = run_secrets(None, None, {"a": "hunter2", "b": "hunter2-extended"}, None) line = 'fatal: [h]: FAILED! => {"msg": "hunter2-extended / hunter2"}' assert scrub(line, secrets) == f'fatal: [h]: FAILED! => {{"msg": "{MASK} / {MASK}"}}' def test_scrub_leaves_clean_lines_alone(): assert scrub("ok: [web1]", ["agent-token-abc"]) == "ok: [web1]" def test_bundled_tasks_that_template_the_agent_token_are_no_log(): """Every bundled task whose args mention steward_token sets no_log (assert-style checks excepted: they print a fixed fail_msg).""" import pathlib import yaml import steward.ansible def missing(plays) -> list[str]: out = [] for play in plays or []: for task in (play.get("tasks") or []) + (play.get("handlers") or []): body = {k: v for k, v in task.items() if k not in ("name", "no_log")} if "ansible.builtin.assert" in body or "assert" in body: continue if "steward_token" in yaml.safe_dump(body) and not task.get("no_log"): out.append(task.get("name", "?")) return out # The check can fail. assert missing([{"tasks": [{"name": "leaky", "copy": {"content": "{{ steward_token }}"}}]}]) == ["leaky"] bundled = pathlib.Path(steward.ansible.__file__).parent / "bundled" files = sorted(bundled.rglob("*.yml")) assert files leaks = [f"{f.name}: {t}" for f in files for t in missing(yaml.safe_load(f.read_text()))] assert not leaks, leaks