Some checks failed
CI Pipeline / lint (push) Successful in 19s
CI Pipeline / build (push) Successful in 41s
CI Pipeline / security-scan (push) Successful in 1m21s
CI Pipeline / test (push) Failing after 1m1s
CI Pipeline / push (push) Has been skipped
CI Pipeline / update-cd (push) Has been skipped
413 lines
12 KiB
Bash
Executable File
413 lines
12 KiB
Bash
Executable File
#!/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 <<EOF
|
|
dn: uid=testuser,ou=People,$LDAP_BASE_DN
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: shadowAccount
|
|
uid: testuser
|
|
cn: Test User
|
|
sn: User
|
|
givenName: Test
|
|
mail: testuser@$LDAP_DOMAIN
|
|
uidNumber: 10001
|
|
gidNumber: 10000
|
|
homeDirectory: /home/testuser
|
|
loginShell: /bin/bash
|
|
userPassword: testuser123
|
|
EOF
|
|
)
|
|
|
|
if echo "$user_ldif" | docker exec -i "$CONTAINER_NAME" ldapadd -x -H ldap://localhost \
|
|
-D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" >/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 <<EOF
|
|
dn: cn=testgroup,ou=Groups,$LDAP_BASE_DN
|
|
objectClass: groupOfMembers
|
|
objectClass: posixGroup
|
|
cn: testgroup
|
|
gidNumber: 10001
|
|
description: Test Group
|
|
member: uid=testuser,ou=People,$LDAP_BASE_DN
|
|
EOF
|
|
)
|
|
|
|
if echo "$group_ldif" | docker exec -i "$CONTAINER_NAME" ldapadd -x -H ldap://localhost \
|
|
-D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" >/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 <<EOF
|
|
dn: uid=testuser2,ou=People,$LDAP_BASE_DN
|
|
objectClass: inetOrgPerson
|
|
objectClass: posixAccount
|
|
objectClass: shadowAccount
|
|
uid: testuser
|
|
cn: Duplicate User
|
|
sn: Duplicate
|
|
uidNumber: 10002
|
|
gidNumber: 10000
|
|
homeDirectory: /home/testuser2
|
|
EOF
|
|
)
|
|
|
|
if echo "$dup_ldif" | docker exec -i "$CONTAINER_NAME" ldapadd -x -H ldap://localhost \
|
|
-D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" 2>&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 "$@"
|