first commit
This commit is contained in:
28
jspwiki/Dockerfile
Normal file
28
jspwiki/Dockerfile
Normal 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"]
|
||||
63
jspwiki/RemoteUserFilter.java
Normal file
63
jspwiki/RemoteUserFilter.java
Normal 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
|
||||
}
|
||||
}
|
||||
31
jspwiki/configure-web-xml.sh
Normal file
31
jspwiki/configure-web-xml.sh
Normal 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
23
jspwiki/entrypoint.sh
Normal 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
159
jspwiki/ldap-sync.sh
Normal 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
|
||||
Reference in New Issue
Block a user