Add complete CI pipeline with testing stages
Some checks failed
CI Pipeline / test (push) Has been cancelled
CI Pipeline / security-scan (push) Has been cancelled
CI Pipeline / push (push) Has been cancelled
CI Pipeline / update-cd (push) Has been cancelled
CI Pipeline / lint (push) Has been cancelled
CI Pipeline / build (push) Has been cancelled
Some checks failed
CI Pipeline / test (push) Has been cancelled
CI Pipeline / security-scan (push) Has been cancelled
CI Pipeline / push (push) Has been cancelled
CI Pipeline / update-cd (push) Has been cancelled
CI Pipeline / lint (push) Has been cancelled
CI Pipeline / build (push) Has been cancelled
Pipeline stages: 1. lint - Dockerfile linting with hadolint 2. build - Build Docker image and save as artifact 3. test - Integration tests (schemas, overlays, LDAP operations) 4. security-scan - Trivy vulnerability scanning 5. push - Push to registry (only after tests pass) 6. update-cd - Placeholder for CD pipeline trigger Tests verify: - Container starts and LDAP responds - All OUs created (People, Groups, Services, Policies) - Schemas loaded (core, cosine, inetorgperson) - Overlays configured (memberof, refint, unique, ppolicy) - Service accounts exist - User/group operations work - memberOf overlay updates user attributes - refint overlay cleans up group membership on user delete - unique overlay rejects duplicate uids
This commit is contained in:
parent
3508ac4f7f
commit
f15108abb7
@ -1,4 +1,4 @@
|
||||
name: Build and Push Docker Image
|
||||
name: CI Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -15,8 +15,25 @@ env:
|
||||
IMAGE_NAME: enterprise-openldap
|
||||
|
||||
jobs:
|
||||
# Stage 1: Lint Dockerfile
|
||||
lint:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Lint Dockerfile with hadolint
|
||||
run: |
|
||||
docker run --rm -i hadolint/hadolint < Dockerfile || {
|
||||
echo "::warning::Dockerfile linting found issues (non-blocking)"
|
||||
}
|
||||
|
||||
# Stage 2: Build image
|
||||
build:
|
||||
runs-on: docker
|
||||
needs: lint
|
||||
outputs:
|
||||
image_tag: ${{ steps.version.outputs.VERSION }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@ -25,47 +42,165 @@ jobs:
|
||||
id: version
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
|
||||
# Extract version from tag (v1.0.0 -> 1.0.0)
|
||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "TAGS=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_OUTPUT
|
||||
elif [[ "$GITHUB_REF" == refs/heads/main ]]; then
|
||||
# Use short SHA for main branch
|
||||
SHORT_SHA=$(echo "$GITHUB_SHA" | cut -c1-7)
|
||||
echo "VERSION=$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||
echo "TAGS=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||
else
|
||||
# Pull request - just use SHA
|
||||
SHORT_SHA=$(echo "$GITHUB_SHA" | cut -c1-7)
|
||||
echo "VERSION=$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||
echo "TAGS=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||
VERSION="$(echo "$GITHUB_SHA" | cut -c1-7)"
|
||||
fi
|
||||
|
||||
- name: Log in to Docker Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
|
||||
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Building version: $VERSION"
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} .
|
||||
docker build -t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} .
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} ${{ env.IMAGE_NAME }}:test
|
||||
|
||||
- name: Tag additional versions
|
||||
- name: Save image for subsequent jobs
|
||||
run: |
|
||||
mkdir -p /tmp/images
|
||||
docker save ${{ env.IMAGE_NAME }}:test -o /tmp/images/image.tar
|
||||
|
||||
- name: Upload image artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
path: /tmp/images/image.tar
|
||||
retention-days: 1
|
||||
|
||||
# Stage 3: Integration tests
|
||||
test:
|
||||
runs-on: docker
|
||||
needs: build
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download image artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
path: /tmp/images
|
||||
|
||||
- name: Load Docker image
|
||||
run: |
|
||||
docker load -i /tmp/images/image.tar
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
chmod +x tests/test-container.sh
|
||||
./tests/test-container.sh
|
||||
env:
|
||||
IMAGE_NAME: ${{ env.IMAGE_NAME }}:test
|
||||
CONTAINER_NAME: openldap-ci-test
|
||||
|
||||
# Stage 4: Security scan
|
||||
security-scan:
|
||||
runs-on: docker
|
||||
needs: build
|
||||
steps:
|
||||
- name: Download image artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
path: /tmp/images
|
||||
|
||||
- name: Load Docker image
|
||||
run: |
|
||||
docker load -i /tmp/images/image.tar
|
||||
|
||||
- name: Scan image with Trivy
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
aquasec/trivy:latest image \
|
||||
--severity HIGH,CRITICAL \
|
||||
--exit-code 0 \
|
||||
--no-progress \
|
||||
${{ env.IMAGE_NAME }}:test
|
||||
|
||||
- name: Scan for critical vulnerabilities (blocking)
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
aquasec/trivy:latest image \
|
||||
--severity CRITICAL \
|
||||
--exit-code 1 \
|
||||
--no-progress \
|
||||
--ignore-unfixed \
|
||||
${{ env.IMAGE_NAME }}:test || {
|
||||
echo "::error::Critical vulnerabilities found!"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Stage 5: Push to registry
|
||||
push:
|
||||
runs-on: docker
|
||||
needs: [test, security-scan]
|
||||
if: github.event_name != 'pull_request'
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.VERSION }}
|
||||
full_image: ${{ steps.version.outputs.FULL_IMAGE }}
|
||||
steps:
|
||||
- name: Download image artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
path: /tmp/images
|
||||
|
||||
- name: Load Docker image
|
||||
run: |
|
||||
docker load -i /tmp/images/image.tar
|
||||
|
||||
- name: Determine version and tags
|
||||
id: version
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
|
||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
# For releases, tag with version, major.minor, and latest
|
||||
MAJOR=$(echo $VERSION | cut -d. -f1)
|
||||
MINOR=$(echo $VERSION | cut -d. -f2)
|
||||
TAGS="${VERSION},${MAJOR}.${MINOR},latest"
|
||||
else
|
||||
VERSION="$(echo "$GITHUB_SHA" | cut -c1-7)"
|
||||
TAGS="${VERSION},latest"
|
||||
fi
|
||||
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "TAGS=$TAGS" >> $GITHUB_OUTPUT
|
||||
echo "FULL_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Log in to Docker Registry
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
|
||||
|
||||
- name: Tag and push images
|
||||
run: |
|
||||
IFS=',' read -ra TAGS <<< "${{ steps.version.outputs.TAGS }}"
|
||||
for TAG in "${TAGS[@]}"; do
|
||||
docker tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} "$TAG"
|
||||
done
|
||||
|
||||
- name: Push Docker image
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
IFS=',' read -ra TAGS <<< "${{ steps.version.outputs.TAGS }}"
|
||||
for TAG in "${TAGS[@]}"; do
|
||||
docker push "$TAG"
|
||||
docker tag ${{ env.IMAGE_NAME }}:test ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG
|
||||
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG
|
||||
echo "Pushed: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG"
|
||||
done
|
||||
|
||||
- name: Logout from registry
|
||||
if: always() && github.event_name != 'pull_request'
|
||||
if: always()
|
||||
run: docker logout ${{ env.REGISTRY }} || true
|
||||
|
||||
# Stage 6: Update CD pipeline (trigger deployment)
|
||||
update-cd:
|
||||
runs-on: docker
|
||||
needs: push
|
||||
if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- name: Trigger CD pipeline
|
||||
run: |
|
||||
echo "=============================================="
|
||||
echo " Ready to update CD pipeline"
|
||||
echo "=============================================="
|
||||
echo "New version: ${{ needs.push.outputs.version }}"
|
||||
echo "Full image: ${{ needs.push.outputs.full_image }}"
|
||||
echo ""
|
||||
echo "TODO: Add step to update version in CD repository"
|
||||
echo "This could be:"
|
||||
echo " - Update docker-compose.yml in infra repo"
|
||||
echo " - Update Helm values"
|
||||
echo " - Trigger ArgoCD sync"
|
||||
echo "=============================================="
|
||||
|
||||
414
tests/test-container.sh
Executable file
414
tests/test-container.sh
Executable file
@ -0,0 +1,414 @@
|
||||
#!/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
|
||||
local loaded_schemas=$(docker exec "$CONTAINER_NAME" ldapsearch -x -H ldap://localhost \
|
||||
-D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \
|
||||
-b "cn=schema,cn=config" -s one "objectClass=*" cn 2>/dev/null | grep "^cn:" | sed 's/cn: {[0-9]*}//' | 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 -x -H ldap://localhost \
|
||||
-D "cn=admin,$LDAP_BASE_DN" -w "$LDAP_ADMIN_PASSWORD" \
|
||||
-b "cn=config" "olcOverlay=$overlay" 2>/dev/null | grep -q "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 "$@"
|
||||
Loading…
x
Reference in New Issue
Block a user