Rename secrets to ignore as it does more than secrets
All checks were successful
CI / test (push) Successful in 5m35s
Lint / test (push) Successful in 27s
Trivy / test (push) Successful in 17s

This commit is contained in:
Miguel Jacq 2025-12-15 17:03:28 +11:00
parent 4882ddff49
commit e4be7f5975
Signed by: mig5
GPG key ID: 59B3F0C24135C6A9
7 changed files with 51 additions and 15 deletions

View file

@ -1,3 +1,8 @@
# 0.0.4
* Fix dash package detection issue
* Reorder which roles install first
# 0.0.3
* various bug fixes

9
debian/changelog vendored
View file

@ -1,5 +1,12 @@
enroll (0.0.4) unstable; urgency=medium
* Fix dash package detection issue
* Reorder which roles install first
-- Miguel Jacq <mig@mig5.net> Mon, 15 Dec 2025 17:00:00 +1100
enroll (0.0.3) unstable; urgency=medium
* Initial package
-- Miguel Jacq <mig@mig5.net> Mon, 15 Dec 2025 12:00:00 +0000
-- Miguel Jacq <mig@mig5.net> Mon, 15 Dec 2025 12:00:00 +1100

View file

@ -6,6 +6,8 @@ import os
import subprocess # nosec
from typing import Dict, List, Optional, Set, Tuple
_DIVERSION_PREFIX = "diversion by "
def _run(cmd: list[str]) -> str:
p = subprocess.run(cmd, check=False, text=True, capture_output=True) # nosec
@ -18,9 +20,32 @@ def dpkg_owner(path: str) -> Optional[str]:
p = subprocess.run(["dpkg", "-S", path], text=True, capture_output=True) # nosec
if p.returncode != 0:
return None
left = p.stdout.split(":", 1)[0].strip()
pkg = left.split(":", 1)[0].strip()
return pkg or None
for raw in (p.stdout or "").splitlines():
line = raw.strip()
if not line:
continue
# dpkg diversion chatter; not an ownership line
if line.startswith(_DIVERSION_PREFIX):
continue
# Expected: "<pkg>[, <pkg2>...][:<arch>]: <path>"
if ":" not in line:
continue
left, _ = line.split(":", 1)
# If multiple pkgs listed, pick the first (common case is just one)
left = left.split(",", 1)[0].strip()
# Strip any ":arch" suffix from left side
pkg = left.split(":", 1)[0].strip()
if pkg and not pkg.startswith(_DIVERSION_PREFIX):
return pkg
return None
def list_manual_packages() -> List[str]:

View file

@ -18,7 +18,7 @@ from .debian import (
read_pkg_md5sums,
stat_triplet,
)
from .secrets import SecretPolicy
from .ignore import IgnorePolicy
from .accounts import collect_non_system_users
@ -233,8 +233,8 @@ def _topdirs_for_package(pkg: str, pkg_to_etc_paths: Dict[str, List[str]]) -> Se
return topdirs
def harvest(bundle_dir: str, policy: Optional[SecretPolicy] = None) -> str:
policy = policy or SecretPolicy()
def harvest(bundle_dir: str, policy: Optional[IgnorePolicy] = None) -> str:
policy = policy or IgnorePolicy()
os.makedirs(bundle_dir, exist_ok=True)
if hasattr(os, "geteuid") and os.geteuid() != 0:
@ -487,9 +487,7 @@ def harvest(bundle_dir: str, policy: Optional[SecretPolicy] = None) -> str:
)
if not pkg_to_etc_paths.get(pkg, []) and not managed:
notes.append(
"No /etc files detected for this package."
)
notes.append("No /etc files detected for this package.")
pkg_snaps.append(
PackageSnapshot(

View file

@ -33,7 +33,7 @@ SENSITIVE_CONTENT_PATTERNS = [
@dataclass
class SecretPolicy:
class IgnorePolicy:
deny_globs: list[str] = None
max_file_bytes: int = 256_000
sample_bytes: int = 64_000

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "enroll"
version = "0.0.3"
version = "0.0.4"
description = "Enroll a server's running state retrospectively into Ansible"
authors = ["Miguel Jacq <mig@mig5.net>"]
license = "GPL-3.0-or-later"

View file

@ -1,8 +1,9 @@
from enroll.secrets import SecretPolicy
from enroll.ignore import IgnorePolicy
def test_secret_policy_denies_common_backup_files():
pol = SecretPolicy()
def test_ignore_policy_denies_common_backup_files():
pol = IgnorePolicy()
assert pol.deny_reason("/etc/shadow-") == "denied_path"
assert pol.deny_reason("/etc/passwd-") == "denied_path"
assert pol.deny_reason("/etc/group-") == "denied_path"
assert pol.deny_reason("/foobar") == "unreadable"