Deploy Prowler CIS scanner #310

Merged
eblume merged 7 commits from deploy-prowler into main 2026-03-24 16:08:10 -07:00
12 changed files with 289 additions and 0 deletions
Showing only changes of commit a97391177a - Show all commits

Deploy Prowler CIS scanner as weekly CronJob on minikube-indri

Custom slim container (no PowerShell/Trivy), NFS-backed reports
on sifaka:/volume1/reports/prowler/, ClusterRole with read-only
RBAC for Kubernetes CIS Benchmark v1.11 checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Erich Blume 2026-03-24 15:00:48 -07:00

17
argocd/apps/prowler.yaml Normal file
View file

@ -0,0 +1,17 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prowler
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
path: argocd/manifests/prowler
destination:
server: https://kubernetes.default.svc
namespace: prowler
syncPolicy:
syncOptions:
- CreateNamespace=true

View file

@ -0,0 +1,53 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: prowler
namespace: prowler
spec:
schedule: "0 3 * * 0" # Sunday 3am
concurrencyPolicy: Forbid
jobTemplate:
spec:
ttlSecondsAfterFinished: 604800 # Auto-delete after 7 days
template:
spec:
serviceAccountName: prowler
containers:
- name: prowler
image: registry.ops.eblu.me/blumeops/prowler:kustomized
args:
- kubernetes
- --compliance
- cis_1.11_kubernetes
- -z
- --output-formats
- html,csv,json-ocsf
- --output-directory
- /reports
volumeMounts:
- name: reports
mountPath: /reports
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
- name: var-lib-etcd
mountPath: /var/lib/etcd
readOnly: true
hostPID: true
restartPolicy: OnFailure
volumes:
- name: reports
persistentVolumeClaim:
claimName: prowler-reports
- name: var-lib-kubelet
hostPath:
path: /var/lib/kubelet
- name: etc-kubernetes
hostPath:
path: /etc/kubernetes
- name: var-lib-etcd
hostPath:
path: /var/lib/etcd

View file

@ -0,0 +1,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prowler
resources:
- serviceaccount.yaml
- rbac.yaml
- pv-nfs.yaml
- pvc.yaml
- cronjob.yaml
images:
- name: registry.ops.eblu.me/blumeops/prowler
newTag: v5.22.0-placeholder

View file

@ -0,0 +1,22 @@
# NFS PersistentVolume for Prowler compliance reports
# Requires: NFS share on sifaka at /volume1/reports with NFS permissions for indri
#
# To create on Synology:
# 1. Control Panel > Shared Folder > Create
# 2. Name: reports, Location: Volume 1
# 3. Control Panel > File Services > NFS > NFS Rules
# 4. Add rule for "reports" share: Hostname=indri, Privilege=Read/Write, Squash=No mapping
apiVersion: v1
kind: PersistentVolume
metadata:
name: prowler-reports-nfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
nfs:
server: sifaka
path: /volume1/reports/prowler

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: prowler-reports
namespace: prowler
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
volumeName: prowler-reports-nfs-pv
resources:
requests:
storage: 10Gi

View file

