# Authentik OAuth provisioning — MANUAL operation, NOT auto-run. # # Security-sensitive IAM changes should be reviewed and run locally: # export AUTHENTIK_BOOTSTRAP_TOKEN=$(kubectl -n iam get secret authentik-secrets \ # -o jsonpath='{.data.AUTHENTIK_BOOTSTRAP_TOKEN}' | base64 -d) # sed 's|http://authentik-server.iam.svc.cluster.local|https://authentik.riotpiao.com|g' \ # k8s/infra/iam/scripts/authentik-provision.py | python3 # # What it does (see scripts/authentik-provision.py docstring): creates scope # mappings (groups, permissions, memory, policy, immich_role), admin groups, # the "rock" admin user, OAuth2 providers + Applications, service accounts # (portfolio-agent, memory-agent), and binds groups to applications. # # This file provides the RBAC (ServiceAccount + RoleBindings) needed if you # ever want to run the Job in-cluster manually (kubectl create -f), but the # PostSync hook is deliberately removed — IAM is not GitOps-auto-deployed. # # RBAC: this Job only touches Secrets (get existing client secrets, create new # ones) across the namespaces those services live in. apiVersion: v1 kind: ServiceAccount metadata: name: authentik-provisioner namespace: iam --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: authentik-provisioner rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "create", "update", "patch"] --- # One RoleBinding per namespace the script touches (least-privilege: Secrets # only, and only in these 5 namespaces — not a cluster-wide ClusterRoleBinding). apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: iam subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: cicd subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: argocd subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: logging subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: storage subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: paperless subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: immich subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: llm-serving subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: portfolio subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: poimen subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: authentik-provisioner namespace: dashboard subjects: - kind: ServiceAccount name: authentik-provisioner namespace: iam roleRef: kind: ClusterRole name: authentik-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: batch/v1 kind: Job metadata: name: authentik-provision namespace: iam # No ArgoCD hook - run manually when IAM changes are needed spec: ttlSecondsAfterFinished: 600 backoffLimit: 3 template: spec: serviceAccountName: authentik-provisioner restartPolicy: Never securityContext: runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault containers: - name: provision image: python:3.12-alpine securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] env: - name: AUTHENTIK_BOOTSTRAP_TOKEN valueFrom: secretKeyRef: name: authentik-secrets key: AUTHENTIK_BOOTSTRAP_TOKEN volumeMounts: - name: script mountPath: /script command: - /bin/sh - -c - | set -e echo "waiting for authentik-server..." until wget -q -O /dev/null http://authentik-server.iam.svc.cluster.local/-/health/ready/ 2>/dev/null; do sleep 5 done echo "installing kubectl (via python urllib - no apk/curl: this" echo "container runs as non-root UID 1000 and can't write to" echo "apk's directories or /usr/local/bin, both root-owned in" echo "the python:3.12-alpine image; /tmp is world-writable)..." python3 -c " import urllib.request, os, stat kver = urllib.request.urlopen('https://dl.k8s.io/release/stable.txt').read().decode().strip() url = f'https://dl.k8s.io/release/{kver}/bin/linux/amd64/kubectl' urllib.request.urlretrieve(url, '/tmp/kubectl') st = os.stat('/tmp/kubectl') os.chmod('/tmp/kubectl', st.st_mode | stat.S_IEXEC) " export PATH="/tmp:$PATH" echo "running provisioning script..." python3 /script/authentik-provision.py volumes: - name: script configMap: name: authentik-provision-script