Reorganized for new stable/waypoint versioning design.
This commit is contained in:
118
crowdsec/versions/v1/README.md
Normal file
118
crowdsec/versions/v1/README.md
Normal 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
|
||||
```
|
||||
43
crowdsec/versions/v1/configmap.yaml
Normal file
43
crowdsec/versions/v1/configmap.yaml
Normal 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
|
||||
134
crowdsec/versions/v1/crowdsec-deployment.yaml
Normal file
134
crowdsec/versions/v1/crowdsec-deployment.yaml
Normal 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
|
||||
24
crowdsec/versions/v1/crowdsec-service.yaml
Normal file
24
crowdsec/versions/v1/crowdsec-service.yaml
Normal 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
|
||||
17
crowdsec/versions/v1/kustomization.yaml
Normal file
17
crowdsec/versions/v1/kustomization.yaml
Normal 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
|
||||
26
crowdsec/versions/v1/manifest.yaml
Normal file
26
crowdsec/versions/v1/manifest.yaml
Normal 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"
|
||||
89
crowdsec/versions/v1/middleware.yaml
Normal file
89
crowdsec/versions/v1/middleware.yaml
Normal 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
|
||||
9
crowdsec/versions/v1/namespace.yaml
Normal file
9
crowdsec/versions/v1/namespace.yaml
Normal 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
|
||||
12
crowdsec/versions/v1/pvc.yaml
Normal file
12
crowdsec/versions/v1/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: crowdsec-data
|
||||
spec:
|
||||
storageClassName: longhorn
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
volumeMode: Filesystem
|
||||
resources:
|
||||
requests:
|
||||
storage: 512Mi
|
||||
9
crowdsec/versions/v1/serviceaccount.yaml
Normal file
9
crowdsec/versions/v1/serviceaccount.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: crowdsec
|
||||
namespace: crowdsec
|
||||
labels:
|
||||
app: crowdsec
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
Reference in New Issue
Block a user