First Commit
This commit is contained in:
commit
2e5a4751a7
30 changed files with 2517 additions and 0 deletions
109
tests/smoke.sh
Executable file
109
tests/smoke.sh
Executable 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue