From b3d4adf7d44fdcdd913ce3d97cd881d81a235482 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 29 Jun 2026 12:25:35 +1000 Subject: [PATCH] Show a warning when manifesting from a harvest as reminder it should be trusted first --- enroll/manifest.py | 13 +++++++++++++ tests/test_manifest.py | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/enroll/manifest.py b/enroll/manifest.py index 0d97330..b607020 100644 --- a/enroll/manifest.py +++ b/enroll/manifest.py @@ -2,6 +2,7 @@ from __future__ import annotations import os import shutil +import sys import tarfile import tempfile from pathlib import Path @@ -19,6 +20,16 @@ from .sopsutil import ( from .validate import validate_harvest +_SEMANTIC_SAFETY_WARNING = ( + "This harvest is structurally valid, but Enroll cannot prove it is semantically safe.\n" + "Only apply manifests generated from harvests whose provenance you trust.\n" +) + + +def _warn_semantic_safety() -> None: + sys.stderr.write(_SEMANTIC_SAFETY_WARNING) + + def _prepare_bundle_dir( bundle: str, *, @@ -217,6 +228,8 @@ def manifest( + validation.to_text().strip() ) + _warn_semantic_safety() + if not sops_mode: manifest_ansible_from_bundle_dir( resolved_bundle_dir, diff --git a/tests/test_manifest.py b/tests/test_manifest.py index dbd7633..e72ee2e 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -87,6 +87,24 @@ def _write_state(bundle: Path, state: dict) -> None: write_schema_state(bundle, state) +def test_manifest_warns_that_validation_is_not_semantic_safety(tmp_path: Path, capsys): + bundle = tmp_path / "bundle" + out = tmp_path / "ansible" + _write_state(bundle, _minimal_package_state([])) + + manifest.manifest(str(bundle), str(out)) + + captured = capsys.readouterr() + assert ( + "This harvest is structurally valid, but Enroll cannot prove it is semantically safe." + in captured.err + ) + assert ( + "Only apply manifests generated from harvests whose provenance you trust." + in captured.err + ) + + def test_manifest_writes_roles_and_playbook_with_clean_when(tmp_path: Path): bundle = tmp_path / "bundle" out = tmp_path / "ansible"