Dev #72

Merged
Latte merged 71 commits from dev into main 2026-10-14 17:52:23 +00:00
2 changed files with 44 additions and 13 deletions
Showing only changes of commit 72462105f5 - Show all commits

No files matched your search

+20 -13
View File
@@ -38,6 +38,7 @@ NAME_PREFIX = "aegis-it-"
GITEA_PORT = 3000
ADMIN_LOGIN = "aegis-admin"
ADMIN_EMAIL = "aegis-admin@example.test"
ADMIN_PASSWORD_ENV = "GITEA_ADMIN_PASSWORD"
READY_TIMEOUT_SECONDS = 90.0
NETWORK_MODE_ENV = "AEGIS_IT_NETWORK_MODE"
HTTP_TIMEOUT_SECONDS = 30.0
@@ -53,12 +54,16 @@ class HarnessError(RuntimeError):
def run_docker(
*args: str, check: bool = True, timeout: float = 120.0
*args: str,
check: bool = True,
timeout: float = 120.0,
env: Mapping[str, str] | None = None,
) -> subprocess.CompletedProcess[str]:
"""Run ``docker <args>`` and return the completed process.
On failure the error names only the first two arguments (never the full
argv, which may carry a password) plus the command's stderr.
Secrets must not go into ``args`` (argv is visible to every local user): pass them
in ``env`` and forward them with ``docker exec -e NAME``. On failure the error names
only the first two arguments plus the command's stderr.
"""
try:
proc = subprocess.run(
@@ -67,6 +72,7 @@ def run_docker(
text=True,
timeout=timeout,
check=False,
env={**os.environ, **env} if env else None,
)
except (FileNotFoundError, PermissionError) as exc:
raise HarnessError("the 'docker' CLI was not found or is not executable") from exc
@@ -480,23 +486,24 @@ def start_gitea() -> GiteaInstance:
res.attached_container = job_container
_wait_ready(base_url, res.container)
admin_password = secrets.token_urlsafe(24)
# The password travels in the environment of the docker CLI process and is forwarded
# with ``-e NAME`` (no value), so it never appears in any argv on the host. Inside
# the container it is read from the shell environment, not from the command line.
run_docker(
"exec",
"-e",
ADMIN_PASSWORD_ENV,
"-u",
"git",
res.container,
"gitea",
"admin",
"user",
"create",
"--admin",
"--username",
"sh",
"-c",
'exec gitea admin user create --admin --username "$1" --email "$2" '
f'--password "${ADMIN_PASSWORD_ENV}" --must-change-password=false',
"sh",
ADMIN_LOGIN,
"--password",
admin_password,
"--email",
ADMIN_EMAIL,
"--must-change-password=false",
env={ADMIN_PASSWORD_ENV: admin_password},
)
instance = GiteaInstance(
base_url=base_url,
+24
View File
@@ -157,3 +157,27 @@ def test_container_id_candidates_fall_back_to_proc(tmp_path: Path) -> None:
def test_container_id_candidates_tolerate_missing_files(tmp_path: Path) -> None:
assert harness.container_id_candidates({}, proc_root=tmp_path) == []
def test_run_docker_passes_secrets_through_the_environment_not_argv(
monkeypatch: pytest.MonkeyPatch,
) -> None:
seen: dict[str, object] = {}
def fake_run(argv: list[str], **kwargs: object) -> object:
seen["argv"] = argv
seen["env"] = kwargs.get("env")
class Done:
returncode = 0
stdout = ""
stderr = ""
return Done()
monkeypatch.setattr(harness.subprocess, "run", fake_run)
harness.run_docker("exec", "-e", "SECRET_VAR", "box", env={"SECRET_VAR": "s3cret-value"})
assert "s3cret-value" not in " ".join(seen["argv"]) # type: ignore[call-overload]
assert seen["env"]["SECRET_VAR"] == "s3cret-value" # type: ignore[index]
assert "PATH" in seen["env"] # type: ignore[operator]