diff --git a/apps/templates/authentik-helm.yaml b/apps/templates/authentik-helm.yaml index 11006fd..1602511 100644 --- a/apps/templates/authentik-helm.yaml +++ b/apps/templates/authentik-helm.yaml @@ -127,6 +127,21 @@ spec: - name: blueprint-longhorn configMap: name: authentik-blueprint-longhorn + # Directory mounts, not subPath, so changes reach the pods + # without a restart. The secrets are optional: a blueprint + # that needs a missing one fails until it shows up. + - name: blueprint-scouting + configMap: + name: authentik-blueprint-scouting + - name: scouting-secrets + projected: + sources: + - secret: + name: immich-oidc-client-secret + optional: true + items: + - key: client_secret + path: immich-oidc-client-secret volumeMounts: - name: blueprint-vault mountPath: /blueprints/custom/vault-oidc.yaml @@ -152,6 +167,11 @@ spec: - name: blueprint-longhorn mountPath: /blueprints/custom/longhorn-oidc.yaml subPath: longhorn-oidc.yaml + - name: blueprint-scouting + mountPath: /blueprints/custom/scouting + - name: scouting-secrets + mountPath: /secrets/scouting + readOnly: true - name: patched-ca-bundle mountPath: /etc/ssl/certs readOnly: true @@ -184,6 +204,21 @@ spec: - name: blueprint-longhorn configMap: name: authentik-blueprint-longhorn + # Directory mounts, not subPath, so changes reach the pods + # without a restart. The secrets are optional: a blueprint + # that needs a missing one fails until it shows up. + - name: blueprint-scouting + configMap: + name: authentik-blueprint-scouting + - name: scouting-secrets + projected: + sources: + - secret: + name: immich-oidc-client-secret + optional: true + items: + - key: client_secret + path: immich-oidc-client-secret volumeMounts: - name: blueprint-vault mountPath: /blueprints/custom/vault-oidc.yaml @@ -209,6 +244,11 @@ spec: - name: blueprint-longhorn mountPath: /blueprints/custom/longhorn-oidc.yaml subPath: longhorn-oidc.yaml + - name: blueprint-scouting + mountPath: /blueprints/custom/scouting + - name: scouting-secrets + mountPath: /secrets/scouting + readOnly: true - name: patched-ca-bundle mountPath: /etc/ssl/certs readOnly: true diff --git a/authentik/blueprint-scouting.yaml b/authentik/blueprint-scouting.yaml new file mode 100644 index 0000000..d83bfc3 --- /dev/null +++ b/authentik/blueprint-scouting.yaml @@ -0,0 +1,95 @@ +# Login for the Scouting MBG photos (immich on foto.scoutingmbg.nl). +# Mounted as a directory, unlike the other blueprints, so authentik picks up +# changes without a restart; secrets come from files in /secrets/scouting +# for the same reason (see apps/templates/authentik-helm.yaml). +apiVersion: v1 +kind: ConfigMap +metadata: + name: authentik-blueprint-scouting +data: + immich-oidc.yaml: | + version: 1 + metadata: + name: immich OIDC + entries: + # Filled by the Scouts Online source on every login: every member, and + # the members with an active Kaderlid role. + - model: authentik_core.group + id: mbg-leden + state: present + identifiers: + name: MBG leden + - model: authentik_core.group + id: mbg-kader + state: present + identifiers: + name: MBG kader + # immich syncs both claims on every login. A quota of 0 makes immich + # refuse uploads, -1 means unlimited. + - model: authentik_providers_oauth2.scopemapping + id: immich-scope + state: present + identifiers: + name: "immich: role and quota" + attrs: + name: "immich: role and quota" + scope_name: immich + description: Upload rights in the Scouting MBG photos + expression: | + admin = ak_is_group_member(request.user, name="authentik Admins") + uploader = admin or ak_is_group_member(request.user, name="MBG kader") + return { + "immich_role": "admin" if admin else "user", + "immich_quota": -1 if uploader else 0, + } + - model: authentik_providers_oauth2.oauth2provider + id: immich-provider + state: present + identifiers: + name: immich + attrs: + name: immich + authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]] + authentication_flow: !Find [authentik_flows.flow, [slug, default-authentication-flow]] + invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]] + client_type: confidential + client_id: immich + client_secret: !File /secrets/scouting/immich-oidc-client-secret + redirect_uris: + - matching_mode: strict + url: https://foto.scoutingmbg.nl/auth/login + # "Link to OAuth" in immich's account settings + - matching_mode: strict + url: https://foto.scoutingmbg.nl/user-settings + - matching_mode: strict + url: app.immich:///oauth-callback + signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Self-signed Certificate"]] + property_mappings: + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-openid]] + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-email]] + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-profile]] + - !KeyOf immich-scope + - model: authentik_core.application + id: immich-app + state: present + identifiers: + slug: immich + attrs: + name: Scouting MBG foto's + provider: !KeyOf immich-provider + meta_launch_url: https://foto.scoutingmbg.nl + policy_engine_mode: any + - model: authentik_policies.policybinding + state: present + identifiers: + order: 0 + target: !KeyOf immich-app + attrs: + group: !KeyOf mbg-leden + - model: authentik_policies.policybinding + state: present + identifiers: + order: 1 + target: !KeyOf immich-app + attrs: + group: !Find [authentik_core.group, [name, "authentik Admins"]] diff --git a/authentik/external-secret.yaml b/authentik/external-secret.yaml index d4e10ec..d70dd54 100644 --- a/authentik/external-secret.yaml +++ b/authentik/external-secret.yaml @@ -153,3 +153,22 @@ spec: remoteRef: key: kv/longhorn-oidc property: client_secret +--- +# Mounted as a file for blueprint-scouting.yaml, not as an env variable. +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: immich-oidc-client-secret +spec: + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + refreshInterval: 15m + target: + name: immich-oidc-client-secret + creationPolicy: Owner + data: + - secretKey: client_secret + remoteRef: + key: kv/immich-oidc + property: client_secret