From bc81690d9f5f1e40dfdc2fb1fb22c6ba4fa3fda8 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 12 Jul 2026 22:31:37 +1000 Subject: [PATCH] Wire ArgoCD to Authentik OIDC ArgoCD had no external ingress and only local admin auth. This exposes argocd-server behind the traefik-internal gateway and enables Authentik SSO, so operators log in with their identity and group membership. - argocd-cm: set url and oidc.config (Authentik issuer, argocd client, openid/profile/email scopes); client secret resolved from the argocd-oidc Secret via $argocd-oidc:client_secret - argocd-rbac-cm: match on the groups claim; default role:readonly; map the argocd-admins Authentik group to role:admin - argocd-cmd-params-cm: server.insecure=true so argocd-server serves HTTP behind the TLS-terminating gateway - Add Gateway + HTTPRoutes for argocd.k8s.syd1.au.unkin.net (mirrors grafana) - Add VaultAuth + VaultStaticSecret sourcing the OIDC client secret from kv/kubernetes/namespace/argocd/default/oauth-credentials into the argocd-oidc Secret (labelled part-of=argocd) Note: the OIDC client secret must be seeded in Vault out of band, and argocd-server needs a one-time rollout restart to pick up server.insecure. --- .../au-syd1/bootstrap/argocd-cm-patch.yaml | 17 ++++++ .../bootstrap/argocd-cmd-params-cm-patch.yaml | 10 ++++ .../bootstrap/argocd-oidc-vaultauth.yaml | 18 ++++++ .../argocd-oidc-vaultstaticsecret.yaml | 23 ++++++++ .../bootstrap/argocd-rbac-cm-patch.yaml | 14 +++++ .../bootstrap/argocd-server-gateway.yaml | 39 +++++++++++++ .../bootstrap/argocd-server-httproute.yaml | 55 +++++++++++++++++++ clusters/au-syd1/bootstrap/kustomization.yaml | 13 +++++ 8 files changed, 189 insertions(+) create mode 100644 clusters/au-syd1/bootstrap/argocd-cmd-params-cm-patch.yaml create mode 100644 clusters/au-syd1/bootstrap/argocd-oidc-vaultauth.yaml create mode 100644 clusters/au-syd1/bootstrap/argocd-oidc-vaultstaticsecret.yaml create mode 100644 clusters/au-syd1/bootstrap/argocd-rbac-cm-patch.yaml create mode 100644 clusters/au-syd1/bootstrap/argocd-server-gateway.yaml create mode 100644 clusters/au-syd1/bootstrap/argocd-server-httproute.yaml diff --git a/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml b/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml index 117b043..1c587f2 100644 --- a/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml +++ b/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml @@ -6,3 +6,20 @@ metadata: namespace: argocd data: kustomize.buildOptions: "--enable-helm" + # External URL ArgoCD serves on (TLS terminated at the traefik-internal gateway). + url: https://argocd.k8s.syd1.au.unkin.net + # OIDC login via Authentik. The client secret is seeded in Vault out of band + # and surfaced as the `argocd-oidc` Secret (labelled part-of=argocd) by VSO; + # `$argocd-oidc:client_secret` resolves the key from that Secret. + oidc.config: | + name: Authentik + issuer: https://identity.unkin.net/application/o/argocd/ + clientID: argocd + clientSecret: $argocd-oidc:client_secret + requestedScopes: + - openid + - profile + - email + requestedIDTokenClaims: + groups: + essential: true diff --git a/clusters/au-syd1/bootstrap/argocd-cmd-params-cm-patch.yaml b/clusters/au-syd1/bootstrap/argocd-cmd-params-cm-patch.yaml new file mode 100644 index 0000000..65ec94d --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-cmd-params-cm-patch.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cmd-params-cm + namespace: argocd +data: + # argocd-server serves plain HTTP; TLS is terminated at the traefik-internal + # gateway in front of it. Required so the gateway can route to port 80. + server.insecure: "true" diff --git a/clusters/au-syd1/bootstrap/argocd-oidc-vaultauth.yaml b/clusters/au-syd1/bootstrap/argocd-oidc-vaultauth.yaml new file mode 100644 index 0000000..16af52b --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-oidc-vaultauth.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultAuth +metadata: + name: default + namespace: argocd +spec: + method: kubernetes + mount: k8s/au/syd1 + vaultConnectionRef: vso-system/default + allowedNamespaces: + - argocd + kubernetes: + role: default + serviceAccount: default + audiences: + - vault + tokenExpirationSeconds: 600 diff --git a/clusters/au-syd1/bootstrap/argocd-oidc-vaultstaticsecret.yaml b/clusters/au-syd1/bootstrap/argocd-oidc-vaultstaticsecret.yaml new file mode 100644 index 0000000..9b73990 --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-oidc-vaultstaticsecret.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: argocd-oidc + namespace: argocd +spec: + vaultAuthRef: default + mount: kv + type: kv-v2 + # Seeded out of band; same secret is read by terraform-authentik to configure + # the provider's client_secret. Key: client_secret. + path: kubernetes/namespace/argocd/default/oauth-credentials + refreshAfter: 5m + hmacSecretData: true + destination: + name: argocd-oidc + create: true + overwrite: true + # ArgoCD only resolves `$secret:key` references against Secrets carrying + # this label. + labels: + app.kubernetes.io/part-of: argocd diff --git a/clusters/au-syd1/bootstrap/argocd-rbac-cm-patch.yaml b/clusters/au-syd1/bootstrap/argocd-rbac-cm-patch.yaml new file mode 100644 index 0000000..4bb25ff --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-rbac-cm-patch.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-rbac-cm + namespace: argocd +data: + # Match RBAC subjects against the `groups` claim from Authentik. + scopes: "[groups]" + # Authenticated users with no matching group get read-only access. + policy.default: role:readonly + # Authentik group -> ArgoCD role. + policy.csv: | + g, argocd-admins, role:admin diff --git a/clusters/au-syd1/bootstrap/argocd-server-gateway.yaml b/clusters/au-syd1/bootstrap/argocd-server-gateway.yaml new file mode 100644 index 0000000..2c9eeb3 --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-server-gateway.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: argocd-server + namespace: argocd + labels: + app.kubernetes.io/name: argocd-server + app.kubernetes.io/instance: argocd + traefik.io/instance: internal + annotations: + cert-manager.io/cluster-issuer: vault-issuer + cert-manager.io/common-name: argocd.k8s.syd1.au.unkin.net + cert-manager.io/private-key-size: "4096" + external-dns.alpha.kubernetes.io/hostname: argocd.k8s.syd1.au.unkin.net + external-dns.alpha.kubernetes.io/target: 198.18.200.4 +spec: + gatewayClassName: traefik-internal + listeners: + - name: http + port: 80 + protocol: HTTP + hostname: argocd.k8s.syd1.au.unkin.net + allowedRoutes: + namespaces: + from: Same + - name: https + port: 443 + protocol: HTTPS + hostname: argocd.k8s.syd1.au.unkin.net + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: argocd-server-tls diff --git a/clusters/au-syd1/bootstrap/argocd-server-httproute.yaml b/clusters/au-syd1/bootstrap/argocd-server-httproute.yaml new file mode 100644 index 0000000..aadb581 --- /dev/null +++ b/clusters/au-syd1/bootstrap/argocd-server-httproute.yaml @@ -0,0 +1,55 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: argocd-server-http-redirect + namespace: argocd + labels: + app.kubernetes.io/name: argocd-server + app.kubernetes.io/instance: argocd +spec: + hostnames: + - argocd.k8s.syd1.au.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: argocd-server + sectionName: http + rules: + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: argocd-server + namespace: argocd + labels: + app.kubernetes.io/name: argocd-server + app.kubernetes.io/instance: argocd +spec: + hostnames: + - argocd.k8s.syd1.au.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: argocd-server + sectionName: https + rules: + - backendRefs: + - group: "" + kind: Service + name: argocd-server + port: 80 + weight: 1 + matches: + - path: + type: PathPrefix + value: / diff --git a/clusters/au-syd1/bootstrap/kustomization.yaml b/clusters/au-syd1/bootstrap/kustomization.yaml index 474f67a..56eff8d 100644 --- a/clusters/au-syd1/bootstrap/kustomization.yaml +++ b/clusters/au-syd1/bootstrap/kustomization.yaml @@ -7,12 +7,25 @@ resources: - https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml - au-syd1-apps.yaml - argocd-self-app.yaml + # Authentik OIDC: expose argocd-server and wire the client secret from Vault. + - argocd-server-gateway.yaml + - argocd-server-httproute.yaml + - argocd-oidc-vaultauth.yaml + - argocd-oidc-vaultstaticsecret.yaml patches: - path: argocd-cm-patch.yaml target: kind: ConfigMap name: argocd-cm + - path: argocd-rbac-cm-patch.yaml + target: + kind: ConfigMap + name: argocd-rbac-cm + - path: argocd-cmd-params-cm-patch.yaml + target: + kind: ConfigMap + name: argocd-cmd-params-cm - path: argocd-tls-certs-patch.yaml target: kind: ConfigMap