11#! /usr/bin/env bash
2- # test-lab-09-05.sh — Lab 09-05: Advanced Integration
3- # Module 09: iRedMail email server
4- # iredmail integrated with full IT-Stack ecosystem
2+ # test-lab-09-05.sh -- Lab 05: iRedMail Advanced Integration
3+ # Tests: OpenLDAP bind, Keycloak realm+LDAP-federation, iRedMail LDAP config, mailhog relay
4+ #
5+ # Usage: bash tests/labs/test-lab-09-05.sh [--no-cleanup]
56set -euo pipefail
67
7- LAB_ID=" 09-05"
8- LAB_NAME=" Advanced Integration"
9- MODULE=" iredmail"
108COMPOSE_FILE=" docker/docker-compose.integration.yml"
11- PASS=0
12- FAIL=0
13-
14- # ── Colors ────────────────────────────────────────────────────────────────────
15- RED=' \033[0;31m' ; GREEN=' \033[0;32m' ; YELLOW=' \033[1;33m'
16- CYAN=' \033[0;36m' ; NC=' \033[0m'
17-
18- pass () { echo -e " ${GREEN} [PASS]${NC} $1 " ; (( PASS++ )) ; }
19- fail () { echo -e " ${RED} [FAIL]${NC} $1 " ; (( FAIL++ )) ; }
20- info () { echo -e " ${CYAN} [INFO]${NC} $1 " ; }
21- warn () { echo -e " ${YELLOW} [WARN]${NC} $1 " ; }
22-
23- echo -e " ${CYAN} ======================================${NC} "
24- echo -e " ${CYAN} Lab ${LAB_ID} : ${LAB_NAME}${NC} "
25- echo -e " ${CYAN} Module: ${MODULE}${NC} "
26- echo -e " ${CYAN} ======================================${NC} "
27- echo " "
28-
29- # ── PHASE 1: Setup ────────────────────────────────────────────────────────────
30- info " Phase 1: Setup"
31- docker compose -f " ${COMPOSE_FILE} " up -d
32- info " Waiting 30s for ${MODULE} to initialize..."
33- sleep 30
34-
35- # ── PHASE 2: Health Checks ────────────────────────────────────────────────────
36- info " Phase 2: Health Checks"
37-
38- if docker compose -f " ${COMPOSE_FILE} " ps | grep -q " running\|Up" ; then
39- pass " Container is running"
9+ KC_PORT=8108
10+ MAIL_PORT=9180
11+ LDAP_PORT=3892
12+ MAILHOG_PORT=8025
13+ KC_ADMIN=admin
14+ KC_PASS=" Lab05Admin!"
15+ LDAP_ADMIN_DN=" cn=admin,dc=lab,dc=local"
16+ LDAP_PASS=" LdapAdmin05!"
17+ READONLY_DN=" cn=readonly,dc=lab,dc=local"
18+ READONLY_PASS=" ReadOnly05!"
19+ CLEANUP=true
20+ [[ " ${1:- } " == " --no-cleanup" ]] && CLEANUP=false
21+
22+ PASS=0; FAIL=0
23+ pass () { echo " [PASS] $1 " ; (( PASS++ )) ; }
24+ fail () { echo " [FAIL] $1 " ; (( FAIL++ )) ; }
25+ section () { echo " " ; echo " === $1 ===" ; }
26+ cleanup () { $CLEANUP && docker compose -f " $COMPOSE_FILE " down -v 2> /dev/null || true ; }
27+ trap cleanup EXIT
28+
29+ section " Lab 09-05: iRedMail Advanced Integration"
30+ echo " Compose file: $COMPOSE_FILE "
31+
32+ section " 1. Start Containers"
33+ docker compose -f " $COMPOSE_FILE " up -d
34+ echo " Waiting for services to initialize..."
35+ sleep 40
36+
37+ section " 2. Keycloak Health"
38+ for i in $( seq 1 24) ; do
39+ if curl -sf " http://localhost:${KC_PORT} /health/ready" | grep -q " UP" ; then
40+ pass " Keycloak health/ready UP"
41+ break
42+ fi
43+ [[ $i -eq 24 ]] && fail " Keycloak did not become healthy" && exit 1
44+ sleep 10
45+ done
46+
47+ section " 3. OpenLDAP Connectivity"
48+ for i in $( seq 1 12) ; do
49+ if docker exec iredmail-int-ldap ldapsearch -x -H ldap://localhost \
50+ -b " dc=lab,dc=local" -D " $LDAP_ADMIN_DN " -w " $LDAP_PASS " \
51+ -s base " (objectClass=*)" > /dev/null 2>&1 ; then
52+ pass " LDAP admin bind successful"
53+ break
54+ fi
55+ [[ $i -eq 12 ]] && fail " LDAP admin bind failed after 120s"
56+ sleep 10
57+ done
58+
59+ # Readonly bind
60+ if docker exec iredmail-int-ldap ldapsearch -x -H ldap://localhost \
61+ -b " dc=lab,dc=local" -D " $READONLY_DN " -w " $READONLY_PASS " \
62+ -s base " (objectClass=*)" > /dev/null 2>&1 ; then
63+ pass " LDAP readonly bind successful"
4064else
41- fail " Container is not running "
65+ fail " LDAP readonly bind failed "
4266fi
4367
44- # ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
45- info " Phase 3: Functional Tests (Lab 05 — Advanced Integration)"
46-
47- # TODO: Add module-specific functional tests here
48- # Example:
49- # if curl -sf http://localhost:25/health > /dev/null 2>&1; then
50- # pass "Health endpoint responds"
51- # else
52- # fail "Health endpoint not reachable"
53- # fi
54-
55- warn " Functional tests for Lab 09-05 pending implementation"
56-
57- # ── PHASE 4: Cleanup ──────────────────────────────────────────────────────────
58- info " Phase 4: Cleanup"
59- docker compose -f " ${COMPOSE_FILE} " down -v --remove-orphans
60- info " Cleanup complete"
61-
62- # ── Results ───────────────────────────────────────────────────────────────────
63- echo " "
64- echo -e " ${CYAN} ======================================${NC} "
65- echo -e " Lab ${LAB_ID} Complete"
66- echo -e " ${GREEN} PASS: ${PASS}${NC} | ${RED} FAIL: ${FAIL}${NC} "
67- echo -e " ${CYAN} ======================================${NC} "
68-
69- if [ " ${FAIL} " -gt 0 ]; then
70- exit 1
71- fi
68+ section " 4. Keycloak Realm + LDAP Federation"
69+ KC_TOKEN=$( curl -sf " http://localhost:${KC_PORT} /realms/master/protocol/openid-connect/token" \
70+ -d " client_id=admin-cli&grant_type=password&username=${KC_ADMIN} &password=${KC_PASS} " \
71+ | grep -o ' "access_token":"[^"]*"' | cut -d' "' -f4)
72+ [[ -n " $KC_TOKEN " ]] && pass " Keycloak admin token obtained" || { fail " Keycloak admin token failed" ; exit 1; }
73+
74+ HTTP=$( curl -s -o /dev/null -w " %{http_code}" -X POST \
75+ " http://localhost:${KC_PORT} /admin/realms" \
76+ -H " Authorization: Bearer $KC_TOKEN " \
77+ -H " Content-Type: application/json" \
78+ -d ' {"realm":"it-stack","enabled":true}' )
79+ [[ " $HTTP " =~ ^(201| 409)$ ]] && pass " Realm it-stack created (HTTP $HTTP )" || fail " Realm creation failed (HTTP $HTTP )"
80+
81+ LDAP_FED_PAYLOAD=' {"name":"ldap","providerId":"ldap","providerType":"org.keycloak.storage.UserStorageProvider","config":{"vendor":["other"],"connectionUrl":["ldap://iredmail-int-ldap:389"],"bindDn":["' " $LDAP_ADMIN_DN " ' "],"bindCredential":["LdapAdmin05!"],"usersDn":["dc=lab,dc=local"],"usernameLDAPAttribute":["uid"],"rdnLDAPAttribute":["uid"],"uuidLDAPAttribute":["entryUUID"],"userObjectClasses":["inetOrgPerson"],"syncRegistrations":["false"],"enabled":["true"]}}'
82+ HTTP=$( curl -s -o /dev/null -w " %{http_code}" -X POST \
83+ " http://localhost:${KC_PORT} /admin/realms/it-stack/components" \
84+ -H " Authorization: Bearer $KC_TOKEN " \
85+ -H " Content-Type: application/json" \
86+ -d " $LDAP_FED_PAYLOAD " )
87+ [[ " $HTTP " =~ ^(201| 409)$ ]] && pass " Keycloak LDAP federation registered (HTTP $HTTP )" || fail " LDAP federation failed (HTTP $HTTP )"
88+
89+ section " 5. iRedMail Environment"
90+ APP_ENV=$( docker inspect iredmail-int-app --format ' {{range .Config.Env}}{{.}} {{end}}' )
91+
92+ echo " $APP_ENV " | grep -q " LDAP_SERVER_HOST=iredmail-int-ldap" \
93+ && pass " LDAP_SERVER_HOST=iredmail-int-ldap" \
94+ || fail " LDAP_SERVER_HOST missing"
95+
96+ echo " $APP_ENV " | grep -q " LDAP_BIND_DN=cn=readonly" \
97+ && pass " LDAP_BIND_DN uses readonly account" \
98+ || fail " LDAP_BIND_DN missing/wrong"
99+
100+ echo " $APP_ENV " | grep -q " LDAP_BASEDN=dc=lab,dc=local" \
101+ && pass " LDAP_BASEDN=dc=lab,dc=local" \
102+ || fail " LDAP_BASEDN missing"
103+
104+ echo " $APP_ENV " | grep -q " RELAY_HOST=iredmail-int-smtp-relay" \
105+ && pass " RELAY_HOST=iredmail-int-smtp-relay" \
106+ || fail " RELAY_HOST missing"
107+
108+ section " 6. iRedMail HTTP Admin Panel"
109+ for i in $( seq 1 20) ; do
110+ HTTP=$( curl -s -o /dev/null -w " %{http_code}" " http://localhost:${MAIL_PORT} /" 2> /dev/null || echo " 000" )
111+ if [[ " $HTTP " =~ ^(200| 302| 301)$ ]]; then
112+ pass " iRedMail HTTP admin panel responds (HTTP $HTTP )"
113+ break
114+ fi
115+ [[ $i -eq 20 ]] && fail " iRedMail admin panel did not become ready (last HTTP $HTTP )"
116+ sleep 15
117+ done
118+
119+ section " 7. Mailhog SMTP Relay"
120+ HTTP=$( curl -s -o /dev/null -w " %{http_code}" " http://localhost:${MAILHOG_PORT} /" 2> /dev/null || echo " 000" )
121+ [[ " $HTTP " =~ ^(200| 302)$ ]] \
122+ && pass " Mailhog web UI accessible (HTTP $HTTP )" \
123+ || fail " Mailhog web UI unreachable (HTTP $HTTP )"
124+
125+ section " 8. Keycloak LDAP Components Listed"
126+ COMPONENTS=$( curl -sf " http://localhost:${KC_PORT} /admin/realms/it-stack/components?type=org.keycloak.storage.UserStorageProvider" \
127+ -H " Authorization: Bearer $KC_TOKEN " 2> /dev/null || echo " []" )
128+ echo " $COMPONENTS " | grep -q " ldap" \
129+ && pass " Keycloak LDAP user storage provider listed" \
130+ || fail " Keycloak LDAP provider not found in components"
131+
132+ section " Summary"
133+ echo " Passed: $PASS | Failed: $FAIL "
134+ [[ $FAIL -eq 0 ]] && echo " Lab 09-05 PASSED" || { echo " Lab 09-05 FAILED" ; exit 1; }
0 commit comments