Reorganized for new stable/waypoint versioning design.

This commit is contained in:
2026-05-24 18:28:47 +00:00
parent 945d2225a2
commit bc7a168851
352 changed files with 1264 additions and 294 deletions

View File

@@ -0,0 +1,118 @@
# CrowdSec Security Service
CrowdSec is an open-source security engine that analyzes traffic patterns and blocks malicious actors. This service integrates CrowdSec with Traefik to provide automatic threat detection and rate limiting for all Wild Cloud ingresses.
## Components
- **CrowdSec Agent**: Analyzes traffic patterns, maintains decision lists, and connects to the CrowdSec threat intelligence network
- **Traefik Bouncer**: Integrates with Traefik via ForwardAuth to enforce CrowdSec decisions
- **Security Middlewares**: Traefik middleware for rate limiting and security headers
## Default Protection
After installation, **all ingresses are automatically protected** with:
- Threat detection (blocks known malicious IPs and attack patterns)
- Rate limiting (100 requests per minute per IP)
- Security headers (HSTS, XSS protection, content-type sniffing prevention)
## Configuration
Configuration is stored in `config.yaml` under `apps.crowdsec`:
```yaml
apps:
crowdsec:
rateLimitAverage: "100"
rateLimitBurst: "100"
```
## Secrets
Secrets are stored in `secrets.yaml` under `apps.crowdsec`:
```yaml
apps:
crowdsec:
agentPassword: <auto-generated>
bouncerApiKey: <auto-generated>
```
## Opting Out
To disable CrowdSec protection for a specific ingress (e.g., webhooks, health checks):
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
traefik.ingress.kubernetes.io/router.middlewares: ""
```
## Using Only Rate Limiting
To use rate limiting without threat detection:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
traefik.ingress.kubernetes.io/router.middlewares: crowdsec-rate-limit@kubernetescrd
```
## Monitoring
View active decisions (blocked IPs):
```bash
kubectl exec -n crowdsec deploy/crowdsec -- cscli decisions list
```
View registered bouncers:
```bash
kubectl exec -n crowdsec deploy/crowdsec -- cscli bouncers list
```
View alerts:
```bash
kubectl exec -n crowdsec deploy/crowdsec -- cscli alerts list
```
View metrics (Prometheus format):
```bash
kubectl port-forward -n crowdsec svc/crowdsec-lapi 6060:6060
curl http://localhost:6060/metrics
```
## Threat Intelligence
CrowdSec includes these detection collections:
- `crowdsecurity/traefik` - Traefik-specific detections
- `crowdsecurity/http-cve` - Known HTTP CVE exploits
- `crowdsecurity/whitelist-good-actors` - Whitelist for known good actors (search engines, etc.)
Enabled scenarios:
- HTTP probing and path traversal detection
- Bad user agent detection
- Sensitive file access attempts
- HTTP crawling detection
- SSH brute force (if exposed)
## Troubleshooting
**Bouncer not connecting to agent:**
```bash
kubectl logs -n crowdsec deploy/traefik-crowdsec-bouncer
kubectl exec -n crowdsec deploy/crowdsec -- cscli bouncers list
```
**Check if middleware is applied:**
```bash
kubectl get middleware -n crowdsec
kubectl describe ingressroute -n <app-namespace> <route-name>
```
**View CrowdSec logs:**
```bash
kubectl logs -n crowdsec deploy/crowdsec
```

View File

@@ -0,0 +1,43 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: crowdsec-config
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
data:
acquis.yaml: |
filenames:
- /var/log/containers/traefik-*_traefik_*.log
force_inotify: true
poll_without_inotify: true
labels:
type: containerd
program: traefik
profiles.yaml: |
name: default_ip_remediation
debug: false
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 4h
on_success: break
---
name: default_range_remediation
debug: false
filters:
- Alert.Remediation == true && Alert.GetScope() == "Range"
decisions:
- type: ban
duration: 4h
scope: Range
on_success: break
postoverflows.yaml: |
# Post-overflow configuration for crowdsec
name: "rdns"
debug: false
filter: "evt.Enriched.IsoCode != ''"
# Add reverse DNS enrichment

View File

