first commit

This commit is contained in:
Stefano Manfredi
2025-12-01 14:58:40 +00:00
commit 2866bff217
28 changed files with 5515 additions and 0 deletions

28
jspwiki/Dockerfile Normal file
View File

@@ -0,0 +1,28 @@
FROM eclipse-temurin:17-jdk AS builder
# Compile Remote-User filter
WORKDIR /build
COPY RemoteUserFilter.java .
RUN javac -cp /usr/local/tomcat/lib/servlet-api.jar:. RemoteUserFilter.java 2>/dev/null || \
wget -q https://repo1.maven.org/maven2/jakarta/servlet/jakarta.servlet-api/6.0.0/jakarta.servlet-api-6.0.0.jar && \
javac -cp jakarta.servlet-api-6.0.0.jar RemoteUserFilter.java && \
jar cf RemoteUserFilter.jar RemoteUserFilter*.class
FROM apache/jspwiki:latest
# Install ldap-utils for LDAP sync
RUN apt-get update && \
apt-get install -y ldap-utils && \
rm -rf /var/lib/apt/lists/*
# Copy compiled filter
COPY --from=builder /build/RemoteUserFilter.jar /usr/local/tomcat/webapps/ROOT/WEB-INF/lib/
# Copy LDAP sync script and custom entrypoint
COPY ldap-sync.sh /usr/local/bin/ldap-sync
COPY configure-web-xml.sh /usr/local/bin/configure-web-xml
COPY entrypoint.sh /custom-entrypoint.sh
RUN chmod +x /usr/local/bin/ldap-sync /usr/local/bin/configure-web-xml /custom-entrypoint.sh
# Use custom entrypoint that runs LDAP sync before starting Tomcat
ENTRYPOINT ["/custom-entrypoint.sh"]

View File

@@ -0,0 +1,63 @@
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.security.Principal;
import java.util.*;
/**
* Servlet Filter that wraps requests to provide Remote-User authentication from Authelia
*/
public class RemoteUserFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Nothing to initialize
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String remoteUser = httpRequest.getHeader("Remote-User");
if (remoteUser != null && !remoteUser.isEmpty()) {
// Wrap the request to override getRemoteUser() and getUserPrincipal()
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
@Override
public String getRemoteUser() {
return remoteUser;
}
@Override
public Principal getUserPrincipal() {
return new Principal() {
@Override
public String getName() {
return remoteUser;
}
};
}
@Override
public boolean isUserInRole(String role) {
String remoteGroups = httpRequest.getHeader("Remote-Groups");
if (remoteGroups != null) {
return Arrays.asList(remoteGroups.split(","))
.contains(role);
}
// All authenticated users have "Authenticated" role
return "Authenticated".equals(role);
}
};
chain.doFilter(wrapper, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// Nothing to clean up
}
}

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# Configure web.xml to use RemoteUserFilter for SSO
set -e
WEB_XML="/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml"
MARKER="<!-- REMOTE_USER_FILTER_CONFIGURED -->"
echo "Configuring JSPWiki for Remote-User SSO..." >&2
# Check if already configured
if grep -q "$MARKER" "$WEB_XML" 2>/dev/null; then
echo "✓ RemoteUserFilter already configured" >&2
exit 0
fi
# Add RemoteUserFilter configuration after <web-app> opening tag completes
# Find the line with version="5.0"> which closes the web-app opening tag
sed -i '/version="5.0">/a\
\
<!-- REMOTE_USER_FILTER_CONFIGURED -->\
<!-- Remote-User Filter for Authelia SSO -->\
<filter>\
<filter-name>RemoteUserFilter</filter-name>\
<filter-class>RemoteUserFilter</filter-class>\
</filter>\
<filter-mapping>\
<filter-name>RemoteUserFilter</filter-name>\
<url-pattern>/*</url-pattern>\
</filter-mapping>' "$WEB_XML"
echo "✓ RemoteUserFilter configured in web.xml" >&2

23
jspwiki/entrypoint.sh Normal file
View File

@@ -0,0 +1,23 @@
#!/bin/bash
set -e
# Configure web.xml for container authentication
echo "Configuring JSPWiki for container authentication..." >&2
/usr/local/bin/configure-web-xml
# Read lldap admin password from secret file
if [ -f "/secrets-lldap/LDAP_USER_PASS" ]; then
export LLDAP_ADMIN_PASSWORD=$(cat /secrets-lldap/LDAP_USER_PASS)
fi
# Sync LDAP users to JSPWiki
echo "Syncing LDAP users to JSPWiki..." >&2
if /usr/local/bin/ldap-sync; then
echo "✓ LDAP sync successful" >&2
else
echo "⚠ LDAP sync failed - JSPWiki may not have users initialized" >&2
echo " Check LDAP connection and credentials in secret file" >&2
fi
# Start Tomcat using the official image's entrypoint
exec /usr/local/tomcat/bin/catalina.sh run

159
jspwiki/ldap-sync.sh Normal file
View File

@@ -0,0 +1,159 @@
#!/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'
<?xml version="1.0" encoding="UTF-8"?>
<users>
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 " <user";
print " loginName=\"" uid "\"";
print " fullName=\"" displayName "\"";
print " wikiName=\"" uid "\"";
print " password=\"{SSHA}placeholder\"";
print " email=\"" mail "\" />";
}
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 " <user";
print " loginName=\"" uid "\"";
print " fullName=\"" displayName "\"";
print " wikiName=\"" uid "\"";
print " password=\"{SSHA}placeholder\"";
print " email=\"" mail "\" />";
}
}
' >> "$JSPWIKI_USERS"
# Close userdatabase.xml
cat >> "$JSPWIKI_USERS" << 'EOF_FOOTER'
</users>
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'
<?xml version="1.0" encoding="UTF-8"?>
<groups>
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 " <group name=\"Admin\">";
print members;
print " </group>";
}
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 " <member principal=\"" uid_value "\" />\n";
}
}
END {
# Save last group if it was lldap_admin
if (cn == "lldap_admin" && members) {
print " <group name=\"Admin\">";
print members;
print " </group>";
}
}
' >> "$JSPWIKI_GROUPS"
# Close groupdatabase.xml
cat >> "$JSPWIKI_GROUPS" << 'EOF_FOOTER'
</groups>
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