12da7140c2
docker-compose.test.yml spins up the all-in-one OpenLDAP image, a standalone Redis, and a test-runner that seeds the test user and runs jest against them. globalSetup honors REDIS_URL; tests/setup.js initializes the ORM and flushes test Redis keys before the run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
178 lines
6.5 KiB
Bash
178 lines
6.5 KiB
Bash
#!/usr/bin/env bash
|
|
# seed-test-user.sh — Create the test user in LDAP for the test suite.
|
|
#
|
|
# The test suite (tests/setup.js) logs in as uid=test / password=MyTestPassword!2.
|
|
# This script creates that user in the LDAP directory along with its personal
|
|
# posixGroup, and adds it to the app_sso_admin group so admin-gated tests pass.
|
|
#
|
|
# Environment variables (from docker-compose.test.yml):
|
|
# LDAP_HOST — LDAP server hostname (default: ldap)
|
|
# LDAP_PORT — LDAP server port (default: 389)
|
|
# BIND_DN — LDAP admin bind DN (default: cn=admin,dc=test,dc=local)
|
|
# BIND_PW — LDAP admin password (default: secret)
|
|
# BASE_DN — LDAP base DN (default: dc=test,dc=local)
|
|
|
|
set -euo pipefail
|
|
|
|
LDAP_HOST="${LDAP_HOST:-ldap}"
|
|
LDAP_PORT="${LDAP_PORT:-389}"
|
|
BIND_DN="${BIND_DN:-cn=admin,dc=test,dc=local}"
|
|
BIND_PW="${BIND_PW:-secret}"
|
|
BASE_DN="${BASE_DN:-dc=test,dc=local}"
|
|
|
|
LDAP_URI="ldap://${LDAP_HOST}:${LDAP_PORT}"
|
|
USER_UID="test"
|
|
USER_PASSWORD="MyTestPassword!2"
|
|
|
|
info() { echo "[INFO] $*"; }
|
|
error() { echo "[ERROR] $*" >&2; }
|
|
|
|
# ── Wait for LDAP to be reachable ────────────────────────────────────────────
|
|
info "Waiting for LDAP at ${LDAP_URI}..."
|
|
for i in $(seq 1 30); do
|
|
if ldapsearch -x -H "$LDAP_URI" -b '' -s base '(objectClass=*)' >/dev/null 2>&1; then
|
|
info "LDAP is reachable"
|
|
break
|
|
fi
|
|
if [ "$i" -eq 30 ]; then
|
|
error "LDAP not reachable after 30 attempts"
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
# ── Check if the test user already exists ────────────────────────────────────
|
|
if ldapsearch -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" \
|
|
-b "cn=${USER_UID},ou=people,${BASE_DN}" -s base '(objectClass=*)' >/dev/null 2>&1; then
|
|
info "Test user '${USER_UID}' already exists — skipping seed"
|
|
exit 0
|
|
fi
|
|
|
|
# ── Generate the SSHA512 password hash ───────────────────────────────────────
|
|
# Inline the hash function to avoid requiring the full model chain (which
|
|
# tries to connect to Redis/LDAP during module loading and would hang).
|
|
info "Generating password hash..."
|
|
PASSWORD_HASH=$(node -e "
|
|
const crypto = require('crypto');
|
|
const salt = crypto.randomBytes(8);
|
|
const hash = crypto.createHash('sha512').update('${USER_PASSWORD}').update(salt).digest();
|
|
console.log('{SSHA512}' + Buffer.concat([hash, salt]).toString('base64'));
|
|
")
|
|
|
|
info "Password hash generated"
|
|
|
|
# ── Create a temporary LDIF file ─────────────────────────────────────────────
|
|
TMPFILE=$(mktemp /tmp/seed-test-user.XXXXXX)
|
|
trap 'rm -f "$TMPFILE"' EXIT
|
|
|
|
cat > "$TMPFILE" << LDIF
|
|
# Personal posixGroup for the test user
|
|
dn: cn=${USER_UID},ou=groups,${BASE_DN}
|
|
objectClass: posixGroup
|
|
objectClass: top
|
|
cn: ${USER_UID}
|
|
gidNumber: 1500
|
|
description: Personal group for test user
|
|
|
|
# Test user posixAccount
|
|
dn: cn=${USER_UID},ou=people,${BASE_DN}
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: top
|
|
objectClass: theta42Person
|
|
objectClass: ldapPublicKey
|
|
objectClass: sudoRole
|
|
cn: ${USER_UID}
|
|
sn: Test
|
|
uid: ${USER_UID}
|
|
uidNumber: 1500
|
|
gidNumber: 1500
|
|
homeDirectory: /home/${USER_UID}
|
|
loginShell: /bin/bash
|
|
mail: test@test.local
|
|
userPassword: ${PASSWORD_HASH}
|
|
description: Test user for automated test suite
|
|
sudoHost: ALL
|
|
sudoCommand: ALL
|
|
sudoUser: ${USER_UID}
|
|
LDIF
|
|
|
|
# ── Add the entries to LDAP ──────────────────────────────────────────────────
|
|
info "Creating test user '${USER_UID}' in LDAP..."
|
|
ldapadd -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" -f "$TMPFILE" 2>/dev/null || true
|
|
if ldapsearch -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" \
|
|
-b "cn=${USER_UID},ou=people,${BASE_DN}" -s base '(objectClass=*)' >/dev/null 2>&1; then
|
|
info "Test user '${USER_UID}' exists or was created"
|
|
else
|
|
error "Failed to create test user '${USER_UID}'"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Add the test user to required SSO groups ─────────────────────────────────
|
|
info "Adding test user to SSO admin groups..."
|
|
for group in app_sso_admin app_sso_invite app_sso_oauth_admin; do
|
|
ldapmodify -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" << EOF 2>/dev/null || true
|
|
dn: cn=${group},ou=groups,${BASE_DN}
|
|
changetype: modify
|
|
add: member
|
|
member: cn=${USER_UID},ou=people,${BASE_DN}
|
|
EOF
|
|
done
|
|
info "Test user added to SSO admin groups"
|
|
|
|
# ── Create additional users needed by tests ─────────────────────────────────
|
|
# wmantly is referenced by OTP (otp.test.js) and impersonation (impersonate.test.js)
|
|
# tests as an existing non-admin user.
|
|
WMANTLY_UID="wmantly"
|
|
if ! ldapsearch -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" \
|
|
-b "cn=${WMANTLY_UID},ou=people,${BASE_DN}" -s base '(objectClass=*)' >/dev/null 2>&1; then
|
|
|
|
info "Creating additional test user '${WMANTLY_UID}'..."
|
|
|
|
# Generate password hash for wmantly
|
|
WMANTLY_HASH=$(node -e "
|
|
const crypto = require('crypto');
|
|
const salt = crypto.randomBytes(8);
|
|
const hash = crypto.createHash('sha512').update('testpass').update(salt).digest();
|
|
console.log('{SSHA512}' + Buffer.concat([hash, salt]).toString('base64'));
|
|
")
|
|
|
|
cat > "$TMPFILE" << LDIF
|
|
dn: cn=${WMANTLY_UID},ou=groups,${BASE_DN}
|
|
objectClass: posixGroup
|
|
objectClass: top
|
|
cn: ${WMANTLY_UID}
|
|
gidNumber: 1501
|
|
|
|
dn: cn=${WMANTLY_UID},ou=people,${BASE_DN}
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: top
|
|
objectClass: theta42Person
|
|
objectClass: ldapPublicKey
|
|
objectClass: sudoRole
|
|
cn: ${WMANTLY_UID}
|
|
sn: Mantly
|
|
uid: ${WMANTLY_UID}
|
|
uidNumber: 1501
|
|
gidNumber: 1501
|
|
homeDirectory: /home/${WMANTLY_UID}
|
|
loginShell: /bin/bash
|
|
mail: wmantly@test.local
|
|
userPassword: ${WMANTLY_HASH}
|
|
sudoHost: ALL
|
|
sudoCommand: ALL
|
|
sudoUser: ${WMANTLY_UID}
|
|
LDIF
|
|
ldapadd -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" -f "$TMPFILE" 2>/dev/null || true
|
|
if ldapsearch -x -H "$LDAP_URI" -D "$BIND_DN" -w "$BIND_PW" \
|
|
-b "cn=${WMANTLY_UID},ou=people,${BASE_DN}" -s base '(objectClass=*)' >/dev/null 2>&1; then
|
|
info "Additional test user '${WMANTLY_UID}' exists or was created"
|
|
else
|
|
error "Failed to create additional test user '${WMANTLY_UID}'"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
info "Seed complete — all test users are ready"
|