Skip to content

Commit 7f7a855

Browse files
authored
Merge pull request #8 from meshcloud/feature/keycloak
Feature/keycloak
2 parents 94dbe9c + d57f29a commit 7f7a855

30 files changed

+2249
-244
lines changed

.github/workflows/build-container.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ on:
2525
caddy_version:
2626
description: 'Caddy version to build'
2727
required: false
28-
default: '2.7'
28+
default: '2.9.1'
2929
type: string
3030
coraza_version:
3131
description: 'Coraza version to build'
@@ -89,7 +89,7 @@ jobs:
8989
with:
9090
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
9191
tags: |
92-
type=raw,value=caddy-${{ github.event.inputs.caddy_version || '2.8' }}-coraza-${{ github.event.inputs.coraza_version || 'v2.0.0' }}
92+
type=raw,value=caddy-${{ github.event.inputs.caddy_version || '2.9.1' }}-coraza-${{ github.event.inputs.coraza_version || 'v2.0.0' }}
9393
type=sha,prefix=build-
9494
type=raw,value=latest,enable={{is_default_branch}}
9595
@@ -102,7 +102,7 @@ jobs:
102102
tags: ${{ steps.meta.outputs.tags }}
103103
labels: ${{ steps.meta.outputs.labels }}
104104
build-args: |
105-
CADDY_VERSION=${{ github.event.inputs.caddy_version || '2.8' }}
105+
CADDY_VERSION=${{ github.event.inputs.caddy_version || '2.9.1' }}
106106
CORAZA_VERSION=${{ github.event.inputs.coraza_version || 'v2.0.0' }}
107107
cache-from: type=gha
108108
cache-to: type=gha,mode=max

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,12 @@ helpers/foundation-deployer/.steps.json
8080

8181
# Go multi-module workspace sum
8282
go.work.sum
83+
84+
# Certificate files
85+
*.pem
86+
*.crt
87+
*.key
88+
89+
# Docker compose - Azure-specific opkssh config (contains FQDNs)
90+
docker-compose/opk-providers-azure/providers
91+
docker-compose/opk-auth_id-azure/auth_id

Caddyfile

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
order coraza_waf first
3+
auto_https disable_redirects
34
}
45

56
# --- WAF for MinIO UI (port 8080) ---
@@ -10,7 +11,7 @@
1011

