157 lines
4.8 KiB
Python
157 lines
4.8 KiB
Python
# CP2A2.2B — L1 Red Queen Worker: Credential-Zero-Test
|
|
# STRICTLY NON-AUTONOMOUS / NON-PRODUCTIVE.
|
|
#
|
|
# Verifiziert, dass der Worker KEINE mutierenden Credentials besitzt.
|
|
# Report NUR PRESENT/ABSENT — NIEMALS Secret-Werte ausgeben.
|
|
#
|
|
# Geprueft werden:
|
|
# - ENV-Variablen (mutierende Credential-Namen)
|
|
# - config.yaml (worker-config.yaml)
|
|
# - Home-Verzeichnis (keine .netrc, .git-credentials, SSH-Keys)
|
|
# - git config (keine credential helpers)
|
|
# - mounted secrets
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
|
|
# Mutierende Credential-Namen (nur Namen, keine Werte)
|
|
MUTATING_CREDENTIAL_NAMES = [
|
|
"FORGEJO_WRITE_TOKEN",
|
|
"NOTION_API_KEY",
|
|
"TELEGRAM_BOT_TOKEN",
|
|
"SAVE_TOKEN",
|
|
"DELETE_TOKEN",
|
|
"TOLARIA_SAVE_TOKEN",
|
|
"TOLARIA_DELETE_TOKEN",
|
|
"GITHUB_TOKEN",
|
|
"GITLAB_TOKEN",
|
|
"AWS_ACCESS_KEY_ID",
|
|
"AWS_SECRET_ACCESS_KEY",
|
|
"AZURE_CLIENT_SECRET",
|
|
"GCP_SA_KEY",
|
|
"DOCKER_AUTH_CONFIG",
|
|
"DOCKER_CONFIG",
|
|
"IG_API_KEY",
|
|
"IG_ACCESS_TOKEN",
|
|
"BROKER_API_KEY",
|
|
"BROKER_TOKEN",
|
|
"TRADING_TOKEN",
|
|
"WEBHOOK_SECRET",
|
|
"SERVICE_ACCOUNT_KEY",
|
|
"DB_PASSWORD",
|
|
"POSTGRES_PASSWORD",
|
|
"MYSQL_PASSWORD",
|
|
"REDIS_PASSWORD",
|
|
"MONGO_PASSWORD",
|
|
]
|
|
|
|
# Dateien, die Credentials enthalten koennten (im Home/Config)
|
|
CREDENTIAL_FILE_PATTERNS = [
|
|
".netrc",
|
|
".git-credentials",
|
|
".pgpass",
|
|
".my.cnf",
|
|
".aws/credentials",
|
|
".config/gcloud/application_default_credentials.json",
|
|
".docker/config.json",
|
|
"id_rsa",
|
|
"id_ed25519",
|
|
"id_dsa",
|
|
"id_ecdsa",
|
|
]
|
|
|
|
|
|
def check_env() -> list[str]:
|
|
"""Prueft ENV auf mutierende Credential-Namen. Gibt gefundene Namen zurueck."""
|
|
found = []
|
|
for name in MUTATING_CREDENTIAL_NAMES:
|
|
if name in os.environ:
|
|
found.append(name)
|
|
return found
|
|
|
|
|
|
def check_config(config_path: str) -> list[str]:
|
|
"""Prueft die Worker-Config auf mutierende Credential-Namen.
|
|
|
|
Ignoriert Kommentare (Zeilen mit #) — Kommentare sind Dokumentation,
|
|
keine tatsaechlichen Credentials. Prueft nur echte YAML-Keys/Werte.
|
|
"""
|
|
found = []
|
|
if not os.path.exists(config_path):
|
|
return found
|
|
try:
|
|
with open(config_path, "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
# Nur Nicht-Kommentar-Zeilen pruefen
|
|
content = "\n".join(
|
|
line for line in lines if not line.lstrip().startswith("#")
|
|
)
|
|
for name in MUTATING_CREDENTIAL_NAMES:
|
|
if name in content:
|
|
found.append(name)
|
|
# Generische Secret-Schluessel in YAML (nur echte Keys, nicht Kommentare)
|
|
for key in ["token", "api_key", "secret", "password", "bearer"]:
|
|
if re.search(rf"^\s*{key}\s*:", content, re.IGNORECASE | re.MULTILINE):
|
|
found.append(f"config-key:{key}")
|
|
except Exception:
|
|
pass
|
|
return found
|
|
|
|
|
|
def check_home(home: str) -> list[str]:
|
|
"""Prueft Home-Verzeichnis auf Credential-Dateien/SSH-Keys."""
|
|
found = []
|
|
for pattern in CREDENTIAL_FILE_PATTERNS:
|
|
path = os.path.join(home, pattern)
|
|
if os.path.exists(path):
|
|
found.append(pattern)
|
|
# SSH-Verzeichnis
|
|
ssh_dir = os.path.join(home, ".ssh")
|
|
if os.path.isdir(ssh_dir):
|
|
for entry in os.listdir(ssh_dir):
|
|
if entry not in ("known_hosts", "config"):
|
|
found.append(f".ssh/{entry}")
|
|
return found
|
|
|
|
|
|
def check_git_config(home: str) -> list[str]:
|
|
"""Prueft git config auf credential helpers."""
|
|
found = []
|
|
git_config = os.path.join(home, ".gitconfig")
|
|
if os.path.exists(git_config):
|
|
try:
|
|
with open(git_config, "r", encoding="utf-8") as f:
|
|
content = f.read()
|
|
if "credential" in content.lower() and "helper" in content.lower():
|
|
found.append("git-credential-helper")
|
|
except Exception:
|
|
pass
|
|
return found
|
|
|
|
|
|
def main() -> int:
|
|
home = os.environ.get("HOME", "/opt/data")
|
|
config_path = os.environ.get("WORKER_CONFIG", "/opt/l1-worker/worker-config.yaml")
|
|
|
|
env_found = check_env()
|
|
config_found = check_config(config_path)
|
|
home_found = check_home(home)
|
|
git_found = check_git_config(home)
|
|
|
|
all_found = sorted(set(env_found + config_found + home_found + git_found))
|
|
|
|
print("=== CP2A2.2B CREDENTIAL-ZERO TEST ===")
|
|
print(f"ENV mutating credentials: {env_found if env_found else 'ABSENT'}")
|
|
print(f"Config mutating credentials: {config_found if config_found else 'ABSENT'}")
|
|
print(f"Home credential files: {home_found if home_found else 'ABSENT'}")
|
|
print(f"Git credential helpers: {git_found if git_found else 'ABSENT'}")
|
|
print(f"TOTAL MUTATING CREDENTIALS: {len(all_found)}")
|
|
print(f"RESULT: {'PASS' if not all_found else 'FAIL'}")
|
|
|
|
return 0 if not all_found else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|