First Commit

This commit is contained in:
Lonny Lowe 2026-09-24 11:29:54 -05:00
commit 2e5a4751a7
30 changed files with 2517 additions and 0 deletions

109
tests/smoke.sh Executable file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env bash
# =====================================================================================
# End-to-end smoke test. Fully isolated: realm TESTLAB.LOCAL on an internal-only docker
# network, named volumes, no host ports, throwaway credentials.
#
# Proves, in order:
# 1. the image builds
# 2. a fresh volume provisions a working AD DC (DNS/Kerberos/LDAP/GC/SYSVOL)
# 3. hardening params actually land in smb.conf
# 4. a restart REUSES the database instead of re-provisioning (idempotency)
# 5. the full verify battery passes both before and after the restart
#
# ./tests/smoke.sh # build + test + destroy
# KEEP=1 ./tests/smoke.sh # leave the lab container running for poking at
# =====================================================================================
set -uo pipefail
cd "$(dirname "$0")/.."
LAB_FILE=docker-compose.lab.yml
CID=ad-lab
LAB_PW='Lab!Only9Tester#2026'
IMAGE=local/samba-ad-dc:4.22-debian13
fail_hard() {
echo
echo "!! ${1}" >&2
echo "---- recent log (schema-apply noise filtered) ----" >&2
docker compose -f "$LAB_FILE" logs --tail 400 2>&1 \
| grep -vE '(Applied|Skip) (Domain|Forest) Update' | tail -40 | sed 's/^/ /' >&2
[ "${KEEP:-0}" = 1 ] || docker compose -f "$LAB_FILE" down -v >/dev/null 2>&1 || true
exit 1
}
echo "==> 1/6 build image"
if ! docker build -t "$IMAGE" -f image/Dockerfile . ; then
echo "!! image build failed" >&2
exit 1
fi
echo "==> 2/6 start lab DC"
docker compose -f "$LAB_FILE" down -v >/dev/null 2>&1 || true # always start from a clean slate
docker compose -f "$LAB_FILE" up -d >/dev/null 2>&1 || fail_hard "compose up failed"
wait_healthy() { # $1 = seconds
local deadline=$(( SECONDS + ${1:-240} )) st=""
while [ "$SECONDS" -lt "$deadline" ]; do
st="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$CID" 2>/dev/null || echo missing)"
[ "$st" = healthy ] && return 0
[ "$st" = unhealthy ] && return 2
printf '.'
sleep 4
done
return 1
}
printf ' waiting for healthy '
wait_healthy 300; rc=$?
echo " -> $rc"
[ "$rc" = 0 ] || fail_hard "lab DC never became healthy (rc=$rc)"
if ! docker compose -f "$LAB_FILE" logs 2>&1 | grep -q 'provisioning complete'; then
fail_hard "expected the entrypoint to report a fresh provisioning run"
fi
echo " fresh provisioning reported"
verify() {
AD_SKIP_DOTENV=1 AD_CONTAINER="$CID" \
AD_REALM=TESTLAB.LOCAL AD_DNS_DOMAIN=testlab.local AD_HOSTNAME=dc1 \
AD_ADMIN_PASSWORD="$LAB_PW" ./scripts/verify.sh
}
echo "==> 3/6 verification battery (fresh forest)"
verify || fail_hard "verification failed on a freshly provisioned forest"
echo "==> 4/6 hardening landed in smb.conf"
for kv in 'server signing = required' 'smb encrypt = desired' 'ntlm auth = ntlmv2-only' 'restrict anonymous = 2'; do
if docker exec "$CID" grep -q "^[[:space:]]*${kv}[[:space:]]*$" /etc/samba/smb.conf; then
echo " ok: $kv"
else
fail_hard "missing '$kv' in rendered smb.conf"
fi
done
echo "==> 5/6 restart must NOT re-provision"
# Count log lines first and diff afterwards: `docker logs --since` is interpreted in the
# daemon's local timezone, which silently mis-filters when the host is not UTC.
log_before="$(docker compose -f "$LAB_FILE" logs 2>/dev/null | wc -l)"
docker restart "$CID" >/dev/null 2>&1 || fail_hard "restart failed"
printf ' waiting for healthy after restart '
wait_healthy 180; rc=$?
echo " -> $rc"
[ "$rc" = 0 ] || fail_hard "not healthy after restart"
log="$(docker compose -f "$LAB_FILE" logs 2>/dev/null | tail -n +$((log_before + 1)))"
if printf '%s' "$log" | grep -q 'provisioning NEW forest'; then
fail_hard "restart tried to re-provision the domain (idempotency broken)"
fi
printf '%s' "$log" | grep -q 'existing AD database found' || fail_hard "restart did not detect the existing database"
echo " entrypoint reused the existing database"
echo "==> 6/6 verification battery (after restart)"
verify || fail_hard "verification failed after restart"
echo
echo -e "\033[32mSMOKE TEST PASSED\033[0m (image: $IMAGE)"
if [ "${KEEP:-0}" = 1 ]; then
echo "lab left running: docker compose -f $LAB_FILE logs -f | docker exec -it $CID bash"
else
docker compose -f "$LAB_FILE" down -v >/dev/null 2>&1 || true
echo "lab destroyed"
fi