Remove puppet and salt
This commit is contained in:
parent
88e9dba39a
commit
e9d7d74445
24 changed files with 256 additions and 7714 deletions
|
|
@ -48,7 +48,6 @@ def test_cli_manifest_subcommand_calls_manifest(monkeypatch, tmp_path):
|
|||
called["fqdn"] = kwargs.get("fqdn")
|
||||
called["jinjaturtle"] = kwargs.get("jinjaturtle")
|
||||
called["no_common_roles"] = kwargs.get("no_common_roles")
|
||||
called["target"] = kwargs.get("target")
|
||||
|
||||
monkeypatch.setattr(cli, "manifest", fake_manifest)
|
||||
monkeypatch.setattr(
|
||||
|
|
@ -70,7 +69,6 @@ def test_cli_manifest_subcommand_calls_manifest(monkeypatch, tmp_path):
|
|||
assert called["fqdn"] is None
|
||||
assert called["jinjaturtle"] == "auto"
|
||||
assert called["no_common_roles"] is False
|
||||
assert called["target"] == "ansible"
|
||||
|
||||
|
||||
def test_cli_force_unsafe_path_before_subcommand_reaches_guard(monkeypatch, tmp_path):
|
||||
|
|
@ -131,36 +129,6 @@ def test_cli_force_unsafe_path_after_subcommand_reaches_guard(monkeypatch, tmp_p
|
|||
assert seen["force"] is True
|
||||
|
||||
|
||||
def test_cli_manifest_target_puppet_is_forwarded(monkeypatch, tmp_path):
|
||||
called = {}
|
||||
|
||||
def fake_manifest(harvest_dir: str, out_dir: str, **kwargs):
|
||||
called["harvest"] = harvest_dir
|
||||
called["out"] = out_dir
|
||||
called["target"] = kwargs.get("target")
|
||||
|
||||
monkeypatch.setattr(cli, "manifest", fake_manifest)
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
[
|
||||
"enroll",
|
||||
"manifest",
|
||||
"--harvest",
|
||||
str(tmp_path / "bundle"),
|
||||
"--out",
|
||||
str(tmp_path / "puppet"),
|
||||
"--target",
|
||||
"puppet",
|
||||
],
|
||||
)
|
||||
|
||||
cli.main()
|
||||
assert called["harvest"] == str(tmp_path / "bundle")
|
||||
assert called["out"] == str(tmp_path / "puppet")
|
||||
assert called["target"] == "puppet"
|
||||
|
||||
|
||||
def test_cli_manifest_no_common_roles_is_forwarded(monkeypatch, tmp_path):
|
||||
called = {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1025,7 +1025,7 @@ def test_report_markdown_with_enforcement_failed():
|
|||
},
|
||||
}
|
||||
result = _report_markdown(report)
|
||||
assert "ansible-playbook failed" in result
|
||||
assert "but failed" in result
|
||||
|
||||
|
||||
def test_report_markdown_with_enforcement_skipped():
|
||||
|
|
@ -1378,7 +1378,7 @@ def test_report_text_with_enforcement_applied():
|
|||
}
|
||||
result = d._report_text(report)
|
||||
assert "Enforcement" in result
|
||||
assert "applied old harvest via ansible-playbook" in result
|
||||
assert "applied old harvest" in result
|
||||
assert "tags=test" in result
|
||||
|
||||
|
||||
|
|
@ -1398,7 +1398,7 @@ def test_report_text_with_enforcement_failed():
|
|||
}
|
||||
result = d._report_text(report)
|
||||
assert "Enforcement" in result
|
||||
assert "ansible-playbook failed" in result
|
||||
assert "failed" in result
|
||||
|
||||
|
||||
def test_report_text_with_enforcement_skipped():
|
||||
|
|
|
|||
|
|
@ -218,18 +218,6 @@ def test_diff_exclude_path_only_filters_files_not_packages(tmp_path: Path):
|
|||
assert report["packages"]["added"] == ["htop"]
|
||||
|
||||
|
||||
def test_enforce_old_harvest_requires_ansible_playbook(monkeypatch, tmp_path: Path):
|
||||
import enroll.diff as d
|
||||
|
||||
monkeypatch.setattr(d.shutil, "which", lambda name: None)
|
||||
|
||||
old = tmp_path / "old"
|
||||
_write_bundle(old, {"inventory": {"packages": {}}, "roles": _minimal_roles()})
|
||||
|
||||
with pytest.raises(RuntimeError, match="ansible-playbook not found"):
|
||||
d.enforce_old_harvest(str(old))
|
||||
|
||||
|
||||
def test_enforce_old_harvest_runs_ansible_with_tags_from_file_drift(
|
||||
monkeypatch, tmp_path: Path
|
||||
):
|
||||
|
|
@ -310,121 +298,6 @@ def test_enforce_old_harvest_runs_ansible_with_tags_from_file_drift(
|
|||
assert "role_usr_local_custom" in str(argv[i + 1])
|
||||
|
||||
|
||||
def test_enforce_old_harvest_runs_puppet_target(monkeypatch, tmp_path: Path):
|
||||
import enroll.diff as d
|
||||
import enroll.manifest as mf
|
||||
|
||||
monkeypatch.setattr(
|
||||
d.shutil,
|
||||
"which",
|
||||
lambda name: "/usr/bin/puppet" if name == "puppet" else None,
|
||||
)
|
||||
|
||||
calls: dict[str, object] = {}
|
||||
|
||||
def fake_manifest(_harvest_dir: str, out_dir: str, **kwargs):
|
||||
calls["manifest_target"] = kwargs.get("target")
|
||||
out = Path(out_dir)
|
||||
(out / "manifests").mkdir(parents=True)
|
||||
(out / "modules").mkdir(parents=True)
|
||||
(out / "manifests" / "site.pp").write_text(
|
||||
"node default { }\n", encoding="utf-8"
|
||||
)
|
||||
|
||||
monkeypatch.setattr(mf, "manifest", fake_manifest)
|
||||
|
||||
def fake_run(
|
||||
argv, cwd=None, env=None, capture_output=False, text=False, check=False
|
||||
):
|
||||
calls["argv"] = list(argv)
|
||||
calls["cwd"] = cwd
|
||||
return types.SimpleNamespace(returncode=0, stdout="ok", stderr="")
|
||||
|
||||
monkeypatch.setattr(d.subprocess, "run", fake_run)
|
||||
|
||||
old = tmp_path / "old"
|
||||
_write_bundle(old, {"inventory": {"packages": {}}, "roles": _minimal_roles()})
|
||||
|
||||
report = {
|
||||
"packages": {"added": [], "removed": ["curl"], "version_changed": []},
|
||||
"services": {"enabled_added": [], "enabled_removed": [], "changed": []},
|
||||
"users": {"added": [], "removed": [], "changed": []},
|
||||
"files": {"added": [], "removed": [], "changed": []},
|
||||
}
|
||||
|
||||
info = d.enforce_old_harvest(str(old), report=report, target="puppet")
|
||||
|
||||
assert info["status"] == "applied"
|
||||
assert info["target"] == "puppet"
|
||||
assert info["tool"] == "puppet apply"
|
||||
assert info["scope"] == "full_manifest"
|
||||
assert info["tags"] == []
|
||||
assert calls["manifest_target"] == "puppet"
|
||||
|
||||
argv = calls.get("argv")
|
||||
assert argv and argv[:2] == ["/usr/bin/puppet", "apply"]
|
||||
assert "--modulepath" in argv
|
||||
assert any(
|
||||
str(Path(calls["cwd"]) / "manifest" / "manifests" / "site.pp") == str(a)
|
||||
for a in argv
|
||||
)
|
||||
|
||||
|
||||
def test_enforce_old_harvest_runs_salt_target(monkeypatch, tmp_path: Path):
|
||||
import enroll.diff as d
|
||||
import enroll.manifest as mf
|
||||
|
||||
monkeypatch.setattr(
|
||||
d.shutil,
|
||||
"which",
|
||||
lambda name: "/usr/bin/salt-call" if name == "salt-call" else None,
|
||||
)
|
||||
|
||||
calls: dict[str, object] = {}
|
||||
|
||||
def fake_manifest(_harvest_dir: str, out_dir: str, **kwargs):
|
||||
calls["manifest_target"] = kwargs.get("target")
|
||||
out = Path(out_dir)
|
||||
(out / "states").mkdir(parents=True)
|
||||
(out / "states" / "top.sls").write_text("base:\n '*': []\n", encoding="utf-8")
|
||||
|
||||
monkeypatch.setattr(mf, "manifest", fake_manifest)
|
||||
|
||||
def fake_run(
|
||||
argv, cwd=None, env=None, capture_output=False, text=False, check=False
|
||||
):
|
||||
calls["argv"] = list(argv)
|
||||
calls["cwd"] = cwd
|
||||
return types.SimpleNamespace(returncode=0, stdout="ok", stderr="")
|
||||
|
||||
monkeypatch.setattr(d.subprocess, "run", fake_run)
|
||||
|
||||
old = tmp_path / "old"
|
||||
_write_bundle(old, {"inventory": {"packages": {}}, "roles": _minimal_roles()})
|
||||
|
||||
report = {
|
||||
"packages": {"added": [], "removed": ["curl"], "version_changed": []},
|
||||
"services": {"enabled_added": [], "enabled_removed": [], "changed": []},
|
||||
"users": {"added": [], "removed": [], "changed": []},
|
||||
"files": {"added": [], "removed": [], "changed": []},
|
||||
}
|
||||
|
||||
info = d.enforce_old_harvest(str(old), report=report, target="salt")
|
||||
|
||||
assert info["status"] == "applied"
|
||||
assert info["target"] == "salt"
|
||||
assert info["tool"] == "salt-call"
|
||||
assert info["scope"] == "full_manifest"
|
||||
assert calls["manifest_target"] == "salt"
|
||||
|
||||
argv = calls.get("argv")
|
||||
assert argv and argv[0] == "/usr/bin/salt-call"
|
||||
assert "--local" in argv
|
||||
assert "--file-root" in argv
|
||||
assert "state.apply" in argv
|
||||
assert str(Path(calls["cwd"]) / "manifest" / "states") in argv
|
||||
|
||||
|
||||
def test_cli_diff_enforce_forwards_target(monkeypatch):
|
||||
import enroll.cli as cli
|
||||
|
||||
|
|
@ -458,17 +331,38 @@ def test_cli_diff_enforce_forwards_target(monkeypatch):
|
|||
"--new",
|
||||
"/tmp/new",
|
||||
"--enforce",
|
||||
"--target",
|
||||
"puppet",
|
||||
],
|
||||
)
|
||||
|
||||
cli.main()
|
||||
assert calls["old"] == "/tmp/old"
|
||||
assert calls["target"] == "puppet"
|
||||
assert calls["report"] is report
|
||||
|
||||
|
||||
def test_cli_diff_enforce_rejects_non_ansible_target(monkeypatch):
|
||||
"""Salt and Puppet targets have been removed from --enforce."""
|
||||
import enroll.cli as cli
|
||||
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
[
|
||||
"enroll",
|
||||
"diff",
|
||||
"--old",
|
||||
"/tmp/old",
|
||||
"--new",
|
||||
"/tmp/new",
|
||||
"--enforce",
|
||||
"--target",
|
||||
"puppet",
|
||||
],
|
||||
)
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
|
||||
def test_cli_diff_forwards_exclude_and_ignore_flags(monkeypatch, capsys):
|
||||
import enroll.cli as cli
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ def test_ansible_static_marks_harvested_jinja_values_unsafe(tmp_path: Path):
|
|||
payload = "{{ lookup('pipe','touch /tmp/PWNED_BY_ENROLL_ANSIBLE') }}"
|
||||
write_schema_state(bundle, _ansible_jinja_payload_state(payload))
|
||||
|
||||
manifest.manifest(str(bundle), str(out), target="ansible")
|
||||
manifest.manifest(str(bundle), str(out))
|
||||
|
||||
defaults = out / "roles" / "users" / "defaults" / "main.yml"
|
||||
text = defaults.read_text(encoding="utf-8")
|
||||
|
|
@ -152,7 +152,7 @@ def test_ansible_fqdn_marks_harvested_jinja_values_unsafe(tmp_path: Path):
|
|||
payload = "{{ lookup('pipe','touch /tmp/PWNED_BY_ENROLL_ANSIBLE') }}"
|
||||
write_schema_state(bundle, _ansible_jinja_payload_state(payload))
|
||||
|
||||
manifest.manifest(str(bundle), str(out), target="ansible", fqdn="host.example.test")
|
||||
manifest.manifest(str(bundle), str(out), fqdn="host.example.test")
|
||||
|
||||
hostvars = out / "inventory" / "host_vars" / "host.example.test" / "users.yml"
|
||||
text = hostvars.read_text(encoding="utf-8")
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
74
tests/test_secret_detection.py
Normal file
74
tests/test_secret_detection.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
"""Regression test: safe-mode content sniff must catch URI-embedded credentials
|
||||
and HTTP Authorization headers, not just assignment-style credential keys."""
|
||||
|
||||
from enroll.ignore import IgnorePolicy
|
||||
|
||||
|
||||
def test_uri_embedded_credentials_denied():
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
leaking = [
|
||||
b"DATABASE_URL=postgresql://admin:S3cr3tPass@db:5432/app\n",
|
||||
b"REDIS_URL=redis://:mypassword@localhost:6379/0\n",
|
||||
b"broker_url = amqp://guest:guest@rabbit:5672//\n",
|
||||
b"uri: mongodb+srv://user:p%40ss@cluster0.mongodb.net\n",
|
||||
]
|
||||
for data in leaking:
|
||||
assert (
|
||||
pol._content_deny_reason("/etc/svc/app.conf", data) == "sensitive_content"
|
||||
), data
|
||||
|
||||
|
||||
def test_authorization_headers_denied():
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
for data in [
|
||||
b"Authorization: Bearer eyJhbGciOiJIUzI1NiIs\n",
|
||||
b"Authorization: Basic dXNlcjpwYXNzd29yZA==\n",
|
||||
b"Proxy-Authorization: Bearer xyz\n",
|
||||
]:
|
||||
assert (
|
||||
pol._content_deny_reason("/etc/svc/app.conf", data) == "sensitive_content"
|
||||
), data
|
||||
|
||||
|
||||
def test_benign_urls_not_false_positive():
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
for data in [
|
||||
b"homepage = https://example.com/docs\n",
|
||||
b"server = http://localhost:8080/api\n",
|
||||
b"origin = git://github.com/u/repo.git\n",
|
||||
b"bind = http://[::1]:9000/\n",
|
||||
b"contact = mailto:admin@example.com\n",
|
||||
b"log_level = info\nworkers = 4\n",
|
||||
]:
|
||||
assert pol._content_deny_reason("/etc/svc/app.conf", data) is None, data
|
||||
|
||||
|
||||
def test_bare_word_password_denied():
|
||||
"""Credential lines using the word password/passphrase/credentials without
|
||||
an assignment delimiter (netrc, ppp, space/tab separated) must be denied."""
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
for data in [
|
||||
b"machine api.example.com login bob password s3cret\n",
|
||||
b"passphrase mysecretphrase\n",
|
||||
b"credentials /run/creds/db\n",
|
||||
]:
|
||||
assert (
|
||||
pol._content_deny_reason("/etc/svc.conf", data) == "sensitive_content"
|
||||
), data
|
||||
|
||||
|
||||
def test_ppp_secrets_paths_denied():
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
for p in ("/etc/ppp/chap-secrets", "/etc/ppp/pap-secrets", "/etc/ppp/my-secrets"):
|
||||
assert pol._path_deny_reason(p) == "denied_path", p
|
||||
|
||||
|
||||
def test_password_keyword_no_false_positives():
|
||||
pol = IgnorePolicy(dangerous=False)
|
||||
for data in [
|
||||
b"passive_mode = true\n",
|
||||
b"PassengerRoot /usr/lib\n",
|
||||
b"description = reset the account\n",
|
||||
b"compression = gzip\n",
|
||||
]:
|
||||
assert pol._content_deny_reason("/etc/app.conf", data) is None, data
|
||||
Loading…
Add table
Add a link
Reference in a new issue