From 5168aa63dcf72af04f6ee0da60472f13f9cf869f Mon Sep 17 00:00:00 2001 From: joshhunt Date: Wed, 14 Jan 2026 23:51:06 +0000 Subject: [PATCH] Add fs devenv oauth setup using authelia --- devenv/frontend-service/Tiltfile | 3 + .../configs/authelia/configuration.yml | 121 ++++++++++++++++++ .../configs/authelia/users_database.yml | 45 +++++++ devenv/frontend-service/configs/nginx.conf | 2 +- devenv/frontend-service/docker-compose.yaml | 58 ++++++++- 5 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 devenv/frontend-service/configs/authelia/configuration.yml create mode 100644 devenv/frontend-service/configs/authelia/users_database.yml diff --git a/devenv/frontend-service/Tiltfile b/devenv/frontend-service/Tiltfile index 9c443cf2ece..186eb9e7d7b 100644 --- a/devenv/frontend-service/Tiltfile +++ b/devenv/frontend-service/Tiltfile @@ -71,6 +71,7 @@ dc_resource("tempo", labels=["observability"]) dc_resource("postgres", labels=["misc"]) dc_resource("tempo-init", labels=["misc"]) +dc_resource("authelia", labels=["auth"]) # paths in tilt files are confusing.... # - if tilt is dealing with the path, it is relative to the Tiltfile @@ -86,6 +87,7 @@ docker_build('grafana-fs-dev', 'devenv/frontend-service/provisioning', 'devenv/frontend-service/configs/grafana-api.local.ini', 'devenv/frontend-service/configs/frontend-service.local.ini', + 'devenv/frontend-service/configs/authelia', 'conf/defaults.ini', 'public/emails', 'public/views', @@ -107,6 +109,7 @@ docker_build('grafana-fs-dev', sync('../../public/dashboards', '/grafana/public/dashboards'), sync('../../public/app/plugins', '/grafana/public/app/plugins'), sync('../../public/build/assets-manifest.json', '/grafana/public/build/assets-manifest.json'), + sync('./configs/authelia', '/grafana/devenv/frontend-service/configs/authelia'), sync('./provisioning', '/ignore/provisioning'), # Just to trigger a restart instead of rebuild sync('./configs/grafana-api.local.ini', '/ignore/grafana-api.local.ini'), # Just to trigger a restart instead of rebuild sync('./configs/frontend-service.local.ini', '/ignore/frontend-service.local.ini'), # Just to trigger a restart instead of rebuild diff --git a/devenv/frontend-service/configs/authelia/configuration.yml b/devenv/frontend-service/configs/authelia/configuration.yml new file mode 100644 index 00000000000..793dee1629c --- /dev/null +++ b/devenv/frontend-service/configs/authelia/configuration.yml @@ -0,0 +1,121 @@ +--- +theme: light + +server: + address: 'tcp://:9091/' + +log: + level: debug + format: text + +webauthn: + disable: true + +duo_api: + disable: true + +authentication_backend: + file: + path: /config/users_database.yml + password: + algorithm: 'argon2' + password_change: + disable: true + password_reset: + disable: true + +session: + secret: insecure_session_secret + cookies: + - name: authelia_session + domain: oauth.localhost + authelia_url: https://oauth.localhost:9091 + expiration: '1 hour' + inactivity: '5 minutes' + remember_me: '1 month' + +access_control: + default_policy: one_factor + +storage: + encryption_key: you_must_generate_a_secret_of_more_than_twenty_chars_and_configure_this + local: + path: /config/db.sqlite3 + +notifier: + filesystem: + filename: /config/notification.txt + +identity_validation: + reset_password: + jwt_secret: a_very_important_secret + +identity_providers: + oidc: + hmac_secret: this_is_a_secret_abc123abc123abc123 + jwks: + - algorithm: RS256 + key: | + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCbKAl8ITAb+1I8 + 61R1bp2ZbZuSuKxUYXuCGWdGa+lhn45sVJz2HkqtYe7m/BG87WbhiJv5LYvMApFW + ajm95LLqp8z3zPzD0ULy3Nks2yNIuMSVyT7/AltvO5wg11gRJZjSkre7knRF/KP6 + ARbCwF/d1iLwXIWeGj+hCzaz3CPfMm7kSVzXUkzC1XsU38fb9TbDVHm1gQMluiKo + Yrmsz2DX6nyTSqJXfj6iblcjePs8Y9jzLNbyda7NyxA6k8WhKMwIHdCQxajsJwy6 + AnkYLTLvNlR+kD6xa4hSCUs/eDo8zqFWybEchvwwbp/Xys443GgDUf/iGbZbBl09 + tYWajIerAgMBAAECggEABzAHoHR5IhK2cJQGSZpiOqVVO6rKcO5DJne+zQhau2cE + 1gflbZFhrD6JLrImsDXfOjt13kk53K2RxgsNubpKf4xedmxMmVWsYEvS070jGU9V + 7ApynKWjTrfYN71CGyk+tyKM2Gekc0mM3xwFzefTiRdObwwaNITKxc8bLaHZF5HP + /FMG2zqf84TU1six4JamVxMK3EQSzBc1PnYoSa5W8hdQCQkZTx+T4YoGSi7UIZG1 + BAxQN8u9Dj2la8fwd8ttT+ErGScyQqbfgCbs9/5guZSHXq/qBrMJ4LP/Ir8+VVfo + lrMtxotHWKvOdZqSy0D9GlUDo7i/tgShrUGojCnQwQKBgQDbZ493k6DvcIlu8N5d + kMMScX+zi6jTQtBfJXhDRybj4i+nUTWlRbnhNAZhD7gl+z+ngnnTWqmULTAPm2Np + jZudARUNiR+iRJonLrVMWeHF2nrE5/wrF3NDe7gyUxE2lAUy/wFFbAIxCp9pD50s + bafU+OYTGe9tTzjo+40PbgMocwKBgQC1CR7QKZjP0WNKO9LQYhY8y8/jkM58GWJm + R5qhlVTJ0yLgBZy3kdxlbpUsBoE6aByOC70cNKOO0vh1iimXzGSdtznBJc+PxiXX + zDFsPoS0QHlfbCQJmYrwiZhHPNAoCWYbJo8KvkIwVnM1UFrLdpCfk9sQIoZph46+ + o7CSsI2t6QKBgBjA7FzPWR7qkXbk0hG4XWndSE0XeqqrJRs2/QSKKIcZY8r6zJSi + 8z/HQNj+jwYp/JqHi/sehXdkScHZBDRKd74U+y0VxW3nU4UMLgQ5N9G8vpEsozSx + Zp28faGf4ZdIx/Vi89/DOdQSoL2Xt2Hl1UOf+UU6bdrlT0Rp7RZKkSylAoGAfBWc + QSHB0++5FpCalqokg9dOzrPaU8UyZNh/bHFmhE9rgBFYsZoQbpW1OU/cE6R4rgPt + wv9xe9uu4SGqEJnP/SoxM+ousmUmWxtiZMcVPldS2czNhqbvTJ+C+JD+O/L1QXbU + ZJCz3V3j6Y8CLKM/zaESbaS8bGi1toWL6X+KHMECgYEAloauyKHsgtKiNF3D8OmI + unN2E9NnLGFg7R59C0j+T9+qzi5Mkfeqef5euOa7KwkbKmhr1SmGW4sjtJ2m4sdD + pyTE9OuMKK7O8xXNSRLEoBk8gjodbeobYPFPjOkAJRZZFnP2JuLhyEklP1P4J0WZ + pPBw/R+JfWyZAqJcwrNdmgU= + -----END PRIVATE KEY----- + lifespans: + access_token: '1 hour' + authorize_code: '1 minute' + id_token: '1 hour' + refresh_token: '90 minutes' + enable_client_debug_messages: true + authorization_policies: + grafana_group_policy: + default_policy: 'deny' + rules: + - policy: 'one_factor' + subject: 'group:grafana' + clients: + - client_id: 'grafana' + consent_mode: implicit + client_name: 'Grafana' + client_secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'. + public: false + authorization_policy: 'grafana_group_policy' + require_pkce: true + pkce_challenge_method: 'S256' + redirect_uris: + - http://localhost:3000/login/generic_oauth + scopes: + - 'openid' + - 'profile' + - 'groups' + - 'email' + response_types: + - 'code' + grant_types: + - 'authorization_code' + access_token_signed_response_alg: 'RS256' + userinfo_signed_response_alg: 'none' + token_endpoint_auth_method: 'client_secret_basic' diff --git a/devenv/frontend-service/configs/authelia/users_database.yml b/devenv/frontend-service/configs/authelia/users_database.yml new file mode 100644 index 00000000000..fdd2114a3a1 --- /dev/null +++ b/devenv/frontend-service/configs/authelia/users_database.yml @@ -0,0 +1,45 @@ +# This file defines test users for local development. +# Password: all users have password "password" +# Password hash generated with: docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'password' +# +# Users must in the 'grafana' group to be able to log in to Grafana. + +users: + # Admin user with GrafanaAdmin role + oauth-admin: + disabled: false + displayname: 'Admin User' + password: '$argon2id$v=19$m=65536,t=3,p=4$an3cCNeaYsC2sFIc1LrCLQ$YxvcYkj2NTUsV5o5wxeIc0KNhqc8/mPIKKC6e1AnC4A' + email: test1@example.com + groups: + - grafana + - grafanaadmin + + # Editor user + oauth-editor: + disabled: false + displayname: 'Editor User' + password: '$argon2id$v=19$m=65536,t=3,p=4$an3cCNeaYsC2sFIc1LrCLQ$YxvcYkj2NTUsV5o5wxeIc0KNhqc8/mPIKKC6e1AnC4A' + email: test2@example.com + groups: + - grafana + - editor + + # Viewer user + oauth-viewer: + disabled: false + displayname: 'Viewer User' + password: '$argon2id$v=19$m=65536,t=3,p=4$an3cCNeaYsC2sFIc1LrCLQ$YxvcYkj2NTUsV5o5wxeIc0KNhqc8/mPIKKC6e1AnC4A' + email: test3@example.com + groups: + - grafana + - viewer + + # Denied access user (not in grafana group) + norole: + disabled: false + displayname: 'No Role User' + password: '$argon2id$v=19$m=65536,t=3,p=4$an3cCNeaYsC2sFIc1LrCLQ$YxvcYkj2NTUsV5o5wxeIc0KNhqc8/mPIKKC6e1AnC4A' + email: norole@example.com + groups: + - users diff --git a/devenv/frontend-service/configs/nginx.conf b/devenv/frontend-service/configs/nginx.conf index aa0c2499656..0fbf748b7c7 100644 --- a/devenv/frontend-service/configs/nginx.conf +++ b/devenv/frontend-service/configs/nginx.conf @@ -73,7 +73,7 @@ server { } # API calls go to the backend - location ~ ^/(api|apis|avatar|bootdata|render|logout|public/plugins|public/openapi3|public/api-merged|goto|swagger|openapi/v3) { + location ~ ^/(api|apis|avatar|bootdata|render|logout|public/plugins|public/openapi3|public/api-merged|goto|swagger|openapi/v3|login/generic_oauth) { # Add debug headers to the response add_header Nginx-Trace-Id $otel_trace_id always; add_header Nginx-Route "backend" always; diff --git a/devenv/frontend-service/docker-compose.yaml b/devenv/frontend-service/docker-compose.yaml index 606067f9629..eb6061a8133 100644 --- a/devenv/frontend-service/docker-compose.yaml +++ b/devenv/frontend-service/docker-compose.yaml @@ -41,7 +41,7 @@ services: GF_FEATURE_TOGGLES_ENABLE: enableNativeHTTPHistogram GF_DATABASE_URL: postgres://grafana:grafana@postgres:5432/grafana GF_SERVER_ROUTER_LOGGING: true - GF_LOG_LEVEL: info + GF_LOG_LEVEL: debug GF_AUTH_LOGIN_COOKIE_NAME: grafana_fs_dev_login # set a custom cookie name to not conflict with other instances running on localhost OTEL_SERVICE_NAME: grafana-api GF_TRACING_OPENTELEMETRY_OTLP_ADDRESS: 'alloy:4317' @@ -150,6 +150,62 @@ services: tempo-init: condition: service_completed_successfully +<<<<<<< ours + authelia: + image: authelia/authelia:latest + container_name: authelia + volumes: + - ./configs/authelia/configuration.yml:/config/configuration.yml + - ./configs/authelia/users_database.yml:/config/users_database.yml + ports: + - '9091:9091' + environment: + - TZ=UTC + labels: + - 'alloy.logs=true' + + authelia: + image: authelia/authelia:latest + container_name: authelia + volumes: + - ./configs/authelia/configuration.yml:/config/configuration.yml + - ./configs/authelia/users_database.yml:/config/users_database.yml + ports: + - '9091:9091' + environment: + - TZ=UTC + labels: + - 'alloy.logs=true' + + authelia: + image: authelia/authelia:latest + container_name: authelia + volumes: + - ./configs/authelia/configuration.yml:/config/configuration.yml + - ./configs/authelia/users_database.yml:/config/users_database.yml + ports: + - '9091:9091' + environment: + - TZ=UTC + labels: + - 'alloy.logs=true' + +||||||| ancestor +======= + authelia: + image: authelia/authelia:latest + container_name: authelia + volumes: + - ./configs/authelia/configuration.yml:/config/configuration.yml + - ./configs/authelia/users_database.yml:/config/users_database.yml + ports: + - '9091:9091' + environment: + - TZ=UTC + labels: + - 'alloy.logs=true' + +>>>>>>> theirs volumes: backend-data: postgres-data: