#!/usr/bin/env bash # ===================================================================================== # LDAPS test. Proves three separate things: # * the DC serves 636 and the chain verifies against our CA # * the SAN actually matches the DC FQDN (Windows requires SAN, not CN) # * a client WITHOUT our CA is rejected (i.e. we are not accidentally self-trusted) # Run ./scripts/tls.sh first to create secrets/tls/. # ./tests/ldaps-test.sh # tears down afterwards # ===================================================================================== # LDAPS end-to-end check against a freshly provisioned DC with our generated certs. set -uo pipefail cd /dockers/WindowsAD PW='Lab!Only9Tester#2026' LABTLS="$PWD/secrets/tls-lab" trap '[ "${KEEP:-0}" = 1 ] || { docker rm -f ad-tlslab >/dev/null 2>&1; docker volume rm tlslab-lib >/dev/null 2>&1; rm -rf "$LABTLS"; }' EXIT # certs for THIS lab only. Never reuse secrets/tls: that is the production chain, # regenerating it here would silently destroy the trust anchor every client has installed. echo "=== generating throwaway testlab CA + leaf (isolated dir, no SYSVOL publish) ===" mkdir -p "$LABTLS" AD_TLS_DIR="$LABTLS" AD_TLS_PUBLISH=no AD_REALM=TESTLAB.LOCAL AD_DNS_DOMAIN=testlab.local \ AD_HOSTNAME=dc1 AD_IP=172.28.90.10 AD_CONTAINER=ad-tlslab-absent ./scripts/tls.sh >/tmp/ldaps-tls.log 2>&1 \ || { echo "cert generation failed:"; tail -15 /tmp/ldaps-tls.log; exit 1; } # Guard: refuse to run against a cert that is not ours, otherwise this test silently tests the # production chain and can "pass" for the wrong reason (or fail confusingly). openssl x509 -in "$LABTLS/dc.crt" -noout -subject | grep -q 'testlab.local' \ || { echo "!! $LABTLS/dc.crt is not a testlab cert - refusing to run this test"; exit 1; } openssl x509 -in "$LABTLS/dc.crt" -noout -ext subjectAltName | sed 's/^/ /' docker rm -f ad-tlslab >/dev/null 2>&1 || true docker volume rm tlslab-lib >/dev/null 2>&1 || true docker network rm adlab >/dev/null 2>&1 || true docker network create --subnet 172.28.90.0/24 --internal adlab >/dev/null docker run -d --name ad-tlslab --hostname dc1.testlab.local --network adlab --ip 172.28.90.10 \ --cap-drop ALL --cap-add SYS_ADMIN --cap-add CHOWN --cap-add FOWNER --cap-add DAC_OVERRIDE \ --cap-add SETUID --cap-add SETGID --cap-add NET_BIND_SERVICE \ -v "$PWD/secrets:/run/ad-secrets:ro" -v "$LABTLS:/run/ad-secrets/tls:ro" -v tlslab-lib:/var/lib/samba \ -e AD_REALM=TESTLAB.LOCAL -e AD_DNS_DOMAIN=testlab.local -e AD_HOSTNAME=dc1 \ -e AD_IP=172.28.90.10 -e AD_ADMIN_PASSWORD="$PW" \ -e AD_TLS_CERT=/run/ad-secrets/tls/dc.crt -e AD_TLS_KEY=/run/ad-secrets/tls/dc.key \ -e AD_TLS_CA=/run/ad-secrets/tls/ca.crt \ local/samba-ad-dc:4.22-debian13 >/dev/null || { echo "start failed"; exit 1; } h=none for _ in $(seq 1 60); do h="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' ad-tlslab 2>/dev/null || echo gone)" [ "$h" = healthy ] && break sleep 4 done echo "health: $h" st="$(docker inspect -f '{{.State.Status}} exit={{.State.ExitCode}}' ad-tlslab 2>/dev/null)" echo "state: $st" [ "$h" = healthy ] || { echo "--- log ---"; docker logs ad-tlslab 2>&1 | grep -vE 'Applied |Skip ' | tail -20; exit 1; } echo "=== 636 listening? ===" docker exec ad-tlslab ss -ltn | grep ':636' || { echo "636 not listening"; exit 1; } echo "=== handshake, trusting our CA (must verify) ===" docker exec ad-tlslab openssl s_client -connect 127.0.0.1:636 \ -CAfile /run/ad-secrets/tls/ca.crt -verify_return_error &1 \ | grep -E 'Verify return code|subject=|CN' | head -4 echo "=== handshake with default trust store (must FAIL, proves certs are not self-trusted) ===" if docker exec ad-tlslab openssl s_client -connect 127.0.0.1:636 -verify_return_error /dev/null 2>&1; then echo "UNEXPECTED: untrusted handshake succeeded"; RC=1 else echo "rejected as expected ✔" fi echo "=== full battery with LDAPS enabled ===" AD_SKIP_DOTENV=1 AD_CONTAINER=ad-tlslab AD_REALM=TESTLAB.LOCAL AD_DNS_DOMAIN=testlab.local \ AD_HOSTNAME=dc1 AD_ADMIN_PASSWORD="$PW" \ AD_TLS_CERT=/run/ad-secrets/tls/dc.crt AD_TLS_CA=/run/ad-secrets/tls/ca.crt \ ./scripts/verify.sh | grep -E 'LDAPS|passed,' RC=${RC:-0} exit "$RC"