From 4ef09f941601f46024c2cbfb7329ac2848366ea6 Mon Sep 17 00:00:00 2001 From: Nora Date: Wed, 24 Jun 2026 16:09:19 -0600 Subject: [PATCH] test(sp26): assert CYCLONE_SFTP_PASSWORD_FILE + cyclone_sftp_password in compose --- backend/tests/test_docker.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/backend/tests/test_docker.py b/backend/tests/test_docker.py index 48b040b..29221be 100644 --- a/backend/tests/test_docker.py +++ b/backend/tests/test_docker.py @@ -117,8 +117,15 @@ def test_compose_declares_required_services(): def test_compose_declares_required_secrets_and_volumes(): compose = yaml.safe_load(COMPOSE_FILE.read_text()) secrets = compose.get("secrets", {}) - for required in ("cyclone_db_key", "cyclone_admin_password"): + for required in ("cyclone_db_key", "cyclone_admin_password", "cyclone_sftp_password"): assert required in secrets, f"compose must declare secret {required!r}" + # SP26: the SFTP secret must point at the same /etc/cyclone/secrets/ tree + # the host operator manages. Catch typos in the file path here so a + # rename breaks the test, not a production deploy. + assert ( + secrets["cyclone_sftp_password"]["file"] + == "/etc/cyclone/secrets/sftp_password" + ) volumes = compose.get("volumes", {}) for required in ( "cyclone_db", @@ -142,6 +149,22 @@ def test_compose_backend_wires_backup_autostart(): assert "CYCLONE_BACKUP_RETENTION_DAYS" in env +def test_compose_backend_wires_sftp_password_file_env_var(): + """SP26 — the backend must wire CYCLONE_SFTP_PASSWORD_FILE to the + mounted Docker secret so the MFT password resolves from + /run/secrets/cyclone_sftp_password without an env-var export.""" + compose = yaml.safe_load(COMPOSE_FILE.read_text()) + backend = compose["services"]["backend"] + env = backend.get("environment", {}) + assert env.get("CYCLONE_SFTP_PASSWORD_FILE") == "/run/secrets/cyclone_sftp_password", ( + "backend must wire CYCLONE_SFTP_PASSWORD_FILE to the Docker secret mount" + ) + backend_secrets = backend.get("secrets", []) + assert any( + _volume_source(s) == "cyclone_sftp_password" for s in backend_secrets + ), "backend must reference the cyclone_sftp_password Docker secret" + + @pytest.mark.skipif( not _has_docker(), reason="docker not on PATH; skipping Dockerfile parse check" )