Skip to content

Commit 892909b

Browse files
πŸ› fix start up config error for appsec and review doc for appsec tls (#300)
* πŸ› fix start up config error for appsec * :doc: add documentation on appsec variables and missing conf parameter * 🍱 fix lint * 🍱 fix lint * 🍱 fix lint * 🍱 fix after lot of tests * update exemple tls with new variables tested * fix exemple appsec with release and not localplugin --------- Co-authored-by: mhx <mathieu@hanotaux.fr>
1 parent c26923d commit 892909b

File tree

10 files changed

+180
-113
lines changed

10 files changed

+180
-113
lines changed

β€ŽMakefileβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ clean_all_docker:
9999
docker compose -f examples/redis-cache/docker-compose.yml down --remove-orphans
100100
docker compose -f examples/trusted-ips/docker-compose.yml down --remove-orphans
101101
docker compose -f examples/tls-auth/docker-compose.yml down --remove-orphans
102-
docker compose -f examples/appsec-enabled/docker-compose.appsec-enabled.yml down --remove-orphans
102+
docker compose -f examples/appsec-enabled/docker-compose.yml down --remove-orphans
103103
docker compose -f examples/captcha/docker-compose.yml down --remove-orphans
104104
docker compose -f examples/custom-captcha/docker-compose.yml down --remove-orphans
105105
docker compose -f examples/custom-ban-page/docker-compose.yml down --remove-orphans

β€ŽREADME.mdβ€Ž

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -310,17 +310,16 @@ make run
310310
### Note
311311

312312
> [!IMPORTANT]
313-
> Some of the behaviours and configuration parameters are shared globally across *all* crowdsec middlewares even if you declare different middlewares with different settings.
313+
> Some of the behaviours and configuration parameters are shared globally across _all_ crowdsec middlewares even if you declare different middlewares with different settings.
314314
>
315315
> **Cache is shared by all services**: This means if an IP is banned, all services which are protected by an instance of the plugin will deny requests from that IP
316316
>
317317
> If you define different caches for different middlewares, only the first one to be instantiated will be bound to the crowdsec stream.
318318
>
319-
> Overall, this middleware is designed in such a way that **only one instance of the plugin is *possible*.** You can have multiple crowdsec middlewares in the same cluster, the key parameters must be aligned (MetricsUpdateIntervalSeconds, CrowdsecMode, CrowdsecAppsecEnabled, etc.)
319+
> Overall, this middleware is designed in such a way that **only one instance of the plugin is _possible_.** You can have multiple crowdsec middlewares in the same cluster, the key parameters must be aligned (MetricsUpdateIntervalSeconds, CrowdsecMode, CrowdsecAppsecEnabled, etc.)
320320
321321
> [!WARNING]
322-
> **Appsec maximum body limit is defaulted to 10MB**
323-
> *Be careful when you upgrade to >1.4.x*
322+
> **Appsec maximum body limit is defaulted to 10MB** > _Be careful when you upgrade to >1.4.x_
324323
325324
### Variables
326325

@@ -351,7 +350,18 @@ make run
351350
- CrowdsecAppsecHost
352351
- string
353352
- default: "crowdsec:7422"
354-
- Crowdsec Appsec Server available on which host and port. The scheme will be handled by the CrowdsecLapiScheme var.
353+
- Crowdsec Appsec Server available on which host and port.
354+
- CrowdsecAppsecTlsInsecureVerify
355+
- bool
356+
- default: false
357+
- Disable verification of certificate presented by Appsec
358+
- CrowdsecAppsecTlsCertificateAuthority
359+
- string
360+
- default: ""
361+
- PEM-encoded Certificate Authority of Appsec
362+
- CrowdsecAppsecScheme
363+
- string
364+
- default: value of `CrowdsecLapiScheme`, expected values are: `http`, `https`
355365
- CrowdsecAppsecPath
356366
- string
357367
- default: "/"
@@ -368,6 +378,10 @@ make run
368378
- int64
369379
- default: 10485760 (= 10MB)
370380
- Transmit only the first number of bytes to Crowdsec Appsec Server.
381+
- CrowdsecAppsecKey
382+
- string
383+
- default: value of `CrowdsecLapiKey`
384+
- Crowdsec AppSec key for the bouncer.
371385
- CrowdsecLapiScheme
372386
- string
373387
- default: `http`, expected values are: `http`, `https`
@@ -614,7 +628,7 @@ http:
614628
615629
#### Fill variable with value of file
616630
617-
`CrowdsecLapiTlsCertificateBouncerKey`, `CrowdsecLapiTlsCertificateBouncer`, `CrowdsecLapiTlsCertificateAuthority`, `CrowdsecCapiMachineId`, `CrowdsecCapiPassword`, `CrowdsecLapiKey`, `CaptchaSiteKey`, `CaptchaSecretKey` and `RedisCachePassword` can be provided with the content as raw or through a file path that Traefik can read.
631+
`CrowdsecLapiTlsCertificateBouncerKey`, `CrowdsecLapiTlsCertificateBouncer`, `CrowdsecLapiTlsCertificateAuthority`, `CrowdsecAppsecTlsCertificateAuthority`, `CrowdsecCapiMachineId`, `CrowdsecCapiPassword`, `CrowdsecLapiKey`, `CrowdsecAppsecKey`, `CaptchaSiteKey`, `CaptchaSecretKey` and `RedisCachePassword` can be provided with the content as raw or through a file path that Traefik can read.
618632
The file variable will be used as preference if both content and file are provided for the same variable.
619633

620634
Format is:
@@ -677,6 +691,13 @@ Set the `crowdsecLapiScheme` to https.
677691
Crowdsec must be listening in HTTPS for this to work.
678692
Please see the [tls-auth example](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/tls-auth/README.md) or the official documentation: [docs.crowdsec.net/docs/local_api/tls_auth/](https://docs.crowdsec.net/docs/local_api/tls_auth/)
679693

694+
#### Use HTTPS to communicate with the Appsec
695+
696+
To communicate with the Appsec in HTTPS you need to either accept any certificates by setting the `crowdsecAppsecTLSInsecureVerify` to true or add the CA used by the server certificate of Crowdsec using `crowdsecAppsecTLSCertificateAuthority` or `crowdsecAppsecTLSCertificateAuthorityFile`.
697+
Set the `crowdsecAppsecScheme` to https.
698+
699+
Currently AppSec does not support mTLS authentication for the AppSec Component.
700+
680701
#### Manually add an IP to the blocklist (for testing purposes)
681702

682703
```bash

β€Žbouncer.goβ€Ž

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,23 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
134134

135135
serverChecker, _ := ip.NewChecker(log, config.ForwardedHeadersTrustedIPs)
136136
clientChecker, _ := ip.NewChecker(log, config.ClientTrustedIPs)
137-
tlsAppsecConfig, err := configuration.GetTLSConfigCrowdsec(config, log, true)
138-
if err != nil {
139-
log.Error("New:getTLSConfigCrowdsec fail to get tlsAppsecConfig " + err.Error())
140-
return nil, err
141-
}
142-
apiAppsecKey, errAppsecKey := configuration.GetVariable(config, "CrowdsecAppsecKey")
143-
if errAppsecKey != nil && len(tlsAppsecConfig.Certificates) == 0 {
144-
log.Error("New:crowdsecLapiKey fail to get CrowdsecAppsecKey and no client certificate setup " + errAppsecKey.Error())
145-
return nil, errAppsecKey
137+
138+
var tlsAppsecConfig *tls.Config
139+
if config.CrowdsecAppsecEnabled {
140+
tlsAppsecConfig, err = configuration.GetTLSConfigCrowdsec(config, log, true)
141+
if config.CrowdsecAppsecScheme == "" {
142+
config.CrowdsecAppsecScheme = config.CrowdsecLapiScheme
143+
}
144+
if err != nil {
145+
log.Error("New:getTLSConfigCrowdsec fail to get tlsAppsecConfig " + err.Error())
146+
return nil, err
147+
}
148+
apiAppsecKey, errAppsecKey := configuration.GetVariable(config, "CrowdsecAppsecKey")
149+
if errAppsecKey != nil && len(tlsAppsecConfig.Certificates) == 0 {
150+
log.Info("New:crowdsecLapiKey fail to get CrowdsecAppsecKey and no client certificate setup " + errAppsecKey.Error())
151+
}
152+
config.CrowdsecAppsecKey = apiAppsecKey
146153
}
147-
config.CrowdsecAppsecKey = apiAppsecKey
148154

149155
var tlsConfig *tls.Config
150156
crowdsecStreamRoute := ""
@@ -155,7 +161,6 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
155161
config.CrowdsecLapiScheme = configuration.HTTPS
156162
config.CrowdsecLapiHost = crowdsecCapiHost
157163
config.CrowdsecLapiPath = "/"
158-
config.CrowdsecAppsecEnabled = config.CrowdsecAppsecEnabled && config.CrowdsecAppsecScheme != ""
159164
config.UpdateIntervalSeconds = 7200 // 2 hours
160165
crowdsecStreamRoute = crowdsecCapiStreamRoute
161166
crowdsecHeader = crowdsecCapiHeader
@@ -173,6 +178,9 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
173178
return nil, errKey
174179
}
175180
config.CrowdsecLapiKey = apiKey
181+
if config.CrowdsecAppsecKey == "" {
182+
config.CrowdsecAppsecKey = apiKey
183+
}
176184
}
177185

178186
var banTemplate *htmltemplate.Template
@@ -374,6 +382,9 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
374382
}
375383
} else {
376384
value, err := handleNoStreamCache(bouncer, remoteIP)
385+
if err != nil {
386+
bouncer.log.Debug("handleNoStreamCache:crowdsecQuery " + err.Error())
387+
}
377388
if value == cache.NoBannedValue {
378389
bouncer.handleNextServeHTTP(rw, req, remoteIP)
379390
} else {

β€Ždocker-compose.local.ymlβ€Ž

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
traefik:
3-
image: "traefik:v3.0.0"
3+
image: "traefik:v3.5.0"
44
container_name: "traefik"
55
restart: unless-stopped
66
command:
@@ -16,8 +16,8 @@ services:
1616
volumes:
1717
- /var/run/docker.sock:/var/run/docker.sock:ro
1818
- logs-local:/var/log/traefik
19-
- './ban.html:/ban.html:ro'
20-
- './captcha.html:/captcha.html:ro'
19+
- "./ban.html:/ban.html:ro"
20+
- "./captcha.html:/captcha.html:ro"
2121
- ./:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
2222
ports:
2323
- 8000:80
@@ -52,6 +52,7 @@ services:
5252
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecappsecenabled=true"
5353
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=stream"
5454
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5="
55+
- "traefik.http.middlewares.crowdsec.plugin.bouncer.ForwardedHeadersTrustedIPs=172.21.0.1/8"
5556

5657
bar2:
5758
image: traefik/whoami

examples/appsec-enabled/docker-compose.appsec-enabled.yml renamed to examples/appsec-enabled/docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
traefik:
3-
image: "traefik:v3.0.0"
3+
image: "traefik:v3.5.0"
44
container_name: "traefik"
55
restart: unless-stopped
66
command:
@@ -13,7 +13,7 @@ services:
1313
- "--entrypoints.web.address=:80"
1414

1515
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
16-
- "--experimental.plugins.bouncer.version=v1.3.0"
16+
- "--experimental.plugins.bouncer.version=v1.5.0"
1717
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
1818
volumes:
1919
- /var/run/docker.sock:/var/run/docker.sock:ro

β€Žexamples/tls-auth/README.mdβ€Ž

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Example
2+
23
## Using https communication and tls authentication with Crowdsec
34

45
##### Summary
6+
57
This example demonstrates the use of https between the Traefik plugin and the Crowdsec LAPI.
68

79
It is possible to communicate with the LAPI in https and still authenticate with API key.
@@ -17,7 +19,9 @@ In that case the setting **crowdsecLapiTLSInsecureVerify** must be set to true.
1719
It is recommended to validate the certificate presented by Crowdsec LAPI using the Certificate Authority which created it.
1820

1921
You can provide the Certificate Authority using:
20-
* A file path readable by Traefik
22+
23+
- A file path readable by Traefik
24+
2125
```yaml
2226
http:
2327
middlewares:
@@ -26,25 +30,29 @@ http:
2630
bouncer:
2731
crowdsecLapiTlsCertificateAuthorityFile: /etc/traefik/certs/crowdsecCA.pem
2832
```
29-
* The PEM encoded certificate as a text variable
33+
34+
- The PEM encoded certificate as a text variable
3035
3136
In the static file configuration of Traefik
37+
3238
```yaml
3339
http:
3440
middlewares:
3541
crowdsec:
3642
plugin:
3743
bouncer:
3844
crowdsecLapiTlsCertificateAuthority: |-
39-
-----BEGIN CERTIFICATE-----
40-
MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
41-
MRAwDgYDVQQHDAdTZWF0dGxlMRMwEQYDVQQIDApXYXNoaW5ndG9uMSIwIAYDVQQK
42-
...
43-
C6qNieSwcvWL7C03ri0DefTQMY54r5wP33QU5hJ71JoaZI3YTeT0Nf+NRL4hM++w
44-
Q0veeNzBQXg1f/JxfeA39IDIX1kiCf71tGlT
45-
-----END CERTIFICATE-----
45+
-----BEGIN CERTIFICATE-----
46+
MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
47+
MRAwDgYDVQQHDAdTZWF0dGxlMRMwEQYDVQQIDApXYXNoaW5ndG9uMSIwIAYDVQQK
48+
...
49+
C6qNieSwcvWL7C03ri0DefTQMY54r5wP33QU5hJ71JoaZI3YTeT0Nf+NRL4hM++w
50+
Q0veeNzBQXg1f/JxfeA39IDIX1kiCf71tGlT
51+
-----END CERTIFICATE-----
4652
```
53+
4754
In a dynamic configuration of a provider (ex docker) as a Label
55+
4856
```yaml
4957
services:
5058
whoami-foo:
@@ -71,26 +79,34 @@ The service `whoami-foo` will authenticate with an **API key** over HTTPS after
7179
The service `whoami-bar` will authenticate with a **client certificate** signed by the CA.
7280

7381
Access to a route that communicate via https and authenticate with API-key:
82+
7483
```
7584
curl http://localhost:8000/foo
7685
```
86+
7787
Access to a route that communicate via https and authenticate with a client certificate:
88+
7889
```
7990
curl http://localhost:8000/bar
8091
```
92+
8193
Access to the traefik dashboard
94+
8295
```
8396
curl http://localhost:8080/dashboard/#/
8497
```
8598
8699
To play the demo environnement run:
100+
87101
```bash
88102
make run_tlsauth
89103
```
90104

91105
Note:
92-
> Traefik need to be restarted if certificates are regenerated after his launch
106+
107+
> Traefik need to be restarted if certificates are regenerated after his launch, crowdsec also
93108
94109
## Separate LAPI and Appsec HTTP/S config
110+
95111
To separate TLS config for LAPI and Appsec, you can use all the TLS LAPI variable beginning with `CrowdsecLapi...` into `CrowdsecAppsec...`.
96112
Don't forget to set `CrowdsecAppsecScheme: HTTP` or `HTTPS` to trigger the separate setup.

β€Žexamples/tls-auth/config/acquis.yamlβ€Ž

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,12 @@ filenames:
22
- /var/log/traefik/access.log
33
labels:
44
type: traefik
5+
---
6+
listen_addr: 0.0.0.0:7422
7+
appsec_config: crowdsecurity/virtual-patching
8+
name: myAppSecComponent
9+
source: appsec
10+
labels:
11+
type: appsec
12+
cert_file: /etc/crowdsec/certs/server.pem
13+
key_file: /etc/crowdsec/certs/server-key.pem

0 commit comments

Comments
Β (0)