#!/bin/bash
# Sync LDAP users to JSPWiki XML databases
# Queries LLDAP via ldapsearch and generates JSPWiki XML files
set -euo pipefail
JSPWIKI_USERS="/var/jspwiki/etc/userdatabase.xml"
JSPWIKI_GROUPS="/var/jspwiki/etc/groupdatabase.xml"
# LDAP connection parameters (from environment or defaults)
LDAP_HOST="${LDAP_HOST:-lldap}"
LDAP_PORT="${LDAP_PORT:-3890}"
LDAP_BASE_DN="${LDAP_BASE_DN:-dc=example,dc=com}"
LDAP_BIND_DN="uid=admin,ou=people,${LDAP_BASE_DN}"
LDAP_BIND_PASSWORD="${LLDAP_ADMIN_PASSWORD:-changeme}"
echo "Syncing LDAP users to JSPWiki..." >&2
echo "LDAP Host: ${LDAP_HOST}:${LDAP_PORT}" >&2
echo "Base DN: ${LDAP_BASE_DN}" >&2
# Create JSPWiki etc directory if it doesn't exist
mkdir -p "$(dirname "$JSPWIKI_USERS")"
# Check if ldapsearch is available
if ! command -v ldapsearch &> /dev/null; then
echo "ERROR: ldapsearch not found. Install ldap-utils package." >&2
exit 1
fi
# Test LDAP connection
echo "Testing LDAP connection..." >&2
if ! ldapsearch -x -H "ldap://${LDAP_HOST}:${LDAP_PORT}" -D "${LDAP_BIND_DN}" -w "${LDAP_BIND_PASSWORD}" -b "${LDAP_BASE_DN}" -s base &>/dev/null; then
echo "ERROR: Cannot connect to LDAP server" >&2
exit 1
fi
echo "✓ LDAP connection successful" >&2
# Query all users from LDAP
echo "Querying LDAP users..." >&2
USERS_LDIF=$(ldapsearch -x -LLL -H "ldap://${LDAP_HOST}:${LDAP_PORT}" \
-D "${LDAP_BIND_DN}" -w "${LDAP_BIND_PASSWORD}" \
-b "ou=people,${LDAP_BASE_DN}" \
"(objectClass=person)" uid displayName mail)
# Start building userdatabase.xml
cat > "$JSPWIKI_USERS" << 'EOF_HEADER'
EOF_HEADER
# Parse LDIF and create JSPWiki user entries
echo "$USERS_LDIF" | awk '
BEGIN {
uid=""; displayName=""; mail="";
}
/^dn:/ {
# Save previous user if exists
if (uid) {
print " ";
}
uid=""; displayName=""; mail="";
}
/^uid: / { uid = $2; }
/^displayName: / {
displayName = substr($0, 14);
gsub(/^[ \t]+|[ \t]+$/, "", displayName);
}
/^mail: / { mail = $2; }
END {
# Save last user
if (uid) {
print " ";
}
}
' >> "$JSPWIKI_USERS"
# Close userdatabase.xml
cat >> "$JSPWIKI_USERS" << 'EOF_FOOTER'
EOF_FOOTER
USER_COUNT=$(grep -c 'loginName=' "$JSPWIKI_USERS" || echo 0)
echo "✓ Synced $USER_COUNT users" >&2
# Query groups from LDAP
echo "Querying LDAP groups..." >&2
GROUPS_LDIF=$(ldapsearch -x -LLL -H "ldap://${LDAP_HOST}:${LDAP_PORT}" \
-D "${LDAP_BIND_DN}" -w "${LDAP_BIND_PASSWORD}" \
-b "ou=groups,${LDAP_BASE_DN}" \
"(objectClass=groupOfUniqueNames)" cn uniqueMember)
# Build groupdatabase.xml
cat > "$JSPWIKI_GROUPS" << 'EOF_HEADER'
EOF_HEADER
# Parse groups and create JSPWiki group entries
# Map LLDAP's lldap_admin group to JSPWiki's Admin group
echo "$GROUPS_LDIF" | awk -v base_dn="$LDAP_BASE_DN" '
BEGIN {
cn=""; members=""; in_admin_group=0;
}
/^dn:/ {
# Save previous group if it was lldap_admin
if (cn == "lldap_admin" && members) {
print " ";
print members;
print " ";
}
cn=""; members=""; in_admin_group=0;
}
/^cn: / {
cn = $2;
if (cn == "lldap_admin") in_admin_group=1;
}
/^uniqueMember: / && in_admin_group {
# Extract uid from DN like "uid=admin,ou=people,dc=example,dc=com"
dn = substr($0, 15);
# Extract uid value using portable AWK
if (index(dn, "uid=") > 0) {
uid_part = substr(dn, index(dn, "uid=") + 4);
comma_pos = index(uid_part, ",");
if (comma_pos > 0) {
uid_value = substr(uid_part, 1, comma_pos - 1);
} else {
uid_value = uid_part;
}
members = members " \n";
}
}
END {
# Save last group if it was lldap_admin
if (cn == "lldap_admin" && members) {
print " ";
print members;
print " ";
}
}
' >> "$JSPWIKI_GROUPS"
# Close groupdatabase.xml
cat >> "$JSPWIKI_GROUPS" << 'EOF_FOOTER'
EOF_FOOTER
ADMIN_COUNT=$(grep -c 'member principal=' "$JSPWIKI_GROUPS" || echo 0)
echo "✓ Synced Admin group with $ADMIN_COUNT members" >&2
echo "✓ LDAP sync complete" >&2