@ -0,0 +1,24 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prowler-reader
rules:
- apiGroups: [""]
resources: ["pods", "configmaps", "nodes", "namespaces"]
verbs: ["get", "list", "watch"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prowler-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prowler-reader
subjects:
- kind: ServiceAccount
name: prowler
namespace: prowler

View file

@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: prowler
namespace: prowler

View file

@ -0,0 +1,45 @@
# Prowler CIS scanner — slim build for Kubernetes provider only
# Strips PowerShell (M365), Trivy (IaC), and dashboard dependencies from upstream
ARG CONTAINER_APP_VERSION=5.22.0
FROM python:3.12-slim-bookworm AS build
ARG CONTAINER_APP_VERSION
RUN apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
RUN git clone --depth 1 --branch ${CONTAINER_APP_VERSION} \
https://github.com/prowler-cloud/prowler.git .
# Install prowler into a virtualenv so we can copy it cleanly
RUN python -m venv /opt/prowler \
&& /opt/prowler/bin/pip install --no-cache-dir --upgrade pip \
&& /opt/prowler/bin/pip install --no-cache-dir .
# ---
FROM python:3.12-slim-bookworm
ARG CONTAINER_APP_VERSION
LABEL org.opencontainers.image.title="prowler"
LABEL org.opencontainers.image.version="${CONTAINER_APP_VERSION}"
LABEL org.opencontainers.image.source="https://forge.ops.eblu.me/eblume/blumeops"
LABEL org.opencontainers.image.vendor="blumeops"
LABEL org.opencontainers.image.description="Prowler CIS scanner (Kubernetes provider)"
RUN addgroup --gid 1000 prowler \
&& adduser --uid 1000 --gid 1000 --disabled-password --gecos "" prowler
COPY --from=build /opt/prowler /opt/prowler
ENV PATH="/opt/prowler/bin:${PATH}"
USER prowler
WORKDIR /home/prowler
ENTRYPOINT ["prowler"]

View file

@ -0,0 +1 @@
Deploy Prowler CIS scanner as a weekly CronJob on minikube-indri, with reports written to sifaka NFS share.

View file

@ -0,0 +1,63 @@
---
title: Deploy Prowler CIS Scanner
modified: 2026-03-24
last-reviewed: 2026-03-24
tags:
- how-to
- kubernetes
- security
- compliance
---
# Deploy Prowler CIS Scanner
Prowler runs weekly CIS Kubernetes Benchmark scans against minikube-indri and writes HTML/CSV/JSON reports to the NFS share on sifaka.
## What it checks
Prowler's Kubernetes provider runs ~70 checks from the CIS Kubernetes Benchmark v1.11, grouped into:
| Category | Checks | How it works |
|----------|--------|-------------|
| **Core (pod security)** | 13 | Queries K8s API for privileged containers, hostPID/hostNetwork, capabilities, secrets in env vars, seccomp |
| **RBAC** | 9 | Queries RBAC API for overprivileged roles, wildcard access, cluster-admin bindings |
| **Apiserver** | 29 | Inspects `kube-apiserver` pod args in kube-system (TLS, auth, audit, admission plugins) |
| **Etcd** | 7 | Inspects `etcd` pod args (TLS, cert auth) |
| **Controller Manager** | 7 | Inspects `kube-controller-manager` pod args |
| **Kubelet** | 16 | Reads kubelet-config ConfigMap + node file permissions (file checks need hostPID) |
| **Scheduler** | 2 | Inspects `kube-scheduler` pod args |
**Minikube relevance:** Most checks work because minikube runs control plane as static pods. Kubelet file permission checks return MANUAL unless Prowler runs on the node (we mount host paths to enable this).
**k3s note:** k3s embeds the control plane in a single binary — no static pods exist. Only core + RBAC checks (~22 of 70) produce results. Consider `kube-bench` for k3s control plane checks.
## Reports
Reports are written to `sifaka:/volume1/reports/prowler/<date>/` in three formats:
- **HTML** — human-readable, self-contained, filterable
- **CSV** — flat tabular, one row per finding
- **JSON-OCSF** — structured, for SIEM ingestion
## Running an ad-hoc scan
```fish
kubectl create job --from=cronjob/prowler prowler-manual -n prowler --context=minikube-indri
```
Watch progress:
```fish
kubectl logs -f job/prowler-manual -n prowler --context=minikube-indri
```
## Container
Custom slim build at `containers/prowler/Dockerfile` — strips PowerShell, Trivy, and non-Kubernetes providers from upstream. See [[build-container-image]] for the build/release process.
**TODO:** Mirror prowler-cloud/prowler on forge for supply chain control.
## See also
- [[deploy-k8s-service]] — general K8s deployment how-to
- [[build-container-image]] — container build pipeline

View file

@ -40,6 +40,7 @@ Registry of all applications deployed via [[argocd]].
| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[forgejo]] CI |
| `ollama` | ollama | `argocd/manifests/ollama/` | [[ollama]] |
| `mealie` | mealie | `argocd/manifests/mealie/` | [[mealie]] |
| `prowler` | prowler | `argocd/manifests/prowler/` | [[prowler]] |
## Sync Policies

View file

@ -0,0 +1,30 @@
---
title: Prowler
modified: 2026-03-24
last-reviewed: 2026-03-24
tags:
- service
- security
---
# Prowler
CIS Kubernetes Benchmark scanner for compliance posture reporting.
## Quick Reference
| Property | Value |
|----------|-------|
| **Namespace** | `prowler` |
| **Image** | `registry.ops.eblu.me/blumeops/prowler` (see `argocd/manifests/prowler/kustomization.yaml` for current tag) |
| **Schedule** | Weekly (Sunday 3am) |
| **Reports** | `sifaka:/volume1/reports/prowler/` (NFS) |
| **Manifests** | `argocd/manifests/prowler/` |
## What it does
Runs Prowler 5 as a CronJob against minikube-indri, executing CIS Kubernetes Benchmark v1.11 checks across pod security, RBAC, apiserver, etcd, kubelet, controller-manager, and scheduler. Reports are written in HTML, CSV, and JSON-OCSF to the NFS share on sifaka.
## See also
- [[deploy-prowler]] — deployment how-to, ad-hoc scan instructions, check relevance notes