Skip to content

hops-ops/auth-stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

auth-stack

Installs Zitadel into a Kubernetes cluster as the platform identity provider, and hosts a focused set of auth.hops.ops.com.ai primitive XRDs (HumanUser, MachineUser, Grant, IDP) that compose against the installed Zitadel.

The stack XRD (AuthStack) wraps the upstream zitadel/zitadel Helm chart — handling the namespace, database wiring, Gateway API routing, and re-projecting chart-managed bootstrap secrets (admin PAT + login-client PAT) into XR status for downstream consumers.

The primitive XRDs let operators declaratively manage the identity model inside a running Zitadel — see Auth-group primitives below.

Quick Start

Local-dev (colima cluster, bundled Postgres, no TLS):

apiVersion: hops.ops.com.ai/v1alpha1
kind: AuthStack
metadata:
  name: auth
  namespace: default
spec:
  clusterName: colima
  domain: auth.localtest.me
  externalSecure: false
  database:
    bundled: true

Production (managed Postgres + Gateway API):

apiVersion: hops.ops.com.ai/v1alpha1
kind: AuthStack
metadata:
  name: auth
  namespace: platform
spec:
  clusterName: prod
  domain: auth.example.com
  firstInstance:
    org: hops-ops
  database:
    external:
      dsnSecretRef:
        name: zitadel-db
        key: dsn
  gateway:
    enabled: true
    parentRef:
      name: platform-gateway
      namespace: istio-system

Database Modes

Exactly one of:

Mode When Notes
external Production with managed Postgres (RDS, CNPG cluster, etc.) Provide a Secret containing the DSN; chart reads ZITADEL_DATABASE_POSTGRES_DSN.
bundled Local dev only Sets postgresql.enabled=true so the chart uses its bundled Bitnami subchart. Not for production.
psqlStack Future Reserved for the platform PSQLStack integration; pending the PSQLDatabase XRD. The composition currently rejects this mode.

Bootstrap & Status Contract

The zitadel/zitadel chart's setup hook creates two machine users on first install:

  • <iamAdmin.username> — JWT machine key in a chart-managed Secret named after the username
  • <iamAdmin.username>-pat — admin PAT
  • <loginClient.username> — login-client PAT

This stack does not author its own init Job. It re-projects those Secret references into XR status so downstream consumers (the future Zitadel Crossplane provider, ad-hoc admin tooling) have a stable place to read the credentials:

status:
  oidc:
    issuerURL: https://auth.example.com
    discoveryURL: https://auth.example.com/.well-known/openid-configuration
  bootstrap:
    iamAdminPatSecretRef:    { name: iam-admin-pat,  namespace: zitadel, key: pat }
    iamAdminKeySecretRef:    { name: iam-admin,      namespace: zitadel, key: key }
    loginClientPatSecretRef: { name: login-client,   namespace: zitadel, key: pat }

Auth-group primitives

Per [[specs/identity-architecture]], the auth-group primitive XRDs that have substantive composition value-add — MachineUser, Grant — live in this repo alongside AuthStack under the auth.hops.ops.com.ai group.

Status:

Kind Plural Composes Status
MachineUser machineusers MachineUser + opt-in AccessToken + opt-in AWS SM Secret + ESO PushSecret (provider-kubernetes Object)
Grant grants user.zitadel.../Grant (same-Org) or project.zitadel.../Grant + user.zitadel.../Grant with projectGrantId (cross-Org)

Single-resource wrappers we deliberately didn't make: HumanUser, IDP, OrganizationSsoConfig (and the previously-attempted Organization, Project). Operators apply raw Zitadel / OpenPanel MRs directly for those.

MachineUser

Declarative Zitadel machine identity for CI runners, Crossplane providers, cross-cluster syncs — anything that needs a long-lived credential to call a SaaS API.

The XRD's value-add is bundling. The MachineUser MR alone is one Zitadel resource. With spec.pat.enabled: true it adds an AccessToken MR (the PAT). With spec.pat.pushToAwsSm: true it adds an AWS Secrets Manager Secret MR + an ESO PushSecret Kubernetes Object — pushing the control-plane connection secret's access_token into AWS SM at the canonical path push/<cluster>/<tenant>/<name> per [[reference_aws_sm_push_tag_convention]]. Four resources, one declarative flag.

PAT generation is opt-in by defaultpat.enabled: false means no long-lived token is minted. Adoption of an existing Zitadel machine user uses spec.machineUserId (propagates as crossplane.io/external-name on the underlying MR).

See examples/machineusers/{minimal,with-pat,with-pat-push}.yaml.

Grant

First-class membership relationship that ties a Zitadel User to a Project + Roles. Polymorphic dispatch — caller writes userId + userOrgId + projectId + projectOrgId + roles and the composition picks the right Zitadel mechanism:

  • Same-Org (userOrgId == projectOrgId): composes one user.zitadel.m.crossplane.io/Grant MR (the user's role assignment within the project).
  • Cross-Org (userOrgId != projectOrgId): composes a project.zitadel.m.crossplane.io/Grant (cross-Org Project Grant authorizing the role set for the user's home Org) plus a user.zitadel.m.crossplane.io/Grant with projectGrantId set (the user's role assignment, pulling roles from the granted set). Multi-iter: user/Grant emits once project/Grant is observed.

See examples/grants/{same-org,cross-org}.yaml.

Cross-Stack Integration

The intent is for consumer stacks (gitops/ArgoCD, observe/Grafana, the-website) to wire to AuthStack's status surface rather than configuring OIDC manually. Today, those consumers still need a Zitadel OIDC application created out-of-band (via the Zitadel UI/API) and a client ID/secret provided to them. Once the Zitadel Crossplane provider lands, consumer stacks can declaratively create OIDC applications by referencing status.bootstrap.iamAdminPatSecretRef.

See [[specs/auth-stack-zitadel]] for the design and open questions.

Out of Scope

  • Per-app OIDC client creation (lives with the Zitadel API or the future Zitadel Crossplane provider).
  • Istio RequestAuthentication / AuthorizationPolicy (per-app concern, may land later).
  • Authentik decommission (per-consumer migration tracked separately).

References

  • Spec: [[specs/auth-stack-zitadel]]
  • Task: [[tasks/auth-stack]]
  • Upstream chart: zitadel/zitadel 9.34.1 (ships Zitadel v4)

About

AuthStack — Crossplane Configuration wrapping Zitadel with durable+operational secrets pattern

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors