Skip to content
6 changes: 3 additions & 3 deletions dev/command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

if [ "$APP_CONTEXT" = "dev" ]; then
echo "Starting Traefik in development mode..."
exec traefik
exec traefik "$@"
fi

if [ "$APP_CONTEXT" = "prod" ]; then
echo "Starting Traefik in production mode..."
exec traefik
exec traefik "$@"
fi

if [ "$APP_CONTEXT" = "tests" ]; then
echo "Starting Traefik in test mode..."
exec traefik
exec traefik "$@"
fi
129 changes: 129 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ EXTERNAL_ADDRESS="${EXTERNAL_ADDRESS:-openslides.example.com}"
ACME_ENDPOINT="${ACME_ENDPOINT:-}"
ACME_EMAIL="${ACME_EMAIL:-}"

# OIDC configuration
OIDC_ENABLED="${OIDC_ENABLED:-}"
OIDC_SESSION_SECRET="${OIDC_SESSION_SECRET:-}"
OIDC_PROVIDER_URL="${OIDC_PROVIDER_URL:-}"
OIDC_CLIENT_ID="${OIDC_CLIENT_ID:-}"
OIDC_CLIENT_SECRET="${OIDC_CLIENT_SECRET:-}"

# Set default values for service endpoints
ACTION_HOST="${ACTION_HOST:-backend}"
ACTION_PORT="${ACTION_PORT:-9002}"
Expand Down Expand Up @@ -50,6 +57,19 @@ CLIENT_PORT="${CLIENT_PORT:-9001}"
# Generate base config from template
envsubst < /templates/traefik.yml > "$TRAEFIK_CONFIG"

# Add experimental plugins section if OIDC is enabled
if [ -n "$OIDC_ENABLED" ]; then
echo "Configuring OIDC plugin in static configuration"
cat >> "$TRAEFIK_CONFIG" << 'EOF'

experimental:
plugins:
traefik-oidc-auth:
moduleName: github.com/sevensolutions/traefik-oidc-auth
version: v0.17.0
EOF
fi

# Add dashboard if enabled
if [ -n "$ENABLE_DASHBOARD" ]; then
echo "Enabling dashboard. 'debug: true' for now. NOT FOR PRODUCTION"
Expand Down Expand Up @@ -144,6 +164,11 @@ for service_file in $SERVICES_DIR/*.service; do
fi

if eval [[ -n "\$${host_var}" ]]; then
# Skip auth service in OIDC mode - authentication handled by Keycloak
if [ -n "$OIDC_ENABLED" ] && [ "$service" = "auth" ]; then
echo "Skipping auth service in OIDC mode (auth handled by Keycloak)"
continue
fi
eval "echo \"Adding config: $service (host: \$${host_var})\"" >&2
SERVICES="$SERVICES $service"
else
Expand All @@ -161,8 +186,61 @@ EOF
# Concatenate all enabled .router files
for service in $SERVICES; do
envsubst < "$SERVICES_DIR/${service}.router" >> "$DYNAMIC_CONFIG"
# Add OIDC middleware to routes that need authentication
# In OIDC mode, Traefik injects the Authorization header with access token
if [ -n "$OIDC_ENABLED" ]; then
case "$service" in
client|autoupdate|action|presenter|icc|vote|search|media|projector)
echo " middlewares:" >> "$DYNAMIC_CONFIG"
echo " - oidc-auth" >> "$DYNAMIC_CONFIG"
;;
esac
fi
done

# In OIDC mode, add provisioning and who-am-i routes to backend
if [ -n "$OIDC_ENABLED" ]; then
echo "Adding OIDC auth routers (routes to backend)"
cat >> "$DYNAMIC_CONFIG" << EOF
keycloak:
rule: "PathPrefix(\`/auth\`)"
service: keycloak
entryPoints:
- main
priority: 10
auth-oidc-provision:
rule: "PathPrefix(\`/system/auth/oidc-provision\`)"
service: action
entryPoints:
- main
middlewares:
- oidc-auth
priority: 15
auth-who-am-i:
rule: "PathPrefix(\`/system/auth/who-am-i\`)"
service: action
entryPoints:
- main
middlewares:
- oidc-auth
priority: 15
autoupdate-theme:
rule: "Path(\`/system/autoupdate/theme\`)"
service: autoupdate
entryPoints:
- main
priority: 50
oauth2:
rule: "PathPrefix(\`/oauth2\`)"
service: client
entryPoints:
- main
middlewares:
- oidc-auth
priority: 10
EOF
fi

# Add services section
cat >> "$DYNAMIC_CONFIG" << 'EOF'

Expand All @@ -174,6 +252,57 @@ for service in $SERVICES; do
envsubst < "$SERVICES_DIR/${service}.service" >> "$DYNAMIC_CONFIG"
done

# Add Keycloak service if OIDC is enabled
if [ -n "$OIDC_ENABLED" ]; then
cat >> "$DYNAMIC_CONFIG" << EOF
keycloak:
loadBalancer:
servers:
- url: "http://keycloak:8080"
passHostHeader: true
EOF
fi

# Add OIDC middleware configuration if enabled
if [ -n "$OIDC_ENABLED" ]; then
echo "Enabling OIDC authentication middleware"
cat >> "$DYNAMIC_CONFIG" << EOF

middlewares:
oidc-auth:
plugin:
traefik-oidc-auth:
LogLevel: debug
Secret: "${OIDC_SESSION_SECRET}"
Provider:
Url: "${OIDC_PROVIDER_URL}"
ClientId: "${OIDC_CLIENT_ID}"
ClientSecret: "${OIDC_CLIENT_SECRET}"
UsePkce: true
Scopes:
- openid
- profile
- email
- roles
LoginUri: /oauth2/login
CallbackUri: /oauth2/callback
LogoutUri: /oauth2/logout
PostLoginRedirectUri: /system/auth/oidc-provision
UnauthorizedBehavior: Auto
PostLogoutRedirectUri: /
SessionCookie:
SameSite: lax
HttpOnly: false
Headers:
- Name: Authentication
Value: 'bearer {{ "{{ .accessToken }}" }}'
- Name: X-Forwarded-User
Value: '{{ "{{ .claims.preferred_username }}" }}'
- Name: X-Auth-Request-Email
Value: '{{ "{{ .claims.email }}" }}'
EOF
fi


# Finally start CMD
exec "$@"
16 changes: 15 additions & 1 deletion templates/traefik.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Traefik configuration for OpenSlides

# Experimental plugins configuration
# The traefik-oidc-auth plugin is loaded via command-line arguments
# when using docker-compose.oidc.yml overlay:
# --experimental.plugins.traefik-oidc-auth.modulename=github.com/sevensolutions/traefik-oidc-auth
# --experimental.plugins.traefik-oidc-auth.version=v0.19.3

# Add provider to read routing config from file
providers:
file:
Expand All @@ -13,7 +19,15 @@ ping: {}
log:
level: ${TRAEFIK_LOG_LEVEL}

accessLog: {}
accessLog:
fields:
headers:
defaultMode: keep
names:
Authorization: keep
X-Forwarded-User: keep
X-Auth-Request-Email: keep
authentication: keep

# entryPoints are generated dynamically in entrypoint.sh script as their
# definitions depend on TLS configuration
Expand Down