Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
134 changes: 133 additions & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ 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_INTERNAL_PROVIDER_URL="${OIDC_INTERNAL_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 +58,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.18.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 @@ -138,12 +159,17 @@ for service_file in $SERVICES_DIR/*.service; do
service_upper=$(echo "$service" | tr '[:lower:]' '[:upper:]')
host_var="${service_upper}_HOST"

if [[ ! -f "$SERVICES_DIR/$service.service" ]] || [[ ! -f "$SERVICES_DIR/$service.router" ]]; then
if [ ! -f "$SERVICES_DIR/$service.service" ] || [ ! -f "$SERVICES_DIR/$service.router" ]; then
echo "Skipping, config incomplete: $service"
continue
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 +187,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
presenter-theme:
rule: "Path(\`/system/presenter/theme\`)"
service: presenter
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 +253,59 @@ 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_INTERNAL_PROVIDER_URL}"
ClientId: "${OIDC_CLIENT_ID}"
ClientSecret: "${OIDC_CLIENT_SECRET}"
UsePkce: true
ValidateIssuer: true
ValidIssuer: "${OIDC_PROVIDER_URL}"
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: drop
X-Forwarded-User: keep
X-Auth-Request-Email: keep
authentication: drop

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