1112
# Handle WebSocket paths without WAF
1213
handle /ws/* {
13-
reverse_proxy localhost:9001 {
14+
reverse_proxy minio:9001 {
1415
header_up Host {http.request.host}
1516
header_up X-Real-IP {remote}
1617
header_up X-Forwarded-For {remote}
@@ -37,7 +38,7 @@
3738
`
3839
}
3940

40-
reverse_proxy localhost:9001 {
41+
reverse_proxy minio:9001 {
4142
header_up Host {http.request.host}
4243
header_up X-Real-IP {remote}
4344
header_up X-Forwarded-For {remote}
@@ -60,6 +61,42 @@
6061
}
6162
}
6263

64+
# --- Keycloak Proxy HTTP (port 8082) ---
65+
:8082 {
66+
reverse_proxy keycloak:8083 {
67+
header_up Host localhost:8082
68+
header_up X-Real-IP {remote}
69+
header_up X-Forwarded-Proto http
70+
header_up X-Forwarded-Host localhost:8082
71+
header_up X-Forwarded-Port 8082
72+
}
73+
74+
log {
75+
output stdout
76+
format json
77+
level INFO
78+
}
79+
}
80+
81+
# --- Keycloak Proxy HTTPS (port 8443) ---
82+
localhost:8443 {
83+
tls internal
84+
85+
reverse_proxy keycloak:8083 {
86+
header_up Host localhost:8443
87+
header_up X-Real-IP {remote}
88+
header_up X-Forwarded-Proto https
89+
header_up X-Forwarded-Host localhost:8443
90+
header_up X-Forwarded-Port 8443
91+
}
92+
93+
log {
94+
output stdout
95+
format json
96+
level INFO
97+
}
98+
}
99+
63100
# --- WAF for MinIO API (port 8081) ---
64101
:8081 {
65102
handle /health {
@@ -78,7 +115,7 @@
78115
`
79116
}
80117

81-
reverse_proxy localhost:9000 {
118+
reverse_proxy minio:9000 {
82119
header_up Connection {http.request.header.connection}
83120
header_up Upgrade {http.request.header.upgrade}
84121
}

Caddyfile.azure

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
order coraza_waf first
3+
auto_https disable_redirects
4+
}
5+
6+
# --- WAF for MinIO UI (port 8080) ---
7+
:8080 {
8+
handle /health {
9+
respond "WAF-UI-OK" 200
10+
}
11+
12+
# Handle WebSocket paths without WAF
13+
handle /ws/* {
14+
reverse_proxy localhost:9001 {
15+
header_up Host {http.request.host}
16+
header_up X-Real-IP {remote}
17+
header_up X-Forwarded-For {remote}
18+
header_up X-Forwarded-Proto {scheme}
19+
header_up Connection {http.request.header.connection}
20+
header_up Upgrade {http.request.header.upgrade}
21+
header_up Sec-WebSocket-Key {http.request.header.sec-websocket-key}
22+
header_up Sec-WebSocket-Version {http.request.header.sec-websocket-version}
23+
transport http {
24+
read_timeout 300s
25+
dial_timeout 300s
26+
}
27+
}
28+
}
29+
30+
route {
31+
coraza_waf {
32+
load_owasp_crs
33+
directives `
34+
SecAction "id:1,phase:1,pass,nolog,initcol:tx=tx"
35+
SecAction "id:2,phase:1,pass,nolog,setvar:tx.bucket_ops=0"
36+
SecRule REQUEST_METHOD "@rx ^(PUT|POST|DELETE)$" "id:1003,phase:1,pass,msg:'Bucket operation',setvar:tx.bucket_ops=+1,expirevar:tx.bucket_ops=60"
37+
SecRule TX:bucket_ops "@gt 50" "id:1004,phase:1,deny,status:429,msg:'Bucket operation rate limit exceeded'"
38+
`
39+
}
40+
41+
reverse_proxy localhost:9001 {
42+
header_up Host {http.request.host}
43+
header_up X-Real-IP {remote}
44+
header_up X-Forwarded-For {remote}
45+
header_up X-Forwarded-Proto {scheme}
46+
header_up Connection {http.request.header.connection}
47+
header_up Upgrade {http.request.header.upgrade}
48+
header_up Sec-WebSocket-Key {http.request.header.sec-websocket-key}
49+
header_up Sec-WebSocket-Version {http.request.header.sec-websocket-version}
50+
transport http {
51+
read_timeout 300s
52+
dial_timeout 300s
53+
}
54+
}
55+
}
56+
57+
log {
58+
output stdout
59+
format json
60+
level INFO
61+
}
62+
}
63+
64+
# --- Keycloak Proxy HTTP (port 8082) ---
65+
:8082 {
66+
reverse_proxy localhost:8083 {
67+
header_up Host {http.request.host}
68+
header_up X-Real-IP {remote}
69+
header_up X-Forwarded-For {remote}
70+
header_up X-Forwarded-Proto https
71+
header_up X-Forwarded-Host {http.request.host}
72+
header_up X-Forwarded-Port 8444
73+
header_up Accept-Encoding identity
74+
}
75+
76+
replace {
77+
"http://localhost:8083" "https://testminio.germanywestcentral.cloudapp.azure.com:8444"
78+
}
79+
80+
log {
81+
output stdout
82+
format json
83+
level INFO
84+
}
85+
}
86+
87+
# --- WAF for MinIO API (port 8081) ---
88+
:8081 {
89+
handle /health {
90+
respond "WAF-API-OK" 200
91+
}
92+
93+
route {
94+
coraza_waf {
95+
load_owasp_crs
96+
directives `
97+
SecAction "id:10,phase:1,pass,nolog,initcol:tx=tx"
98+
SecAction "id:11,phase:1,pass,nolog,setvar:tx.bucket_ops=0"
99+
SecRule REQUEST_METHOD "@streq DELETE" "id:2001,phase:1,log,msg:'DELETE operation logged'"
100+
SecRule REQUEST_METHOD "@rx ^(PUT|POST|DELETE)$" "id:2002,phase:1,pass,msg:'Bucket operation',setvar:tx.bucket_ops=+1,expirevar:tx.bucket_ops=60"
101+
SecRule TX:bucket_ops "@gt 50" "id:2003,phase:1,deny,status:429,msg:'Bucket operation rate limit exceeded'"
102+
`
103+
}
104+
105+
reverse_proxy localhost:9000 {
106+
header_up Connection {http.request.header.connection}
107+
header_up Upgrade {http.request.header.upgrade}
108+
}
109+
}
110+
111+
log {
112+
output stdout
113+
format json
114+
level INFO
115+
}
116+
}

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Multi-stage build for Coraza-Caddy WAF
22

33
# --- Versions ---
4-
ARG CADDY_VERSION=2.9
4+
ARG CADDY_VERSION=2.9.1
55
ARG CORAZA_VERSION=v2.0.0
66

77
# --- Build stage ---

README-coraza.md

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ A modern Web Application Firewall built with [Coraza](https://coraza.io) and [Ca
55
## Features
66

77
-**OWASP Core Rule Set v4** - Latest security rules
8-
-**Multi-backend routing** - Single WAF protects MinIO UI + API
8+
-**Multi-backend routing** - Single WAF protects MinIO UI + API + Keycloak
99
-**Security headers** - Production-ready security configuration
1010
-**Health checks** - Built-in monitoring endpoints
1111
-**Rate limiting** - API protection against abuse
@@ -28,6 +28,7 @@ docker pull ghcr.io/YOUR_USERNAME/minio_azure_container_app/coraza-caddy:latest
2828
|----------|---------|-------------|
2929
| `MINIO_UI_BACKEND` | `localhost:9001` | MinIO Console backend |
3030
| `MINIO_API_BACKEND` | `localhost:9000` | MinIO S3 API backend |
31+
| `KEYCLOAK_BACKEND` | `localhost:8083` | Keycloak backend (Azure only) |
3132

3233
### Basic Usage
3334

@@ -46,18 +47,39 @@ docker run -d \
4647
```
4748
Caddy WAF (8080) → MinIO UI (9001)
4849
(8081) → MinIO API (9000)
50+
(8082) → Keycloak (8083) [Azure only]
51+
(8443) → Keycloak HTTPS (8083) [Local dev only]
4952
```
5053

54+
### Port Mapping
55+
56+
| Port | Service | WAF Enabled | Environment |
57+
|------|---------|-------------|-------------|
58+
| 8080 | MinIO UI | ✅ Yes | Both |
59+
| 8081 | MinIO API | ✅ Yes | Both |
60+
| 8082 | Keycloak HTTP | ❌ No (proxy only) | Azure |
61+
| 8443 | Keycloak HTTPS | ❌ No (proxy only) | Local dev |
62+
5163
### Request Routing
5264

65+
**MinIO UI (port 8080):**
5366
- **`/`** → MinIO Console (UI)
54-
- **`/api/*`** → MinIO S3 API
55-
- **`/s3/*`** → MinIO S3 API (direct bucket access)
67+
- **`/ws/*`** → WebSocket connections (WAF bypassed)
68+
- **`/health`** → Health check endpoint
69+
70+
**MinIO API (port 8081):**
71+
- **All paths** → MinIO S3 API
5672
- **`/health`** → Health check endpoint
5773

74+
**Keycloak (port 8082/8443):**
75+
- **All paths** → Keycloak authentication service
76+
5877
## Security Features
5978

60-
### WAF Protection
79+
### WAF Protection (MinIO UI & API only)
80+
81+
Keycloak endpoints use simple reverse proxy without WAF to avoid conflicts with authentication flows.
82+
6183
- SQL injection prevention
6284
- XSS protection
6385
- Command injection blocking
@@ -86,10 +108,14 @@ env:
86108
value: "localhost:9001"
87109
- name: MINIO_API_BACKEND
88110
value: "localhost:9000"
111+
- name: KEYCLOAK_BACKEND
112+
value: "localhost:8083"
89113
```
90114
91115
### Health Check
92-
The container exposes `/health` on port 8080 for health checks.
116+
The container exposes `/health` endpoints:
117+
- Port 8080: MinIO UI health check
118+
- Port 8081: MinIO API health check
93119

94120
## Development
95121

@@ -125,7 +151,11 @@ docker logs minio-waf | jq '.audit'
125151

126152
### Health Check
127153
```bash
154+
# MinIO UI health check
128155
curl http://localhost:8080/health
156+
157+
# MinIO API health check
158+
curl http://localhost:8081/health
129159
```
130160

131161
### WAF Status

0 commit comments

Comments
 (0)