From 77c45c63f344025c299602235586e362ee850307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Sat, 23 Aug 2025 13:50:17 +0200 Subject: [PATCH] Add authelia OIDC test setup --- .gitignore | 4 + .../authelia-oidc/authelia/configuration.yml | 131 ++++++++++++++++++ .../authelia-oidc/authelia/users_database.yml | 18 +++ .../authelia-oidc/compose.yml | 72 ++++++++++ .../authelia-oidc/setup.sh | 42 ++++++ .../authelia-oidc/traefik/certificates.yml | 6 + 6 files changed, 273 insertions(+) create mode 100644 scripts/unsecure-test-setups/authelia-oidc/authelia/configuration.yml create mode 100644 scripts/unsecure-test-setups/authelia-oidc/authelia/users_database.yml create mode 100644 scripts/unsecure-test-setups/authelia-oidc/compose.yml create mode 100755 scripts/unsecure-test-setups/authelia-oidc/setup.sh create mode 100644 scripts/unsecure-test-setups/authelia-oidc/traefik/certificates.yml diff --git a/.gitignore b/.gitignore index 68fad2d..6467f6a 100644 --- a/.gitignore +++ b/.gitignore @@ -196,3 +196,7 @@ typings/ /chromium-profile # direnv /.direnv + +# Test setups +/scripts/unsecure-test-setups/authelia-oidc/authelia/db.sqlite3 +/scripts/unsecure-test-setups/authelia-oidc/traefik/certs diff --git a/scripts/unsecure-test-setups/authelia-oidc/authelia/configuration.yml b/scripts/unsecure-test-setups/authelia-oidc/authelia/configuration.yml new file mode 100644 index 0000000..60e56e0 --- /dev/null +++ b/scripts/unsecure-test-setups/authelia-oidc/authelia/configuration.yml @@ -0,0 +1,131 @@ +--- +############################################################### +# Authelia configuration # +############################################################### + +server: + address: 'tcp://:9091' + +log: + level: 'debug' + +totp: + issuer: 'authelia.com' + +identity_validation: + reset_password: + jwt_secret: 'a_very_important_secret' + +authentication_backend: + file: + path: '/config/users_database.yml' + +access_control: + default_policy: 'deny' + rules: + - domain: 'traefik.example.com' + policy: 'one_factor' + - domain: 'linkding.example.com' + policy: 'one_factor' + +session: + secret: 'insecure_session_secret' + + cookies: + - name: 'authelia_session' + domain: 'example.com' # Should match whatever your root protected domain is + authelia_url: 'https://authelia.example.com' + expiration: '1 hour' # 1 hour + inactivity: '5 minutes' # 5 minutes + default_redirection_url: 'https://linkding.example.com' + +regulation: + max_retries: 3 + find_time: '2 minutes' + ban_time: '5 minutes' + +storage: + encryption_key: 'you_must_generate_a_random_string_of_more_than_twenty_chars_and_configure_this' + local: + path: '/config/db.sqlite3' + +notifier: + filesystem: + filename: '/tmp/notification.txt' + +identity_providers: + oidc: + ## The other portions of the mandatory OpenID Connect 1.0 configuration go here. + ## See: https://www.authelia.com/c/oidc + hmac_secret: 'this_is_a_secret_abc123abc123abc' + jwks: + - key_id: 'example' + algorithm: 'RS256' + use: 'sig' + key: | + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCuS2pK2VzqW+Sn + hBATps7vo2AdZCtF3p+FOJ4WEwQoiJarS0pAJxKn4BT9PHP1gY8XCs45Qys586xQ + UZwS1/9B482tQwkDQkfqXOIfTzqhTydVsi6t8Ff7ywW8K2lURcK+PnSE91Yp8tSO + YWlXDajoI8wKkRSpcCApkmBZ3hJiJR9DlcfwKBJSNxt+DbuobQs4SOpjSY4fnDpn + S5DFc72hiFOxvdx48y8c08UU+zNyHIIjYQ1995HwXysn7UwWCJaC4lI4ecaxHa01 + 4irOx3HsuXEzs/U5UBs2lBXFfKn/JHAPVJvxlER5ciUCNiHGWWh+A7hrd9BemoMQ + kRCIlldJAgMBAAECggEACtSWGmhTFx+Gb/fbeWMjRv4RkAX8T+NHaZN09FVya9Pf + ++0p5B5hcQPSPhGqeXoXYoTJ/4IqXpejEJsfngakvosJqe9pURXmatxiczRcxe8J + mFBCCQ4vI27wUGroqMNMeH6gRi5p4OGtXlsUfQO06BboXAw7mtNENl0ZhmAPp6BB + ZWyQm90Kwx4T0JgNwdlau+9ZWQ/10/7mOs1bX+8vZDFCmzbzFfoPjgEo+Mw1sE/H + i5kQxWErkWfeiabVp/7JlazHSYygwk21t1VgSBP4tgfkdAht68BievwguxCIrFRG + MPCkgzktJgIfo5k0yuo//afKUKo+OViQ3ZB4YdGKkQKBgQDPgl59fqRZpGCwnKPu + ymVi2c/bxjm6aK2VLX2dUFrPprzmfvUY8j/jDDcx4zOJg7jxNs2PGDooLDOSwa82 + i+YPTnBHlS3PBUp7jLPdCcZ0I8gMT5OWxnmPwGqUS6BqVTAhDq3QsJxD88FS8eD2 + mbFuBh5WAhj9URX+vc/FwLO/+QKBgQDXBhOXNAB64goQOM7ymUxihLQtYemO9h5N + /cXsxpJF8KH/PtWpw9c6nc2d/GPs4OYoCaqsuQVSyQXDcXayNC6Dn8KwUrJP2yGL + CHOAGg6HJbq+c5AKE1ytzvblTCyOcHZCjtlqwqJwO68xTWfSdbkvYYnfwyx+g0O9 + SsoouvzF0QKBgHI2GBnMZVrtbUZnwJbCkVD5/zzAeq+Nw9RyqEu4mXLnG9tljzM+ + ykkGRS7RFWGfvWAOQM98jy3jPjONJQnJsENGcegERKVIDTm5NJn5MmBj/UxBVENN + VET5q++ZPF6qKoZXVPWi7y87b3Fereosp4qeFX5TQzvRsGB4Sm5WZNjJAoGAbezN + Vx9en3OvcVuZcKyuQC9XbVwA6vUnyPdTmBhr7xV1u+eDk6ZrAaxq0bmV3COdhhpr + BqIP9qKOL7xx0eibXu7tuPaN8gU0wL8xTOwFQVIohfTOTlhXqQOFdPPcU3Vq/9vH + iqy2Hmpkxe+shAtrAK38rkg5FvRETSFO+EOftgECgYEAi7nAy4ta2X5hHqt+86Rr + OD1M1zdhreF73WvSBIeKiR+rffbgBvIRNFkGk4iYs6Wc6ZyoS+FEJGjO33Om+I1s + Emd8JSHhRcRBq6cOsDzo4PKzMVSJaWpAfmCk9wVjAz0gpJDn2MtSanTqn1749A3L + VU7Fiz0jxshSPqw2KIjcnBI= + -----END PRIVATE KEY----- + certificate_chain: | + -----BEGIN CERTIFICATE----- + MIIDIzCCAgugAwIBAgIQBDUsQ9wfCEtzppdn5GlKUDANBgkqhkiG9w0BAQsFADAy + MREwDwYDVQQKEwhBdXRoZWxpYTEdMBsGA1UEAxMUYXV0aGVsaWEuZXhhbXBsZS5j + b20wHhcNMjUwODIzMTEwOTM2WhcNMjYwODIzMTEwOTM2WjAyMREwDwYDVQQKEwhB + dXRoZWxpYTEdMBsGA1UEAxMUYXV0aGVsaWEuZXhhbXBsZS5jb20wggEiMA0GCSqG + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuS2pK2VzqW+SnhBATps7vo2AdZCtF3p+F + OJ4WEwQoiJarS0pAJxKn4BT9PHP1gY8XCs45Qys586xQUZwS1/9B482tQwkDQkfq + XOIfTzqhTydVsi6t8Ff7ywW8K2lURcK+PnSE91Yp8tSOYWlXDajoI8wKkRSpcCAp + kmBZ3hJiJR9DlcfwKBJSNxt+DbuobQs4SOpjSY4fnDpnS5DFc72hiFOxvdx48y8c + 08UU+zNyHIIjYQ1995HwXysn7UwWCJaC4lI4ecaxHa014irOx3HsuXEzs/U5UBs2 + lBXFfKn/JHAPVJvxlER5ciUCNiHGWWh+A7hrd9BemoMQkRCIlldJAgMBAAGjNTAz + MA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8E + AjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAb910zH+0Yqxxq+LgJiIFC5guJAorY9WlD + nRHvt/1i+ZvNdc57Xq6W5/YI1g5IG/EWyDOSr5mkw6VWvGrN/HTE7cH9d2LPyWxb + n5dyUezUMdoXmizANJq7ixQLLSJiRFRhYGjiMK816m9zY/3KZqacpTJDsrhM2i6d + aaGgfkxpivMDb4PEZs4dDlR5PfFuEBFWpTDBdUeWEx/sL3t1Zfogr6lKb8PmmnEI + RKzofXAvAPQ69hE3jSWSldxqgE0Jofzwiw4dcLLAHmLlJDkbB+2HMJljFW9Fj7fK + DW7HwcVQqJ4GOW/1IjuogZuDQUlXZPMI3iujoOhYOypx6Wpf4LzO + -----END CERTIFICATE----- + clients: + - client_id: 'linkding' + client_name: 'Linkding' + client_secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'. + public: false + authorization_policy: 'one_factor' + require_pkce: false + pkce_challenge_method: '' + redirect_uris: + - 'https://linkding.example.com/oidc/callback/' + scopes: + - 'openid' + - 'email' + - 'profile' + access_token_signed_response_alg: 'none' + userinfo_signed_response_alg: 'none' + token_endpoint_auth_method: 'client_secret_post' +... diff --git a/scripts/unsecure-test-setups/authelia-oidc/authelia/users_database.yml b/scripts/unsecure-test-setups/authelia-oidc/authelia/users_database.yml new file mode 100644 index 0000000..9177ea8 --- /dev/null +++ b/scripts/unsecure-test-setups/authelia-oidc/authelia/users_database.yml @@ -0,0 +1,18 @@ +--- +############################################################### +# Users Database # +############################################################### + +# This file can be used if you do not have an LDAP set up. + +# List of users +users: + admin: + disabled: false + displayname: 'admin' + password: '$argon2id$v=19$m=65536,t=3,p=4$t6SNxOtQ6wBnGZUbPu/MVQ$+KCk9Zfc7gemFDRo5a90yfbTkkR0dI5DbeNzYkKxXLE' + email: 'admin@example.com' + groups: + - 'admins' + - 'dev' +... diff --git a/scripts/unsecure-test-setups/authelia-oidc/compose.yml b/scripts/unsecure-test-setups/authelia-oidc/compose.yml new file mode 100644 index 0000000..4a98093 --- /dev/null +++ b/scripts/unsecure-test-setups/authelia-oidc/compose.yml @@ -0,0 +1,72 @@ +# DO NOT USE THIS! +# This is only intended for testing OIDC functionality when developing Linkding. +# Follow the linkding and Authelia documentation to set up a proper production deployment. + +networks: + net: + driver: 'bridge' + +services: + linkding: + image: 'sissbruecker/linkding:local' + environment: + LD_SUPERUSER_NAME: 'admin' + LD_SUPERUSER_PASSWORD: 'admin' + LD_ENABLE_OIDC: 'True' + OIDC_RP_CLIENT_ID: 'linkding' + OIDC_RP_CLIENT_SECRET: 'insecure_secret' + OIDC_OP_AUTHORIZATION_ENDPOINT: 'https://authelia.example.com/api/oidc/authorization' + OIDC_OP_TOKEN_ENDPOINT: 'http://authelia:9091/api/oidc/token' + OIDC_OP_USER_ENDPOINT: 'http://authelia:9091/api/oidc/userinfo' + OIDC_OP_JWKS_ENDPOINT: 'http://authelia:9091/jwks.json' + networks: + net: {} + labels: + traefik.enable: 'true' + traefik.http.routers.public.rule: 'Host(`linkding.example.com`)' + traefik.http.routers.public.entrypoints: 'https' + traefik.http.routers.public.tls: 'true' + traefik.http.routers.public.tls.options: 'default' + authelia: + image: 'authelia/authelia:latest' + volumes: + - './authelia:/config' + networks: + net: {} + labels: + traefik.enable: 'true' + traefik.http.routers.authelia.rule: 'Host(`authelia.example.com`)' + traefik.http.routers.authelia.entrypoints: 'https' + traefik.http.routers.authelia.tls: 'true' + traefik.http.routers.authelia.tls.options: 'default' + traefik: + image: 'traefik:v3.5.0' + volumes: + - './traefik:/etc/traefik' + - '/var/run/docker.sock:/var/run/docker.sock' + networks: + net: {} + labels: + traefik.enable: 'true' + traefik.http.routers.api.rule: 'Host(`traefik.example.com`)' + traefik.http.routers.api.entrypoints: 'https' + traefik.http.routers.api.service: 'api@internal' + traefik.http.routers.api.tls: 'true' + traefik.http.routers.api.tls.options: 'default' + ports: + - '80:80/tcp' + - '443:443/tcp' + - '443:443/udp' + command: + - '--api' + - '--providers.docker=true' + - '--providers.docker.exposedByDefault=false' + - '--providers.file.filename=/etc/traefik/certificates.yml' + - '--entrypoints.http=true' + - '--entrypoints.http.address=:80' + - '--entrypoints.http.http.redirections.entrypoint.to=https' + - '--entrypoints.http.http.redirections.entrypoint.scheme=https' + - '--entrypoints.https=true' + - '--entrypoints.https.address=:443' + - '--log=true' + - '--log.level=DEBUG' diff --git a/scripts/unsecure-test-setups/authelia-oidc/setup.sh b/scripts/unsecure-test-setups/authelia-oidc/setup.sh new file mode 100755 index 0000000..dfb7f24 --- /dev/null +++ b/scripts/unsecure-test-setups/authelia-oidc/setup.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +writehosts(){ + echo "\ +127.0.0.1 authelia.$DOMAIN +127.0.0.1 linkding.$DOMAIN +127.0.0.1 traefik.$DOMAIN" | sudo tee -a /etc/hosts > /dev/null +} + +if [ $(id -u) != 0 ]; then + echo "The script requires root access to perform some functions such as modifying your /etc/hosts file" + read -rp "Would you like to elevate access with sudo? [y/N] " confirmsudo + if ! [[ "$confirmsudo" =~ ^([yY][eE][sS]|[yY])$ ]]; then + echo "Sudo elevation denied, exiting" + exit 1 + fi +fi + +DOMAIN="example.com" + +MODIFIED=$(cat /etc/hosts | grep $DOMAIN && echo true || echo false) + +if [[ $MODIFIED == "false" ]]; then + writehosts +fi + +sudo docker run -a stdout -v $PWD/traefik/certs:/tmp/certs authelia/authelia authelia crypto certificate rsa generate --common-name="*.${DOMAIN}" --directory=/tmp/certs/ > /dev/null +echo "Generated SSL certificate for *.$DOMAIN" + +cat << EOF +Setup completed successfully. + +You can start the stack with: + docker compose up + +You can then visit the following locations: +- https://linkding.$DOMAIN +- https://authelia.$DOMAIN +- https://traefik.$DOMAIN + +You will need to authorize the self-signed certificate upon visiting each domain. +EOF diff --git a/scripts/unsecure-test-setups/authelia-oidc/traefik/certificates.yml b/scripts/unsecure-test-setups/authelia-oidc/traefik/certificates.yml new file mode 100644 index 0000000..35ce8f2 --- /dev/null +++ b/scripts/unsecure-test-setups/authelia-oidc/traefik/certificates.yml @@ -0,0 +1,6 @@ +--- +tls: + certificates: + - certFile: '/etc/traefik/certs/public.crt' + keyFile: '/etc/traefik/certs/private.pem' +...