Deploy Prowler CIS scanner (#310)
All checks were successful
Build Container / detect (push) Successful in 4s
Build Container / build-dockerfile (prowler) (push) Successful in 10s

## Summary
- Deploy Prowler 5 as a weekly CronJob on minikube-indri for CIS Kubernetes Benchmark v1.11 scanning
- Custom slim container build (strips PowerShell, Trivy, and non-K8s providers from upstream)
- Reports (HTML, CSV, JSON-OCSF) written to NFS share on sifaka at `/volume1/reports/prowler/`
- Read-only ClusterRole for pod, RBAC, and control plane inspection
- Host path mounts + hostPID for kubelet file permission checks

## Follow-ups
- Mirror prowler-cloud/prowler on forge for supply chain control
- Build and push container image, update kustomization.yaml newTag
- Consider adding k3s-ringtail scanning (core + RBAC checks only)

## Test plan
- [ ] Build container: `mise run container-release prowler v5.22.0`
- [ ] Update `argocd/manifests/prowler/kustomization.yaml` newTag to built image tag
- [ ] Sync ArgoCD: `argocd app sync apps && argocd app set prowler --revision deploy-prowler && argocd app sync prowler`
- [ ] Trigger manual job: `kubectl create job --from=cronjob/prowler prowler-manual -n prowler --context=minikube-indri`
- [ ] Verify reports appear on sifaka NFS share
- [ ] `mise run services-check`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #310
This commit is contained in:
Erich Blume 2026-03-24 16:08:09 -07:00
commit d021b3534f
16 changed files with 449 additions and 25 deletions

View file

@ -7,10 +7,10 @@
#USAGE arg "<container>" help="Container name (directory under containers/)"
#USAGE flag "--ref <ref>" help="Commit SHA or branch to build (defaults to current HEAD)"
#USAGE flag "--dry-run" help="Show what would be done without triggering"
"""Trigger container build workflows via Forgejo API dispatch.
"""Trigger container build workflow via Forgejo API dispatch.
Dispatches both Build Container and Build Container (Nix) workflows.
Each workflow checks for its build file and skips if not present.
Dispatches the unified build-container workflow, which handles both
Dockerfile and Nix builds in a single workflow.
"""
import subprocess
@ -26,10 +26,7 @@ FORGE_API = f"{FORGE_URL}/api/v1"
REPO = "eblume/blumeops"
FORGE_ACTIONS = f"{FORGE_URL}/{REPO}/actions"
WORKFLOWS = [
"build-container.yaml",
"build-container-nix.yaml",
]
WORKFLOW = "build-container.yaml"
app = typer.Typer(add_completion=False)
@ -108,9 +105,7 @@ def main(
typer.echo()
if dry_run:
typer.echo("[dry-run] Would dispatch workflows:")
for wf in WORKFLOWS:
typer.echo(f" - {wf}")
typer.echo(f"[dry-run] Would dispatch {WORKFLOW}")
typer.echo()
typer.echo(f"Monitor builds at: {FORGE_ACTIONS}")
return
@ -121,21 +116,20 @@ def main(
"Content-Type": "application/json",
}
for wf in WORKFLOWS:
url = f"{FORGE_API}/repos/{REPO}/actions/workflows/{wf}/dispatches"
payload = {
"ref": "main",
"inputs": {
"container": container,
"ref": ref,
},
}
resp = httpx.post(url, json=payload, headers=headers, timeout=30)
if resp.status_code == 204:
typer.echo(f"Dispatched {wf}")
else:
typer.echo(f"Error dispatching {wf}: {resp.status_code} {resp.text}")
raise typer.Exit(1)
url = f"{FORGE_API}/repos/{REPO}/actions/workflows/{WORKFLOW}/dispatches"
payload = {
"ref": "main",
"inputs": {
"container": container,
"ref": ref,
},
}
resp = httpx.post(url, json=payload, headers=headers, timeout=30)
if resp.status_code == 204:
typer.echo(f"Dispatched {WORKFLOW}")
else:
typer.echo(f"Error dispatching {WORKFLOW}: {resp.status_code} {resp.text}")
raise typer.Exit(1)
typer.echo()
typer.echo(f"Monitor builds at: {FORGE_ACTIONS}")