Example Output
-```bash title="sudo cscli metrics show appsec"
+```bash title="Bare-metal output (listen_addr: 127.0.0.1:7422)"
Appsec Metrics:
╭─────────────────┬───────────┬─────────╮
│ Appsec Engine │ Processed │ Blocked │
@@ -440,6 +636,22 @@ Appsec '127.0.0.1:7422/' Rules Metrics:
╰─────────────────────────────────┴───────────╯
```
+```bash title="Kubernetes output (listen_addr: 0.0.0.0:7422)"
+Appsec Metrics:
+╭─────────────────┬───────────┬─────────╮
+│ Appsec Engine │ Processed │ Blocked │
+├─────────────────┼───────────┼─────────┤
+│ 0.0.0.0:7422/ │ 2 │ 1 │
+╰─────────────────┴───────────┴─────────╯
+
+Appsec '0.0.0.0:7422/' Rules Metrics:
+╭─────────────────────────────────┬───────────╮
+│ Rule ID │ Triggered │
+├─────────────────────────────────┼───────────┤
+│ crowdsecurity/vpatch-env-access │ 1 │
+╰─────────────────────────────────┴───────────╯
+```
+
You can test and investigate further with [Stack
Health-Check](/u/getting_started/health_check) and [Appsec Troubleshooting
guide](/appsec/troubleshooting.md)
diff --git a/crowdsec-docs/unversioned/bouncers/traefik.mdx b/crowdsec-docs/unversioned/bouncers/traefik.mdx
index 60d44bd87..a1863396a 100644
--- a/crowdsec-docs/unversioned/bouncers/traefik.mdx
+++ b/crowdsec-docs/unversioned/bouncers/traefik.mdx
@@ -4,71 +4,96 @@ title: Traefik (Kubernetes)
sidebar_position: 5
---
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-import useBaseUrl from '@docusaurus/useBaseUrl';
-import RemediationSupportBadges from '@site/src/components/remediation-support-badge';
-
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import RemediationSupportBadges from "@site/src/components/remediation-support-badge";
-
+
-
-
+
+
-📚 Documentation
-💠 Hub
-💬 Discourse
+ 📚 Documentation
+ 💠{" "}
+
+ Source
+
+ 💬 Discourse
-
+
:::tip AppSec Support
-This bouncer supports the [AppSec Component](/docs/next/appsec/intro) for real-time WAF protection. Enable `crowdsecAppsecEnabled: true` in your middleware configuration to get virtual patching and defense against known CVEs, SQL injection, XSS, and other application-layer attacks.
+This bouncer supports the [AppSec Component](/docs/next/appsec/intro) for
+real-time WAF protection. Enable `crowdsecAppsecEnabled: true` in your
+middleware configuration to get virtual patching and defense against known
+CVEs, SQL injection, XSS, and other application-layer attacks.
-For a full walkthrough, see the [AppSec Quickstart for Traefik](/docs/next/appsec/quickstart/traefik).
+For a full walkthrough, see the
+[AppSec Quickstart for Traefik](/docs/next/appsec/quickstart/traefik).
:::
-## Traefik on kubernetes
+# Traefik on kubernetes
-:::important
-This remediation component is community developed and maintained. You can see all
-the configuration options in the [bouncer
-documentation](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin).
-You can also refer to a [full traefik and CrowdSec stack on
-kubernetes](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/tree/main/examples/kubernetes)
-or our [Appsec Traefik Quickstart](/docs/next/appsec/quickstart/traefik).
-
-This piece of documentation is rather an howto than a full fledge documentation.
-:::
+## Objectives
+
+This quickstart shows how to deploy the CrowdSec Traefik bouncer in Kubernetes
+and protect workloads exposed through
+[Traefik](https://doc.traefik.io/traefik/) using a middleware plugin.
+
+At the end, you will have:
+
+- CrowdSec LAPI running in-cluster and reachable from Traefik
+- A Traefik middleware enforcing CrowdSec remediation decisions
+- A Kubernetes secret storing the shared bouncer key
+- The bouncer key mounted into the Traefik pod as a file
+- An operational pattern that avoids committing the LAPI key in plaintext
+
+## Prerequisites
+
+It is assumed that you already have:
-### Prerequesites
+- A working CrowdSec [Security Engine](/intro.mdx) installation. For a
+ Kubernetes install quickstart, refer to
+ [/u/getting_started/installation/kubernetes](/u/getting_started/installation/kubernetes).
+- A working Traefik installation in Kubernetes.
+- Existing `IngressRoute`, `Ingress`, or other Traefik-managed routes
+ exposing your applications.
-#### Source IPs
+:::warning
+This integration currently relies on a community Traefik plugin, not on a
+first-party CrowdSec remediation component.
-To ensure remediation works correctly, Traefik must receive the actual client IP
-for every request. When Traefik is deployed behind an upstream proxy or load
-balancer, the source IP may otherwise be replaced with the proxy’s address.
-Traefik Behind an Upstream Proxy or Load Balancer
+The upstream project used in this guide is:
-When Traefik operates behind a load balancer, CDN, or any intermediate proxy,
-proper forwarding and trust of client IP information is required for CrowdSec to
-apply decisions accurately.
+- `maxlerebourg/crowdsec-bouncer-traefik-plugin`
+ :::
-Traefik must first be configured to trust the upstream IP ranges. This is done
-using the
-[forwardedHeaders.trustedIPs](https://doc.traefik.io/traefik/v3.2/routing/entrypoints/#forwarded-headers)
-and
-[proxyProtocol.trustedIPs](https://doc.traefik.io/traefik/v3.2/routing/entrypoints/#proxyprotocol)
-entrypoint settings, depending on whether the environment relies on forwarded
-headers or the PROXY protocol.
+## Required traefik configuration items
-The CrowdSec bouncer middleware then also needs to trust these same ranges:
+### Traefik configuration's on source IPs
+
+To ensure remediation works correctly, Traefik must receive the real client IP
+for each request. When Traefik is deployed behind a load balancer, CDN, or
+another reverse proxy, the source IP may otherwise be replaced with the
+upstream address.
+
+Traefik must first trust the upstream IP ranges. This is done with:
+
+- [forwardedHeaders.trustedIPs](https://doc.traefik.io/traefik/v3.2/routing/entrypoints/#forwarded-headers)
+- [proxyProtocol.trustedIPs](https://doc.traefik.io/traefik/v3.2/routing/entrypoints/#proxyprotocol)
+
+The CrowdSec middleware must then trust the same ranges:
```yaml
spec:
@@ -77,8 +102,8 @@ spec:
forwardedHeadersTrustedIps:
```
-In case the header in which the ip is set is not `X-Forwarded-For`, it can be
-set with:
+If the client IP is forwarded through a header other than `X-Forwarded-For`,
+set it explicitly:
```yaml
spec:
@@ -88,82 +113,209 @@ spec:
```
Correctly forwarding and trusting these headers ensures that both Traefik and
-CrowdSec operate on the real client IP, which is required for IP-based
+CrowdSec operate on the same client IP, which is required for IP-based
remediation.
-
-Side note about source ip with CrowdSec and Kubernetes
+
+Side note about source IP with CrowdSec and Kubernetes
Source IP addresses are essential in a CrowdSec deployment for two reasons.
First, the log processor must know which IPs are responsible for triggering
scenarios. Second, the remediation component needs to identify the originating
IP of incoming requests in order to apply the appropriate action.
-In a Kubernetes environment, this requires disabling source NAT on nodes so that
-the CrowdSec-monitored service pods receive the real client IP. As a
-consequence, the Service’s externalTrafficPolicy must be set to Local, and the
-workload (Traefik or any ingress/controller) must run either as a DaemonSet or
-as a Deployment ensuring one pod per node. This guarantees that no traffic — and
-therefore no security events — is missed.
-
+In a Kubernetes environment, this requires disabling source NAT on nodes so
+that the CrowdSec-monitored service pods receive the real client IP. As a
+consequence, the Service's `externalTrafficPolicy` must be set to `Local`, and
+the workload must run either as a `DaemonSet` or as a `Deployment` ensuring one
+pod per node. This guarantees that no traffic, and therefore no security
+events, is missed.
-#### Traefik Custom Resources Definition
+
-Traefik’s CRDs provide the custom resource types (such as Middleware) required
-for configuring Traefik through the Kubernetes CRD provider. CrowdSec
-remediation relies on one of these resources to declare the CrowdSec bouncer
-middleware. Without the CRDs, this middleware cannot be created or used, and
-Traefik is unable to apply CrowdSec decisions.
+### Traefik Custom Resource Definitions
+
+Traefik's CRDs provide the custom resource types, such as `Middleware`, that
+are required to configure Traefik through the Kubernetes CRD provider. CrowdSec
+remediation relies on one of these resources to declare the middleware. Without
+the CRDs, this middleware cannot be created or used.
-Here is the command sequence to install the Traefik CRDs via the Helm chart:
+Install the Traefik CRDs via Helm:
```bash
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm upgrade --install traefik-crds traefik/traefik-crds -n traefik --create-namespace
```
+
-You can deploy Traefik CRDs without helm as well following [https://doc.traefik.io/traefik/reference/install-configuration/providers/kubernetes/kubernetes-crd/](Traefik documentation)
+
+You can also deploy the Traefik CRDs without Helm:
+
```bash
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.6/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
```
-
-#### Experimental plugin loading ability
+### Enable experimental plugin loading
-CrowdSec Bouncer Traefik Plugin can't be enabled via CLI flags alone, one has to
-enable the experimental plugin load. This can be done by adding this snippet to
-Traefik helm's chart values:
+The CrowdSec Traefik plugin cannot be enabled only through CLI flags. You must
+also enable experimental plugin loading in the Traefik chart values:
-```yaml values.yaml
+```yaml title="traefik-values.yaml"
experimental:
plugins:
- crowdsec-bouncer-traefik-plugin:
- moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- version: "v1.4.5"
+ bouncer:
+ moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
+ version: v1.4.5
+volumes:
+ - name: crowdsec-bouncer-key
+ mountPath: /etc/traefik/crowdsec
+ type: secret
+ secretName: crowdsec-bouncer-key
```
-### Middleware
+Apply or upgrade your Traefik release:
-To achieve remediation in a Traefik environment, one has to use a "Middleware" resource.
+```bash
+helm upgrade --install traefik traefik/traefik -n traefik --create-namespace -f traefik-values.yaml
+```
-Here is bouncer-middleware.yaml:
+## Store the Traefik bouncer key in a Kubernetes secret
-```yaml
+The practical approach is to choose a fixed shared key and store it in
+Kubernetes secrets instead of hardcoding it in Helm values.
+
+Two secrets are needed because CrowdSec and Traefik run in different
+namespaces:
+
+- In the `crowdsec` namespace, CrowdSec LAPI reads `BOUNCER_KEY_traefik` from
+ the `crowdsec-keys` secret.
+- In the `traefik` namespace, Traefik mounts the same key from the
+ `crowdsec-bouncer-key` secret as a file.
+
+Both secrets must contain the same `BOUNCER_KEY_traefik` value.
+
+Create or update the secrets used by CrowdSec LAPI and Traefik:
+
+```yaml title="crowdsec-keys.yaml"
+apiVersion: v1
+kind: Secret
+metadata:
+ name: crowdsec-keys
+ namespace: crowdsec
+type: Opaque
+stringData:
+ ENROLL_KEY: ""
+ BOUNCER_KEY_traefik: ""
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: crowdsec-bouncer-key
+ namespace: traefik
+type: Opaque
+stringData:
+ BOUNCER_KEY_traefik: ""
+```
+
+Apply it:
+
+```bash
+kubectl apply -f crowdsec-keys.yaml
+```
+
+Then reference `BOUNCER_KEY_traefik` from the CrowdSec Helm values:
+
+```yaml title="crowdsec-values.yaml"
+lapi:
+ env:
+ - name: BOUNCER_KEY_traefik
+ valueFrom:
+ secretKeyRef:
+ name: crowdsec-keys
+ key: BOUNCER_KEY_traefik
+```
+
+Apply the CrowdSec release again:
+
+```bash
+helm upgrade --install crowdsec crowdsec/crowdsec --namespace crowdsec --create-namespace -f crowdsec-values.yaml
+```
+
+The `crowdsec-bouncer-key` secret in the `traefik` namespace is used later when
+mounting the key into the Traefik pod.
+
+## Verify CrowdSec LAPI access
+
+The Traefik middleware only needs access to CrowdSec LAPI. Make sure the
+CrowdSec release exposes the LAPI service, that the bouncer key is available
+through `lapi.env`, and that Traefik has the same key mounted from the
+`crowdsec-bouncer-key` secret.
+
+Verify the CrowdSec pods and services:
+
+```bash
+kubectl -n crowdsec get pods
+kubectl -n crowdsec get svc crowdsec-service
+```
+
+You should see:
+
+- `crowdsec-lapi` in `Running`
+- `crowdsec-service` exposing port `8080`
+
+## Deploy the Traefik middleware
+
+To achieve remediation in a Traefik environment, create a `Middleware`
+resource.
+
+:::important
+The Traefik `Middleware` CRD does not have a native `secretKeyRef` field for the
+plugin configuration. In Kubernetes, the key can be mounted from a `Secret` into
+the Traefik pod and reference it with `crowdsecLapiKeyFile`.
+:::
+
+Mount the Traefik-side secret into the pod and let the middleware read it from a
+file.
+
+Use a Traefik chart values file like this:
+
+```yaml title="traefik-values.yaml"
+experimental:
+ plugins:
+ bouncer:
+ moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
+ version: v1.4.5
+volumes:
+ - name: crowdsec-bouncer-key
+ mountPath: /etc/traefik/crowdsec
+ type: secret
+ secretName: crowdsec-bouncer-key
+```
+
+Apply or upgrade your Traefik release:
+
+```bash
+helm upgrade --install traefik traefik/traefik -n traefik --create-namespace -f traefik-values.yaml
+```
+
+Then create the middleware:
+
+```yaml title="bouncer-middleware.yaml"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
@@ -174,28 +326,70 @@ spec:
bouncer:
enabled: true
crowdsecMode: stream
- crowdsecLapiHost: crowdsec-service.default.svc.cluster.local:8080
- crowdsecLapiKey:
+ crowdsecLapiScheme: http
+ crowdsecLapiHost: crowdsec-service.crowdsec.svc.cluster.local:8080
+ crowdsecLapiPath: /
+ crowdsecLapiKeyFile: /etc/traefik/crowdsec/BOUNCER_KEY_traefik
```
-Now, you can install the remediation component:
+Apply it:
```bash
kubectl apply -f bouncer-middleware.yaml
```
-### Traefik with WAF(appsec) on kubernetes
+This keeps the source-of-truth key in Kubernetes secrets and avoids storing the
+literal key in the middleware manifest.
-We supposed you already have working crowdsec values configuration, basically here is the important configuration to put in crowdsec values :
+
+Show direct crowdsecLapiKey example
-```yaml
+You can apply a middleware manifest with an inline key as well:
+
+```yaml title="bouncer-middleware.yaml"
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+ name: bouncer
+ namespace: traefik
+spec:
+ plugin:
+ bouncer:
+ enabled: true
+ crowdsecMode: stream
+ crowdsecLapiScheme: http
+ crowdsecLapiHost: crowdsec-service.crowdsec.svc.cluster.local:8080
+ crowdsecLapiPath: /
+ crowdsecLapiKey:
+```
+
+Apply it:
+
+```bash
+kubectl apply -f bouncer-middleware.yaml
+```
+
+This is useful for quick validation, but `crowdsecLapiKeyFile` with a mounted
+Kubernetes secret seems to be a more secure approach.
+
+
+
+Once the middleware exists, attach it to your `IngressRoute` or other Traefik
+route resources.
+
+## Traefik with WAF (AppSec) on Kubernetes
+
+If you want remediation and WAF protection together, first enable AppSec in the
+CrowdSec chart while still sourcing the bouncer key from the Kubernetes secret:
+
+```yaml title="crowdsec-values.yaml"
config:
config.yaml.local: |
api:
server:
auto_registration:
enabled: true
- token: "${REGISTRATION_TOKEN}" # /!\ Do not modify this variable (auto-generated and handled by the chart)
+ token: "${REGISTRATION_TOKEN}"
allowed_ranges:
- "127.0.0.1/32"
- "192.168.0.0/16"
@@ -218,16 +412,49 @@ appsec:
lapi:
env:
- name: BOUNCER_KEY_traefik
- value:
+ valueFrom:
+ secretKeyRef:
+ name: crowdsec-keys
+ key: BOUNCER_KEY_traefik
```
-If you add this config to crowdsec values, don't forget to `helm upgrade`
+If you add this config to the CrowdSec values, don't forget to upgrade the
+release:
-Then the configuration for the middleware (bouncer-middleware.yaml) :
+```bash
+helm upgrade --install crowdsec crowdsec/crowdsec \
+ --namespace crowdsec \
+ --create-namespace \
+ -f crowdsec-values.yaml
+```
-```yaml
-kind: Middleware
+Traefik must also mount the `crowdsec-bouncer-key` secret so the middleware can
+read the bouncer key from a file:
+
+```yaml title="traefik-values.yaml"
+experimental:
+ plugins:
+ bouncer:
+ moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
+ version: v1.4.5
+volumes:
+ - name: crowdsec-bouncer-key
+ mountPath: /etc/traefik/crowdsec
+ type: secret
+ secretName: crowdsec-bouncer-key
+```
+
+If needed, upgrade the Traefik release as well:
+
+```bash
+helm upgrade --install traefik traefik/traefik -n traefik --create-namespace -f traefik-values.yaml
+```
+
+Then use an AppSec-enabled middleware:
+
+```yaml title="bouncer-middleware.yaml"
apiVersion: traefik.io/v1alpha1
+kind: Middleware
metadata:
name: bouncer
namespace: traefik
@@ -237,19 +464,18 @@ spec:
enabled: true
crowdsecMode: stream
crowdsecLapiScheme: http
- crowdsecLapiHost: crowdsec-service.default.svc.cluster.local:8080
+ crowdsecLapiHost: crowdsec-service.crowdsec.svc.cluster.local:8080
+ crowdsecLapiPath: /
+ crowdsecLapiKeyFile: /etc/traefik/crowdsec/BOUNCER_KEY_traefik
crowdsecAppsecEnabled: true
- crowdsecAppsecHost: crowdsec-appsec-service.default.svc.cluster.local:7422
- crowdsecAppsecPath: "/"
+ crowdsecAppsecHost: crowdsec-appsec-service.crowdsec.svc.cluster.local:7422
+ crowdsecAppsecPath: /
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
crowdsecAppsecBodyLimit: 10485760
- crowdsecLapiKey:
- crowdsecLapiPath: "/"
```
-
-Now, you can install or update the remediation component:
+Apply it:
```bash
kubectl apply -f bouncer-middleware.yaml
@@ -265,5 +491,7 @@ curl -I http:///.env
```
:::tip Monitoring AppSec
-Once AppSec is enabled, use `cscli metrics show appsec` to view processed vs. blocked requests and individual rule triggers. These metrics also appear in the [CrowdSec Console](https://app.crowdsec.net) after enrollment.
+Once AppSec is enabled, use `cscli metrics show appsec` to view processed vs.
+blocked requests and individual rule triggers. These metrics also appear in the
+[CrowdSec Console](https://app.crowdsec.net) after enrollment.
:::