@@ -0,0 +1,134 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: crowdsec
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
template:
metadata:
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
serviceAccountName: crowdsec
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: traefik
topologyKey: kubernetes.io/hostname
securityContext:
runAsUser: 0
runAsNonRoot: false
fsGroup: 0
seccompProfile:
type: RuntimeDefault
containers:
- name: crowdsec
image: crowdsecurity/crowdsec:v1.7.8
env:
- name: COLLECTIONS
value: "crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/whitelist-good-actors crowdsecurity/iptables crowdsecurity/linux"
- name: PARSERS
value: "crowdsecurity/traefik-logs crowdsecurity/http-logs crowdsecurity/nginx-logs"
- name: SCENARIOS
value: "crowdsecurity/http-crawl-non_statics crowdsecurity/http-probing crowdsecurity/http-sensitive-files crowdsecurity/http-bad-user-agent crowdsecurity/http-path-traversal-probing crowdsecurity/ssh-bf crowdsecurity/ssh-slow-bf"
- name: POSTOVERFLOWS
value: "crowdsecurity/rdns crowdsecurity/cdn-whitelist"
- name: GID
value: "1000"
- name: LEVEL_TRACE
value: "false"
- name: LEVEL_DEBUG
value: "false"
- name: LEVEL_INFO
value: "true"
- name: AGENT_USERNAME
value: "kubernetes-cluster"
- name: AGENT_PASSWORD
valueFrom:
secretKeyRef:
name: crowdsec-agent-secret
key: password
- name: BOUNCER_KEY_traefik
valueFrom:
secretKeyRef:
name: crowdsec-secrets
key: bouncerApiKey
optional: true
ports:
- name: lapi
containerPort: 8080
protocol: TCP
- name: prometheus
containerPort: 6060
protocol: TCP
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: false
volumeMounts:
- name: crowdsec-config
mountPath: /etc/crowdsec/acquis.yaml
subPath: acquis.yaml
readOnly: true
- name: crowdsec-config
mountPath: /etc/crowdsec/profiles.yaml
subPath: profiles.yaml
readOnly: true
- name: crowdsec-data
mountPath: /var/lib/crowdsec/data
- name: crowdsec-config-dir
mountPath: /etc/crowdsec/config
- name: varlog
mountPath: /var/log
readOnly: true
volumes:
- name: crowdsec-config
configMap:
name: crowdsec-config
- name: crowdsec-data
persistentVolumeClaim:
claimName: crowdsec-data
- name: crowdsec-config-dir
emptyDir: {}
- name: varlog
hostPath:
path: /var/log

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
name: crowdsec-lapi
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
type: ClusterIP
selector:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
ports:
- name: lapi
port: 8080
targetPort: 8080
protocol: TCP
- name: prometheus
port: 6060
targetPort: 6060
protocol: TCP

View File

@@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: "{{ .namespace }}"
labels:
- includeSelectors: true
pairs:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
resources:
- namespace.yaml
- serviceaccount.yaml
- configmap.yaml
- pvc.yaml
- crowdsec-deployment.yaml
- crowdsec-service.yaml
- middleware.yaml

View File

@@ -0,0 +1,26 @@
version: v1.7.8
requires:
- name: longhorn
- name: traefik
defaultConfig:
namespace: crowdsec
rateLimitAverage: "100"
rateLimitBurst: "100"
defaultSecrets:
- key: agentPassword
- key: bouncerApiKey
deploy:
createSecrets:
- name: crowdsec-agent-secret
entries:
password: agentPassword
- name: crowdsec-bouncer-secret
entries:
api-key: bouncerApiKey
- name: crowdsec-bouncer-secret
namespace: traefik
entries:
api-key: bouncerApiKey
waitForRollout:
name: crowdsec
timeout: "120s"

View File

@@ -0,0 +1,89 @@
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: crowdsec-bouncer
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
plugin:
bouncer:
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec-lapi.crowdsec.svc.cluster.local:8080
crowdsecLapiKeyFile: /etc/traefik/crowdsec/api-key
crowdsecMode: stream
updateIntervalSeconds: 15
defaultDecisionSeconds: 60
crowdsecAppsecEnabled: false
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
rateLimit:
average: {{ .rateLimitAverage }}
burst: {{ .rateLimitBurst }}
period: 1m
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security-headers
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
headers:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: true
sslRedirect: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
addVaryHeader: true
accessControlAllowMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
accessControlAllowOriginList:
- "*"
accessControlMaxAge: 100
customRequestHeaders:
X-Forwarded-Proto: https
customResponseHeaders:
Server: ""
X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security-chain
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
spec:
chain:
middlewares:
- name: security-headers
namespace: crowdsec
- name: rate-limit
namespace: crowdsec
- name: crowdsec-bouncer
namespace: crowdsec

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
name: "{{ .namespace }}"
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud
pod-security.kubernetes.io/enforce: privileged

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: crowdsec-data
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 512Mi

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: crowdsec
namespace: crowdsec
labels:
app: crowdsec
managedBy: kustomize
partOf: wild-cloud