Register Zot as OIDC client in Authentik (#236)

## Summary
- Add Authentik blueprint (`zot.yaml`) with OAuth2 provider, application, `artifact-workloads` group, and `zot-ci` service account
- Wire `zot-client-secret` through ExternalSecret → worker Deployment env var → blueprint `!Env`
- Add Ansible pre_task to fetch OIDC secret from 1Password (item ID `oor7os5kapczgpbwv7obkca4y4`)
- Add `oidc-credentials.json.j2` template and deploy task in zot role (with `when` guard)

## Manual Steps Required Before Deploy
1. Generate client secret: `openssl rand -hex 32`
2. Store in 1Password: add field `zot-client-secret` to "Authentik (blumeops)" item in vault `blumeops`

## What This Does NOT Do
- Does NOT modify `config.json.j2` (that's the root goal `harden-zot-registry`)
- Does NOT wire CI auth (that's `wire-ci-registry-auth`)
- Does NOT set service account password or API keys (manual post-deploy)

## Verification
After ArgoCD sync:
- [ ] Authentik admin UI shows "Zot Registry" application
- [ ] OIDC discovery at `https://authentik.ops.eblu.me/application/o/zot/.well-known/openid-configuration` returns valid JSON
- [ ] Blueprint status is `successful`
- [ ] `artifact-workloads` group exists with `zot-ci` service account

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/236
This commit is contained in:
Erich Blume 2026-02-21 08:45:06 -08:00
commit 21b6533aea
7 changed files with 116 additions and 0 deletions

View file

@ -154,3 +154,80 @@ data:
enabled: true
negate: false
timeout: 30
zot.yaml: |
version: 1
metadata:
name: BlumeOps Zot SSO
labels:
blueprints.goauthentik.io/description: "Zot OIDC provider, application, and CI identity"
entries:
# artifact-workloads group (CI push identity)
- model: authentik_core.group
id: artifact-workloads-group
identifiers:
name: artifact-workloads
attrs:
name: artifact-workloads
# Service account for CI push (admin sets password via UI after deploy)
- model: authentik_core.user
id: zot-ci-user
identifiers:
username: zot-ci
attrs:
username: zot-ci
name: Zot CI Service Account
type: service_account
is_active: true
groups:
- !KeyOf artifact-workloads-group
# OAuth2 provider for Zot
- model: authentik_providers_oauth2.oauth2provider
id: zot-provider
identifiers:
name: Zot
attrs:
name: Zot
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: zot
client_secret: !Env AUTHENTIK_ZOT_CLIENT_SECRET
redirect_uris:
- matching_mode: strict
url: https://registry.ops.eblu.me/zot/auth/callback/oidc
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
# Zot application — linked to the OAuth2 provider
- model: authentik_core.application
id: zot-app
identifiers:
slug: zot
attrs:
name: Zot Registry
slug: zot
provider: !KeyOf zot-provider
meta_launch_url: https://registry.ops.eblu.me
policy_engine_mode: any
# Policy binding — restrict Zot to admins group
- model: authentik_policies.policybinding
identifiers:
order: 0
target: !KeyOf zot-app
group: !Find [authentik_core.group, [name, admins]]
attrs:
target: !KeyOf zot-app
group: !Find [authentik_core.group, [name, admins]]
order: 0
enabled: true
negate: false
timeout: 30

View file

@ -63,6 +63,11 @@ spec:
secretKeyRef:
name: authentik-config
key: forgejo-client-secret
- name: AUTHENTIK_ZOT_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: authentik-config
key: zot-client-secret
volumeMounts:
- name: blueprints
mountPath: /blueprints/custom

View file

@ -45,3 +45,7 @@ spec:
remoteRef:
key: "Authentik (blumeops)"
property: forgejo-client-secret
- secretKey: zot-client-secret
remoteRef:
key: "Authentik (blumeops)"
property: zot-client-secret