diff --git a/argocd/manifests/authentik/configmap-blueprint.yaml b/argocd/manifests/authentik/configmap-blueprint.yaml new file mode 100644 index 0000000..527748d --- /dev/null +++ b/argocd/manifests/authentik/configmap-blueprint.yaml @@ -0,0 +1,72 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: authentik-blueprints + namespace: authentik +data: + grafana.yaml: | + version: 1 + metadata: + name: BlumeOps Grafana SSO + labels: + blueprints.goauthentik.io/description: "Grafana OIDC provider and application" + entries: + # admins group — gates access to admin-only applications + - model: authentik_core.group + id: admins-group + identifiers: + name: admins + attrs: + name: admins + + # OAuth2 provider for Grafana + - model: authentik_providers_oauth2.oauth2provider + id: grafana-provider + identifiers: + name: Grafana + attrs: + name: Grafana + authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]] + invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]] + client_type: confidential + client_id: grafana + client_secret: !Env [AUTHENTIK_GRAFANA_CLIENT_SECRET] + redirect_uris: + - matching_mode: strict + url: https://grafana.ops.eblu.me/login/generic_oauth + - matching_mode: strict + url: https://grafana.tail8d86e.ts.net/login/generic_oauth + signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]] + property_mappings: + - !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]] + - !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]] + - !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]] + sub_mode: hashed_user_id + include_claims_in_id_token: true + + # Grafana application — linked to the OAuth2 provider + - model: authentik_core.application + id: grafana-app + identifiers: + slug: grafana + attrs: + name: Grafana + slug: grafana + provider: !KeyOf grafana-provider + meta_launch_url: https://grafana.ops.eblu.me + policy_engine_mode: any + + # Policy binding — restrict Grafana to admins group + - model: authentik_policies.policybinding + identifiers: + order: 0 + target: !KeyOf grafana-app + group: !KeyOf admins-group + attrs: + target: !KeyOf grafana-app + group: !KeyOf admins-group + order: 0 + enabled: true + negate: false + timeout: 30 diff --git a/argocd/manifests/authentik/deployment-worker.yaml b/argocd/manifests/authentik/deployment-worker.yaml index 152b460..0ab1067 100644 --- a/argocd/manifests/authentik/deployment-worker.yaml +++ b/argocd/manifests/authentik/deployment-worker.yaml @@ -53,6 +53,15 @@ spec: key: postgresql-password - name: AUTHENTIK_REDIS__HOST value: authentik-redis + - name: AUTHENTIK_GRAFANA_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: authentik-config + key: grafana-client-secret + volumeMounts: + - name: blueprints + mountPath: /blueprints/custom + readOnly: true resources: requests: memory: "256Mi" @@ -60,3 +69,7 @@ spec: limits: memory: "1Gi" cpu: "1000m" + volumes: + - name: blueprints + configMap: + name: authentik-blueprints diff --git a/argocd/manifests/authentik/external-secret.yaml b/argocd/manifests/authentik/external-secret.yaml index 2c17d91..b7072a0 100644 --- a/argocd/manifests/authentik/external-secret.yaml +++ b/argocd/manifests/authentik/external-secret.yaml @@ -37,3 +37,7 @@ spec: remoteRef: key: "Authentik (blumeops)" property: postgresql-password + - secretKey: grafana-client-secret + remoteRef: + key: "Authentik (blumeops)" + property: grafana-client-secret diff --git a/argocd/manifests/authentik/kustomization.yaml b/argocd/manifests/authentik/kustomization.yaml index 385ae5b..f639eba 100644 --- a/argocd/manifests/authentik/kustomization.yaml +++ b/argocd/manifests/authentik/kustomization.yaml @@ -4,6 +4,7 @@ kind: Kustomization namespace: authentik resources: - external-secret.yaml + - configmap-blueprint.yaml - deployment-server.yaml - deployment-worker.yaml - deployment-redis.yaml diff --git a/argocd/manifests/grafana-config/external-secret-authentik-oauth.yaml b/argocd/manifests/grafana-config/external-secret-authentik-oauth.yaml new file mode 100644 index 0000000..a83d35e --- /dev/null +++ b/argocd/manifests/grafana-config/external-secret-authentik-oauth.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: grafana-authentik-oauth + namespace: monitoring +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: grafana-authentik-oauth + creationPolicy: Owner + template: + data: + GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: "{{ .clientSecret }}" + data: + - secretKey: clientSecret + remoteRef: + key: "Authentik (blumeops)" + property: grafana-client-secret diff --git a/argocd/manifests/grafana-config/kustomization.yaml b/argocd/manifests/grafana-config/kustomization.yaml index 59e4e19..7322144 100644 --- a/argocd/manifests/grafana-config/kustomization.yaml +++ b/argocd/manifests/grafana-config/kustomization.yaml @@ -6,7 +6,7 @@ namespace: monitoring resources: - ingress-tailscale.yaml - external-secret-admin.yaml - - external-secret-dex-oauth.yaml + - external-secret-authentik-oauth.yaml - external-secret-teslamate-datasource.yaml # Dashboard ConfigMaps - discovered by Grafana sidecar via label grafana_dashboard=1 - dashboards/configmap-borgmatic.yaml diff --git a/argocd/manifests/grafana/values.yaml b/argocd/manifests/grafana/values.yaml index 24c406c..b07c74e 100644 --- a/argocd/manifests/grafana/values.yaml +++ b/argocd/manifests/grafana/values.yaml @@ -12,7 +12,7 @@ admin: envFromSecrets: - name: grafana-teslamate-datasource optional: true - - name: grafana-dex-oauth + - name: grafana-authentik-oauth optional: true # Persistence with PVC for SQLite database @@ -32,13 +32,13 @@ grafana.ini: allow_embedding: false auth.generic_oauth: enabled: true - name: Dex + name: Authentik client_id: grafana client_secret: $__env{GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET} scopes: openid profile email - auth_url: https://dex.ops.eblu.me/auth - token_url: https://dex.ops.eblu.me/token - api_url: https://dex.ops.eblu.me/userinfo + auth_url: https://authentik.ops.eblu.me/application/o/authorize/ + token_url: https://authentik.ops.eblu.me/application/o/token/ + api_url: https://authentik.ops.eblu.me/application/o/userinfo/ allow_sign_up: true role_attribute_path: "'Admin'" auto_login: false