Files
harmony/examples/harmony_sso
Jean-Gabriel Gill-Couture 466a8aafd1
Some checks failed
Run Check Script / check (pull_request) Failing after 12s
feat(postgresql): add wait_for_ready option to PostgreSQLConfig
Add wait_for_ready field (default: true) to PostgreSQLConfig. When
enabled, K8sPostgreSQLInterpret waits for the cluster's -rw service
to exist after applying the Cluster CR, ensuring callers like
get_endpoint() succeed immediately.

This eliminates the retry loop in the harmony_sso example's
deploy_zitadel() -- ZitadelScore now deploys in a single pass because
the PG service is guaranteed to exist before Zitadel's Helm chart
init job tries to connect.

The deploy_zitadel function shrinks from a 5-attempt retry loop to a
simple score.interpret() call.
2026-03-30 08:45:49 -04:00
..

Harmony SSO Example

Deploys Zitadel (identity provider) and OpenBao (secrets management) on a local k3d cluster, then demonstrates using them as harmony_config backends for shared config and secret management.

Prerequisites

  • Docker running
  • Ports 8080 and 8200 free
  • /etc/hosts entries (or use a local DNS resolver):
    127.0.0.1  sso.harmony.local
    127.0.0.1  bao.harmony.local
    

Usage

Full deployment

# Deploy everything (OpenBao + Zitadel)
cargo run -p example-harmony-sso

# OpenBao only (faster, skip Zitadel)
cargo run -p example-harmony-sso -- --skip-zitadel

Config storage demo (token auth)

After deployment, run the config demo to verify harmony_config works with OpenBao:

cargo run -p example-harmony-sso -- --demo

This writes and reads a SsoExampleConfig through the ConfigManager chain (EnvSource -> StoreSource<OpenbaoSecretStore>), demonstrating environment variable overrides and persistent storage in OpenBao KV v2.

SSO device flow demo

Requires a Zitadel application configured for device code grant:

HARMONY_SSO_CLIENT_ID=<zitadel-app-client-id> \
  cargo run -p example-harmony-sso -- --sso-demo

Cleanup

cargo run -p example-harmony-sso -- --cleanup

What gets deployed

Component Namespace Access
OpenBao (standalone, file storage) openbao http://bao.harmony.local:8200
Zitadel (with CNPG PostgreSQL) zitadel http://sso.harmony.local:8080

OpenBao configuration

  • Auth methods: userpass, JWT
  • Secrets engine: KV v2 at secret/
  • Policy: harmony-dev grants CRUD on secret/data/harmony/*
  • Userpass credentials: harmony / harmony-dev-password
  • JWT auth: configured with Zitadel as OIDC provider, role harmony-developer
  • Unseal keys: saved to ~/.local/share/harmony/openbao/unseal-keys.json

Architecture

Developer CLI
  |
  |-- harmony_config::ConfigManager
  |     |-- EnvSource (HARMONY_CONFIG_* env vars)
  |     |-- StoreSource<OpenbaoSecretStore>
  |           |-- Token auth (OPENBAO_TOKEN)
  |           |-- Cached token validation
  |           |-- Zitadel OIDC device flow (RFC 8628)
  |           |-- Userpass fallback
  |
  v
k3d cluster (harmony-example)
  |-- OpenBao (KV v2 secrets engine)
  |     |-- JWT auth -> validates Zitadel id_tokens
  |     |-- userpass auth -> dev credentials
  |
  |-- Zitadel (OpenID Connect IdP)
        |-- Device authorization grant
        |-- Federated login (Google, GitHub, Entra ID)