From 7ae26163088f2c1e4d2cffbb2de8aa28201100fa Mon Sep 17 00:00:00 2001 From: Junwei Zhao Date: Wed, 1 Apr 2026 19:51:16 +1100 Subject: [PATCH] Add crowdsec auto ban --- adhoc-config/crowdsec-nginx-sync.yaml | 117 ++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 adhoc-config/crowdsec-nginx-sync.yaml diff --git a/adhoc-config/crowdsec-nginx-sync.yaml b/adhoc-config/crowdsec-nginx-sync.yaml new file mode 100644 index 0000000..18ef830 --- /dev/null +++ b/adhoc-config/crowdsec-nginx-sync.yaml @@ -0,0 +1,117 @@ +--- +# CrowdSec → NGINX Ingress IP Block Sync +# +# Runs every minute, reads all active CrowdSec ban decisions, +# and updates the NGINX Ingress Controller ConfigMap's block-cidrs field. +# This propagates CrowdSec's automated threat detection into NGINX's global IP blocklist. + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: crowdsec-nginx-sync + namespace: crowdsec + +--- +# Allow the sync job to read CrowdSec LAPI pod exec (to run cscli) +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: crowdsec-nginx-sync +rules: + # Exec into CrowdSec LAPI pod to run cscli + - apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] + # Read/patch the NGINX Ingress ConfigMap + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "patch"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: crowdsec-nginx-sync +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: crowdsec-nginx-sync +subjects: + - kind: ServiceAccount + name: crowdsec-nginx-sync + namespace: crowdsec + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: crowdsec-nginx-sync + namespace: crowdsec +spec: + schedule: "* * * * *" # every minute + concurrencyPolicy: Forbid # skip if previous run is still going + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + activeDeadlineSeconds: 55 # must finish before next run + template: + spec: + serviceAccountName: crowdsec-nginx-sync + restartPolicy: Never + containers: + - name: sync + image: bitnami/kubectl:latest + command: + - /bin/sh + - -c + - | + set -e + + # Find the CrowdSec LAPI pod + LAPI_POD=$(kubectl get pods -n crowdsec \ + -l "type=lapi" \ + -o jsonpath='{.items[0].metadata.name}') + + if [ -z "$LAPI_POD" ]; then + echo "ERROR: CrowdSec LAPI pod not found" + exit 1 + fi + + echo "Using LAPI pod: $LAPI_POD" + + # Fetch all active ban decisions in raw CSV format: + # id,source,ip,reason,action,country,as,events_count,expiration,simulated,alert_id + # The ip column has format "Ip:1.2.3.4" or "Range:1.2.3.0/24" + RAW=$(kubectl exec -n crowdsec "$LAPI_POD" -- \ + cscli decisions list -t ban -o raw 2>/dev/null || true) + + # Skip CSV header, extract column 3, strip the "Ip:" / "Range:" prefix + CIDRS=$(echo "$RAW" | \ + tail -n +2 | \ + cut -d',' -f3 | \ + sed 's/^[^:]*://g' | \ + grep -v '^$' | \ + tr '\n' ',' | \ + sed 's/,$//') + + echo "Active ban count: $(echo "$RAW" | tail -n +2 | grep -c '.' || echo 0)" + echo "Blocked CIDRs: ${CIDRS:-}" + + # Patch the NGINX Ingress ConfigMap (JSON merge patch — only updates block-cidrs) + kubectl patch configmap ingress-nginx-controller \ + -n ingress-nginx \ + --type merge \ + -p "{\"data\":{\"block-cidrs\":\"${CIDRS}\"}}" + + echo "ConfigMap patched successfully" + resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 100m + memory: 64Mi