Skip to content

Commit 1933837

Browse files
committed
improve ingress nginx
1 parent d0b4835 commit 1933837

File tree

1 file changed

+68
-203
lines changed

1 file changed

+68
-203
lines changed

crowdsec-docs/docs/appsec/quickstart/nginx-ingress.mdx

Lines changed: 68 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -11,107 +11,91 @@ import UnderlineTooltip from '@site/src/components/underline-tooltip';
1111

1212
## Objectives
1313

14-
This quickstart shows how to deploy the CrowdSec AppSec component with the official Helm chart and protect workloads exposed through the Kubernetes [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/). At the end you will have:
14+
This quickstart shows how to deploy the CrowdSec AppSec component with the
15+
official Helm chart and protect workloads exposed through the Kubernetes [NGINX
16+
Ingress Controller](https://kubernetes.github.io/ingress-nginx/). At the end you
17+
will have:
1518

1619
- CrowdSec running in-cluster with the AppSec API listening on `7422`
1720
- The ingress controller using the CrowdSec Lua plugin to forward requests for inspection
1821
- Basic virtual patching rules blocking common web exploits
1922

20-
## Prerequisites
21-
22-
Before you begin, make sure you have:
23-
24-
- A working Kubernetes cluster (v1.25+ recommended) with `kubectl` access
25-
- [Helm 3](https://helm.sh/docs/intro/install/) installed locally
26-
- The [`ingress-nginx` Helm repository](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx) available, or an existing controller that can be upgraded
27-
- Cluster-admin permissions to create namespaces, Deployments, Secrets and ConfigMaps
28-
- Internet access from the cluster nodes so the CrowdSec pod can download Hub content
29-
30-
:::warning Lua-enabled controller required
31-
CrowdSec’s NGINX Ingress remediation relies on the Lua plugin interface. Use the `crowdsecurity/controller` image shipped by CrowdSec (included in the values below). The vanilla upstream controller dropped Lua support in v1.12.
23+
## Pre-requisites
24+
25+
1. If you're new to the [AppSec Component](/appsec/intro.md#introduction) or
26+
**W**eb **A**pplication **F**irewalls, start with the
27+
[Introduction](/appsec/intro.md#introduction) for a better understanding.
28+
29+
2. It's assumed that you have already installed **CrowdSec [Security
30+
Engine](intro.mdx)**: for installation, refer to the [QuickStart
31+
guide](/u/getting_started/installation/kubernetes). The AppSec Component, which
32+
analyzes HTTP requests, is included within the security engine as a
33+
<UnderlineTooltip tooltip="Acquisition files tell CrowdSec where to find logs
34+
and which application they belong to.">Acquisition</UnderlineTooltip>.
35+
36+
:::warning
37+
A Lua-enabled controller is essential for CrowdSec's NGINX Ingress
38+
remediation, as it relies on the Lua plugin interface. Please use the
39+
`crowdsecurity/controller` image provided by CrowdSec (as specified in the
40+
values below). Note that the standard upstream controller removed Lua support in
41+
version 1.12.
3242
:::
3343

3444
## Step 1 – Deploy CrowdSec with AppSec enabled
3545

3646
1. Add or update the CrowdSec Helm repository:
3747

38-
```bash
39-
helm repo add crowdsec https://crowdsecurity.github.io/helm-charts
40-
helm repo update
48+
```bash
49+
helm repo add crowdsec https://crowdsecurity.github.io/helm-charts
50+
helm repo update
4151
```
4252

43-
:::note
44-
If CrowdSec is already deployed with Helm in this cluster, the repository entry is already present—you only need `helm repo update`.
45-
:::
46-
47-
2. Create `crowdsec-appsec-values.yaml` with the AppSec configuration:
48-
49-
```yaml title="crowdsec-appsec-values.yaml"
50-
appsec:
51-
enabled: true
52-
service:
53-
type: ClusterIP
54-
port: 7422
55-
acquisitions:
56-
- listen_addr: 0.0.0.0:7422
57-
source: appsec
58-
labels:
59-
type: appsec
60-
appsec_configs:
61-
- crowdsecurity/appsec-default
62-
config:
63-
cscli:
64-
setup:
65-
collections:
66-
- crowdsecurity/appsec-virtual-patching
67-
- crowdsecurity/appsec-generic-rules
68-
bouncers:
69-
- name: nginx_ingress_waf
70-
key: ${NGINX_INGRESS_BOUNCER_KEY}
71-
```
53+
:::note
54+
If CrowdSec is already deployed with Helm in this cluster, the repository entry is already present—you only need `helm repo update`.
55+
:::
7256

73-
- `listen_addr: 0.0.0.0:7422` exposes the AppSec API inside the cluster.
74-
- The two collections provide virtual patching and generic rule coverage.
75-
- The chart bootstraps a bouncer named `nginx_ingress_waf` using the key you export locally.
57+
2. Add this to the CrowdSec `values.yaml` with the AppSec configuration:
58+
59+
```yaml title="values.yaml"
60+
appsec
61+
acquisitions:
62+
- appsec_config: crowdsecurity/appsec-default
63+
labels:
64+
type: appsec
65+
listen_addr: 0.0.0.0:7422
66+
path: /
67+
source: appsec
68+
enabled: true
69+
env:
70+
- name: COLLECTIONS
71+
value: crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules
72+
```
7673
77-
3. Install (or upgrade) the CrowdSec release:
74+
This yaml configuration snippet exposes those important configuration items:
75+
* `listen_addr: 0.0.0.0:7422` exposes the AppSec API inside the cluster.
76+
* The two collections provide virtual patching and generic rule coverage.
77+
* The chart bootstraps a bouncer named `nginx_ingress_waf` using the key you export locally.
7878

79-
```bash
80-
helm upgrade --install crowdsec crowdsec/crowdsec \
81-
--namespace crowdsec \
82-
--create-namespace \
83-
-f crowdsec-appsec-values.yaml
84-
```
8579

86-
4. Confirm the pods are healthy:
80+
3. Upgrade the CrowdSec release:
8781

88-
```bash
89-
kubectl -n crowdsec get pods
82+
```bash
83+
helm upgrade --install crowdsec crowdsec/crowdsec --namespace crowdsec --create-namespace -f crowdsec-appsec-values.yaml
9084
```
9185

92-
You should see both the `crowdsec` pod and the `crowdsec-appsec` pod in `Running` state.
93-
94-
## Step 2 – Provide the bouncer key via environment variables
95-
96-
The ingress controller authenticates against CrowdSec with a bouncer API key. Instead of invoking `cscli` manually, let the Helm chart create the bouncer by providing the key through an environment variable.
97-
98-
1. Generate (or reuse) a strong key and export it in your shell:
99-
100-
```bash
101-
export NGINX_INGRESS_BOUNCER_KEY=$(openssl rand -hex 32)
102-
```
86+
4. Confirm the pods are healthy:
10387

104-
:::tip
105-
Keep working in the same terminal so the variable remains available while you write both values files. If you already have a key, export it instead of generating a new one.
106-
:::
88+
```bash
89+
kubectl -n crowdsec get pods
90+
```
10791

108-
2. When you create `crowdsec-appsec-values.yaml`, ensure the `${NGINX_INGRESS_BOUNCER_KEY}` placeholder is expanded by your shell (for example with `cat <<EOF` or `envsubst`). During installation the chart registers the `nginx_ingress_waf` bouncer automatically, so no additional Kubernetes Secret is required. Repeat the same approach for `crowdsec-ingress-values.yaml` in the next step.
92+
You should see both the `crowdsec` pod and the `crowdsec-appsec` pod in `Running` state.
10993

110-
## Step 3 – Enable the CrowdSec Lua plugin on NGINX Ingress
94+
## Step 2 – Enable the CrowdSec Lua plugin on NGINX Ingress
11195

112-
Create `crowdsec-ingress-values.yaml` (from the same shell session so `${NGINX_INGRESS_BOUNCER_KEY}` is still defined) to extend the ingress controller with the CrowdSec plugin and point it to the AppSec API:
96+
Create `ingress-values.yaml` is still defined) to extend the ingress controller with the CrowdSec plugin and point it to the AppSec API:
11397

114-
```yaml title="crowdsec-ingress-values.yaml"
98+
```yaml title="ingress-values.yaml"
11599
controller:
116100
image:
117101
registry: docker.io
@@ -129,7 +113,7 @@ controller:
129113
- name: API_URL
130114
value: "http://crowdsec-service.crowdsec.svc.cluster.local:8080"
131115
- name: API_KEY
132-
value: "${NGINX_INGRESS_BOUNCER_KEY}"
116+
value: privateKey-foo
133117
- name: BOUNCER_CONFIG
134118
value: "/crowdsec/crowdsec-bouncer.conf"
135119
- name: APPSEC_URL
@@ -167,147 +151,28 @@ controller:
167151
```
168152

169153
- `API_URL` targets the Local API service exposed by the Helm chart.
170-
- `API_KEY` reuses the `${NGINX_INGRESS_BOUNCER_KEY}` variable exported earlier so the ingress controller shares the same credential.
154+
- `API_KEY` defines the key for the bouncer to be able to connect to CrowdSec LAPI
171155
- `APPSEC_URL` points to the AppSec service; keep the namespace in sync with your CrowdSec release.
172156
- The plugin copies the Lua files from the init container into an `emptyDir` that is mounted at runtime.
173157

174158
Deploy or upgrade the ingress controller with the new values:
175159

176-
<Tabs
177-
groupId="nginx-ingress-deploy"
178-
defaultValue="upgrade"
179-
values={[
180-
{ label: 'Upgrade existing release', value: 'upgrade' },
181-
{ label: 'Fresh install', value: 'install' },
182-
]}
183-
>
184-
<TabItem value="upgrade">
185-
186160
```bash
187-
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
161+
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
188162
--namespace ingress-nginx \
189163
-f crowdsec-ingress-values.yaml
190164
```
191165

192-
</TabItem>
193-
<TabItem value="install">
166+
::: note
167+
After the rollout, you can optionally check that the right container is deployed
194168

195-
```bash
196-
helm install ingress-nginx ingress-nginx/ingress-nginx \
197-
--namespace ingress-nginx \
198-
--create-namespace \
199-
-f crowdsec-ingress-values.yaml
200-
```
201-
202-
</TabItem>
203-
</Tabs>
204-
205-
After the rollout, verify that the controller pod lists the `crowdsec` plugin during startup:
206169

207170
```bash
208-
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller | grep crowdsec
171+
kubectl -n ingress-nginx exec -ti <ingress-pod-name> -- find /etc/nginx/lua/plugins/crowdsec
209172
```
173+
This should give you a bunch of crowdsec lua files.
210174

211-
You should see log lines confirming the plugin was loaded and the remote AppSec endpoint was reached.
212-
213-
## Step 4 – Validate the end-to-end flow
214-
215-
1. Confirm the AppSec service is reachable from inside the cluster:
216-
217-
```bash
218-
kubectl -n ingress-nginx exec deploy/ingress-nginx-controller -- \
219-
curl -s -o /dev/null -w '%{http_code}\n' \
220-
http://crowdsec-appsec-service.crowdsec.svc.cluster.local:7422/
221-
```
222-
223-
The command should return `400` or `404`, indicating the service responded.
224-
225-
2. Deploy a sample application and ingress (replace hostnames as needed):
226-
227-
```yaml title="demo.yaml"
228-
apiVersion: v1
229-
kind: Namespace
230-
metadata:
231-
name: demo
232-
---
233-
apiVersion: apps/v1
234-
kind: Deployment
235-
metadata:
236-
name: whoami
237-
namespace: demo
238-
spec:
239-
replicas: 1
240-
selector:
241-
matchLabels:
242-
app: whoami
243-
template:
244-
metadata:
245-
labels:
246-
app: whoami
247-
spec:
248-
containers:
249-
- name: whoami
250-
image: containous/whoami:v1.5.0
251-
ports:
252-
- containerPort: 80
253-
---
254-
apiVersion: v1
255-
kind: Service
256-
metadata:
257-
name: whoami
258-
namespace: demo
259-
spec:
260-
selector:
261-
app: whoami
262-
ports:
263-
- port: 80
264-
targetPort: 80
265-
---
266-
apiVersion: networking.k8s.io/v1
267-
kind: Ingress
268-
metadata:
269-
name: whoami
270-
namespace: demo
271-
annotations:
272-
kubernetes.io/ingress.class: nginx
273-
spec:
274-
rules:
275-
- host: whoami.example.test
276-
http:
277-
paths:
278-
- path: /
279-
pathType: Prefix
280-
backend:
281-
service:
282-
name: whoami
283-
port:
284-
number: 80
285-
```
286-
287-
```bash
288-
kubectl apply -f demo.yaml
289-
```
290-
291-
3. Trigger a benign request and a malicious probe:
292-
293-
```bash
294-
# Replace with the address that resolves to your ingress controller
295-
INGRESS_HOST=whoami.example.test
296-
curl -H "Host: $INGRESS_HOST" http://<load-balancer-ip>/
297-
curl -H "Host: $INGRESS_HOST" http://<load-balancer-ip>/.env -i
298-
```
299-
300-
The `.env` request should return `403 Forbidden` and a CrowdSec block page while the regular request succeeds.
301-
302-
4. Inspect CrowdSec metrics and alerts:
303-
304-
```bash
305-
kubectl -n crowdsec exec "$CROWdSEC_POD" -c crowdsec -- cscli alerts list
306-
kubectl -n crowdsec exec "$CROWdSEC_POD" -c crowdsec -- cscli metrics show appsec
307-
```
308-
309-
You should see the AppSec component processing traffic and banning the offending source.
310-
175+
:::
311176
## Next steps
312177

313178
- Add the [OWASP CRS](/appsec/advanced_deployments.mdx) to extend detection coverage.

0 commit comments

Comments
 (0)