Skip to content

Commit 6528614

Browse files
committed
feat(lab-03): Keycloak advanced — 2-node cluster, MailHog SMTP, brute-force policy, custom scopes
1 parent fac797a commit 6528614

3 files changed

Lines changed: 291 additions & 86 deletions

File tree

.github/workflows/ci.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,37 @@ jobs:
148148

149149
- name: Cleanup
150150
if: always()
151-
run: docker compose -f docker/docker-compose.lan.yml down -v
151+
run: docker compose -f docker/docker-compose.lan.yml down -v
152+
153+
lab-03-smoke:
154+
name: Lab 03 — Keycloak Cluster + MailHog
155+
runs-on: ubuntu-latest
156+
needs: validate
157+
continue-on-error: true
158+
steps:
159+
- uses: actions/checkout@v4
160+
161+
- name: Install tools
162+
run: sudo apt-get install -y netcat-openbsd curl
163+
164+
- name: Start advanced stack (2 nodes + postgres + mailhog)
165+
run: docker compose -f docker/docker-compose.advanced.yml up -d
166+
167+
- name: Wait for Keycloak node 1
168+
run: timeout 200 bash -c 'until curl -sf http://localhost:8080/health/ready; do sleep 5; done'
169+
170+
- name: Wait for Keycloak node 2
171+
run: timeout 200 bash -c 'until curl -sf http://localhost:8081/health/ready; do sleep 5; done'
172+
173+
- name: Run Lab 02-03 test script
174+
env:
175+
KC_PASS: "Lab03Password!"
176+
run: bash tests/labs/test-lab-02-03.sh
177+
178+
- name: Collect logs on failure
179+
if: failure()
180+
run: docker compose -f docker/docker-compose.advanced.yml logs
181+
182+
- name: Cleanup
183+
if: always()
184+
run: docker compose -f docker/docker-compose.advanced.yml down -v

docker/docker-compose.advanced.yml

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,116 @@
1-
# Lab 03 — Advanced Features: keycloak with TLS, resource limits, logging
2-
---
1+
# Lab 02-03: Advanced Features — Keycloak cluster + MailHog SMTP + brute force protection
2+
# Purpose: HA deployment, email flow testing, session replication, token policies
3+
#
4+
# Usage:
5+
# docker compose -f docker/docker-compose.advanced.yml up -d
6+
# Keycloak node 1: http://localhost:8080
7+
# Keycloak node 2: http://localhost:8081
8+
# MailHog UI: http://localhost:8025 (catches all Keycloak emails)
9+
# MailHog SMTP: localhost:1025
10+
311
services:
4-
keycloak:
5-
image: quay.io/keycloak/keycloak:24
6-
container_name: it-stack-keycloak
12+
13+
# ─── SHARED DATABASE ─────────────────────────────────────────────────────
14+
keycloak-db:
15+
image: postgres:16-alpine
16+
container_name: it-stack-kc-db-adv
717
restart: unless-stopped
8-
ports:
9-
- "8080:$firstPort"
1018
environment:
11-
- IT_STACK_ENV=lab-03-advanced
12-
- TLS_ENABLED=true
19+
POSTGRES_DB: keycloak
20+
POSTGRES_USER: keycloak
21+
POSTGRES_PASSWORD: "Lab03Password!"
1322
volumes:
14-
- keycloak_data:/var/lib/keycloak
15-
- ./certs:/etc/ssl/certs:ro
16-
deploy:
17-
resources:
18-
limits:
19-
cpus: "2.0"
20-
memory: G
21-
logging:
22-
driver: json-file
23-
options:
24-
max-size: "100m"
25-
max-file: "5"
23+
- kc-db-adv:/var/lib/postgresql/data
2624
networks:
27-
- it-stack-net
25+
- kc-db-net
26+
healthcheck:
27+
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
28+
interval: 10s
29+
timeout: 5s
30+
retries: 5
2831

29-
networks:
30-
it-stack-net:
31-
driver: bridge
32+
# ─── MAILHOG — SMTP sink for email testing ────────────────────────────────
33+
mailhog:
34+
image: mailhog/mailhog:latest
35+
container_name: it-stack-mailhog
36+
restart: unless-stopped
37+
ports:
38+
- "1025:1025" # SMTP
39+
- "8025:8025" # Web UI
40+
networks:
41+
- kc-app-net
42+
43+
# ─── KEYCLOAK NODE 1 ─────────────────────────────────────────────────────
44+
keycloak-1:
45+
image: quay.io/keycloak/keycloak:24.0
46+
container_name: it-stack-keycloak-1
47+
restart: unless-stopped
48+
command: start-dev --http-port=8080
49+
environment:
50+
KC_DB: postgres
51+
KC_DB_URL: jdbc:postgresql://keycloak-db:5432/keycloak
52+
KC_DB_USERNAME: keycloak
53+
KC_DB_PASSWORD: "Lab03Password!"
54+
KC_BOOTSTRAP_ADMIN_USERNAME: admin
55+
KC_BOOTSTRAP_ADMIN_PASSWORD: "Lab03Password!"
56+
KC_HOSTNAME_STRICT: "false"
57+
KC_HTTP_ENABLED: "true"
58+
KC_PROXY_HEADERS: forwarded
59+
# Cache — distributed mode for clustering
60+
KC_CACHE: ispn
61+
KC_CACHE_STACK: tcp
62+
JAVA_OPTS_APPEND: "-Djgroups.bind_addr=it-stack-keycloak-1"
63+
ports:
64+
- "8080:8080"
65+
networks:
66+
- kc-app-net
67+
- kc-db-net
68+
depends_on:
69+
keycloak-db:
70+
condition: service_healthy
71+
healthcheck:
72+
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health/ready || exit 1"]
73+
interval: 15s
74+
timeout: 10s
75+
retries: 15
76+
start_period: 60s
77+
78+
# ─── KEYCLOAK NODE 2 ─────────────────────────────────────────────────────
79+
keycloak-2:
80+
image: quay.io/keycloak/keycloak:24.0
81+
container_name: it-stack-keycloak-2
82+
restart: unless-stopped
83+
command: start-dev --http-port=8081
84+
environment:
85+
KC_DB: postgres
86+
KC_DB_URL: jdbc:postgresql://keycloak-db:5432/keycloak
87+
KC_DB_USERNAME: keycloak
88+
KC_DB_PASSWORD: "Lab03Password!"
89+
KC_BOOTSTRAP_ADMIN_USERNAME: admin
90+
KC_BOOTSTRAP_ADMIN_PASSWORD: "Lab03Password!"
91+
KC_HOSTNAME_STRICT: "false"
92+
KC_HTTP_ENABLED: "true"
93+
KC_PROXY_HEADERS: forwarded
94+
KC_CACHE: ispn
95+
KC_CACHE_STACK: tcp
96+
JAVA_OPTS_APPEND: "-Djgroups.bind_addr=it-stack-keycloak-2"
97+
ports:
98+
- "8081:8081"
99+
networks:
100+
- kc-app-net
101+
- kc-db-net
102+
depends_on:
103+
keycloak-db:
104+
condition: service_healthy
105+
keycloak-1:
106+
condition: service_healthy
32107

33108
volumes:
34-
keycloak_data:
109+
kc-db-adv:
110+
111+
networks:
112+
kc-app-net:
113+
driver: bridge
114+
kc-db-net:
115+
driver: bridge
116+
internal: true

0 commit comments

Comments
 (0)