Hanzo

KMS Integration

How Hanzo IAM stores and reads its secrets from Hanzo KMS

KMS Integration

Hanzo IAM keeps all sensitive configuration — OAuth client secrets, social-provider credentials, and admin passwords — in Hanzo KMS. Nothing sensitive is hard-coded in manifests or environment variables.

How it works

IAM authenticates to KMS with a machine identity and reads its secrets through two complementary paths:

  1. Direct fetch at startup — IAM logs in to KMS (POST /v1/kms/auth/login) with its machine-identity clientId/clientSecret and reads the secrets it needs.
  2. KMSSecret CRD — the kms-operator keeps an iam-secrets Kubernetes Secret continuously in sync as a fallback for workloads that consume secrets as env vars.
┌──────────────────────────────────────────────┐
│            Hanzo KMS (kms.hanzo.ai)           │
│   org: hanzo-iam     env: production          │
│   machine identity: iam-service (read-only)   │
└───────────────┬───────────────────┬───────────┘
        direct login          KMSSecret CRD
        (startup)             (operator sync)
                │                   │
                ▼                   ▼
        ┌──────────────┐   ┌──────────────────┐
        │   IAM pod    │   │ iam-secrets (K8s) │
        └──────────────┘   └──────────────────┘

Machine identity

IAM uses a dedicated, least-privilege machine identity so its secrets are isolated from other services:

FieldValue
Identityiam-service
Accessread-only on the hanzo-iam org
CredentialclientId / clientSecret, mounted from a K8s Secret

The credentials live in a Kubernetes Secret — only the references, never the values, are committed:

apiVersion: v1
kind: Secret
metadata:
  name: iam-kms-auth
  namespace: hanzo
type: Opaque
stringData:
  clientId: ""      # populated out-of-band from KMS/IAM, never committed
  clientSecret: ""

What IAM stores in KMS

IAM's secrets are organized under its hanzo-iam org in KMS:

CategoryExamples
Application client secretsOne per registered <org>-<app> application (e.g. hanzo-cloud, hanzo-chat, hanzo-platform)
Social provider credentialsGitHub, Google, Microsoft, Apple OAuth client IDs and secrets
Admin credentialsThe seeded organization administrator password

Each application's OAuth clientSecret is stored under a key named for its <org>-<app> slug — never inlined into init_data.json or a manifest.

Syncing IAM's secrets to Kubernetes

apiVersion: secrets.lux.network/v1alpha1
kind: KMSSecret
metadata:
  name: iam-kms-sync
  namespace: hanzo
spec:
  hostAPI: https://kms.hanzo.ai
  resyncInterval: 60
  authentication:
    universalAuth:
      credentialsRef:
        secretName: iam-kms-auth
        secretNamespace: hanzo
      secretsScope:
        projectSlug: hanzo-iam      # IAM's own org
        envSlug: production
        secretsPath: /
        keys:
          - IAM_ADMIN_PASSWORD
          - HANZO_CLOUD_CLIENT_SECRET
          - GITHUB_CLIENT_SECRET
  managedSecretReference:
    secretName: iam-secrets
    secretNamespace: hanzo
    secretType: Opaque
    creationPolicy: Orphan

How other services consume an IAM secret

A service that authenticates via IAM OIDC stores its own client_secret in KMS and syncs it the same way. For example, an app reads its OIDC client secret from a synced Secret:

env:
  - name: OIDC_CLIENT_SECRET
    valueFrom:
      secretKeyRef:
        name: app-secrets
        key: OIDC_CLIENT_SECRET

See KMS Service Integration for the full pattern.

Security model

  • No plaintext secrets in git — Kubernetes Secrets are populated from KMS, never committed.
  • Least privilege — IAM's machine identity is read-only and scoped to its own org.
  • Isolation — IAM's secrets live in a separate KMS org from service secrets.
  • Audit trail — every read and write is logged in KMS.

Next Steps

Hanzo KMS architecture and the secret API

How every Hanzo service consumes secrets from KMS

Service-to-KMS authentication

How is this guide?

Last updated on

On this page