#!/bin/sh # # OpenLDAP Container Integration Tests # Runs a series of tests to verify the container works correctly # set -e # Configuration CONTAINER_NAME="${CONTAINER_NAME:-openldap-test}" IMAGE_NAME="${IMAGE_NAME:-enterprise-openldap:test}" LDAP_DOMAIN="${LDAP_DOMAIN:-test.local}" LDAP_ORGANISATION="${LDAP_ORGANISATION:-Test Organisation}" LDAP_ADMIN_PASSWORD="${LDAP_ADMIN_PASSWORD:-testpassword123}" LDAP_BASE_DN="dc=test,dc=local" MAX_WAIT="${MAX_WAIT:-60}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Counters TESTS_PASSED=0 TESTS_FAILED=0 # Helper functions log_info() { echo "${YELLOW}[INFO]${NC} $1" } log_pass() { echo "${GREEN}[PASS]${NC} $1" TESTS_PASSED=$((TESTS_PASSED + 1)) } log_fail() { echo "${RED}[FAIL]${NC} $1" TESTS_FAILED=$((TESTS_FAILED + 1)) } cleanup() { log_info "Cleaning up test container..." docker rm -f "$CONTAINER_NAME" 2>/dev/null || true } # Ensure cleanup on exit trap cleanup EXIT # Start the container start_container() { log_info "Starting test container with image: $IMAGE_NAME" docker run -d \ --name "$CONTAINER_NAME" \ -e LDAP_DOMAIN="$LDAP_DOMAIN" \ -e LDAP_ORGANISATION="$LDAP_ORGANISATION" \ -e LDAP_ADMIN_PASSWORD="$LDAP_ADMIN_PASSWORD" \ -e LDAP_TLS_ENABLED=false \ -e LDAP_CREATE_SERVICE_ACCOUNTS=true \ -e LDAP_LOG_LEVEL=256 \ "$IMAGE_NAME" if [ $? -eq 0 ]; then log_pass "Container started" else log_fail "Container failed to start" return 1 fi } # Wait for LDAP to be ready wait_for_ldap() { log_info "Waiting for LDAP to be ready (max ${MAX_WAIT}s)..." local count=0 while [ $count -lt $MAX_WAIT ]; do if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost -b "" -s base "objectClass=*" >/dev/null 2>&1; then log_pass "LDAP is responding" return 0 fi count=$((count + 1)) sleep 1 done log_fail "LDAP did not become ready within ${MAX_WAIT}s" log_info "Container logs:" docker logs "$CONTAINER_NAME" 2>&1 | tail -50 return 1 } # Test: Verify base DN exists test_base_dn() { log_info "Testing base DN exists..." if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "$LDAP_BASE_DN" -s base "objectClass=*" >/dev/null 2>&1; then log_pass "Base DN exists and admin can bind" else log_fail "Base DN test failed" return 1 fi } # Test: Verify organizational units test_organizational_units() { log_info "Testing organizational units..." local ous="People Groups Services Policies" local failed=0 for ou in $ous; do if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "ou=$ou,$LDAP_BASE_DN" -s base "objectClass=organizationalUnit" 2>/dev/null | grep -q "dn: ou=$ou"; then log_pass "OU=$ou exists" else log_fail "OU=$ou not found" failed=1 fi done return $failed } # Test: Verify schemas are loaded test_schemas() { log_info "Testing schemas are loaded..." local schemas="core cosine inetorgperson" local failed=0 # Get loaded schemas using SASL EXTERNAL via ldapi (requires root in container) local loaded_schemas=$(docker exec "$CONTAINER_NAME" ldapsearch -Y EXTERNAL -H ldapi://%2Frun%2Fopenldap%2Fldapi \ -b "cn=schema,cn=config" -s one "objectClass=*" cn 2>/dev/null | grep "^cn:" | tr -d ' ') for schema in $schemas; do if echo "$loaded_schemas" | grep -qi "$schema"; then log_pass "Schema '$schema' is loaded" else log_fail "Schema '$schema' not found" failed=1 fi done return $failed } # Test: Verify overlays are configured test_overlays() { log_info "Testing overlays are configured..." local overlays="memberof refint unique ppolicy" local failed=0 for overlay in $overlays; do if docker exec "$CONTAINER_NAME" ldapsearch -Y EXTERNAL -H ldapi://%2Frun%2Fopenldap%2Fldapi \ -b "cn=config" "olcOverlay={*}$overlay" 2>/dev/null | grep -qi "olcOverlay.*$overlay"; then log_pass "Overlay '$overlay' is configured" else log_fail "Overlay '$overlay' not found" failed=1 fi done return $failed } # Test: Verify service accounts exist test_service_accounts() { log_info "Testing service accounts..." local services="keycloak nextcloud gitea postfix dovecot sssd" local failed=0 for service in $services; do if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "cn=$service,ou=Services,$LDAP_BASE_DN" -s base "objectClass=*" 2>/dev/null | grep -q "dn: cn=$service"; then log_pass "Service account '$service' exists" else log_fail "Service account '$service' not found" failed=1 fi done return $failed } # Test: Add a user test_add_user() { log_info "Testing add user..." local user_ldif=$(cat </dev/null 2>&1; then log_pass "User 'testuser' created" else log_fail "Failed to create user 'testuser'" return 1 fi } # Test: Add a group with member test_add_group() { log_info "Testing add group with member..." local group_ldif=$(cat </dev/null 2>&1; then log_pass "Group 'testgroup' created with member" else log_fail "Failed to create group 'testgroup'" return 1 fi } # Test: Verify memberOf overlay works test_memberof_overlay() { log_info "Testing memberOf overlay..." # Check if user has memberOf attribute if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "uid=testuser,ou=People,$LDAP_BASE_DN" memberOf 2>/dev/null | grep -q "memberOf: cn=testgroup"; then log_pass "memberOf attribute correctly set on user" else log_fail "memberOf attribute not found on user" return 1 fi } # Test: User authentication test_user_authentication() { log_info "Testing user authentication..." if docker exec "$CONTAINER_NAME" ldapwhoami -x -H ldap://localhost \ -D "uid=testuser,ou=People,$LDAP_BASE_DN" -w "testuser123" 2>/dev/null | grep -q "testuser"; then log_pass "User authentication successful" else log_fail "User authentication failed" return 1 fi } # Test: Service account can search test_service_account_search() { log_info "Testing service account can search users..." # Get keycloak password from the container local keycloak_pass=$(docker exec "$CONTAINER_NAME" cat /var/lib/openldap/service-passwords.txt 2>/dev/null | grep keycloak | cut -d: -f2 | tr -d ' ') if [ -z "$keycloak_pass" ]; then log_fail "Could not retrieve keycloak service account password" return 1 fi if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=keycloak,ou=Services,$LDAP_BASE_DN" -w "$keycloak_pass" \ -b "ou=People,$LDAP_BASE_DN" "(uid=testuser)" uid 2>/dev/null | grep -q "uid: testuser"; then log_pass "Service account can search users" else log_fail "Service account search failed" return 1 fi } # Test: Unique overlay (duplicate uid should fail) test_unique_overlay() { log_info "Testing unique overlay (duplicate uid should be rejected)..." local dup_ldif=$(cat <&1 | grep -qi "constraint violation\|already exists\|unique"; then log_pass "Unique overlay rejected duplicate uid" else # Check if it was rejected by checking entry doesn't exist if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "uid=testuser2,ou=People,$LDAP_BASE_DN" 2>/dev/null | grep -q "numEntries: 0\|No such object"; then log_pass "Unique overlay rejected duplicate uid" else log_fail "Unique overlay did not reject duplicate uid" return 1 fi fi } # Test: Refint overlay (delete user should remove from group) test_refint_overlay() { log_info "Testing refint overlay (user deletion updates group)..." # Delete the test user if docker exec "$CONTAINER_NAME" ldapdelete -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ "uid=testuser,ou=People,$LDAP_BASE_DN" >/dev/null 2>&1; then # Check if user was removed from group if docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \ -D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \ -b "cn=testgroup,ou=Groups,$LDAP_BASE_DN" member 2>/dev/null | grep -q "member: uid=testuser"; then log_fail "Refint overlay did not remove user from group" return 1 else log_pass "Refint overlay removed user from group" fi else log_fail "Failed to delete test user" return 1 fi } # Main test execution main() { echo "==============================================" echo " OpenLDAP Container Integration Tests" echo "==============================================" echo "" # Setup cleanup start_container || exit 1 wait_for_ldap || exit 1 echo "" echo "--- Basic Structure Tests ---" test_base_dn test_organizational_units echo "" echo "--- Schema Tests ---" test_schemas echo "" echo "--- Overlay Configuration Tests ---" test_overlays echo "" echo "--- Service Account Tests ---" test_service_accounts echo "" echo "--- Functional Tests ---" test_add_user test_add_group test_memberof_overlay test_user_authentication test_service_account_search test_unique_overlay test_refint_overlay echo "" echo "==============================================" echo " Test Results" echo "==============================================" echo " ${GREEN}Passed: $TESTS_PASSED${NC}" echo " ${RED}Failed: $TESTS_FAILED${NC}" echo "==============================================" if [ $TESTS_FAILED -gt 0 ]; then echo "" log_info "Container logs (last 30 lines):" docker logs "$CONTAINER_NAME" 2>&1 | tail -30 exit 1 fi exit 0 } main "$@"