Hanzo

KMS Integration

How Hanzo IAM uses KMS for secure secret management

KMS Integration

Hanzo IAM stores all sensitive configuration — OAuth client secrets, social provider credentials, admin passwords — in Hanzo KMS. No secrets are hardcoded in deployment manifests or environment variables.

Architecture

┌──────────────────────────────────────────────────────────────┐
│                    Hanzo KMS (kms.hanzo.ai)                  │
│                                                              │
│  Project: hanzo-iam                                          │
│  Environment: prod                                           │
│  Secrets: 23 entries (client secrets, OAuth, admin creds)    │
│                                                              │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  Machine Identity: iam-service                          │ │
│  │  Auth: Universal Auth (clientId + clientSecret)         │ │
│  │  Role: Viewer on hanzo-iam project                      │ │
│  └─────────────────────────────────────────────────────────┘ │
└──────────────┬───────────────────────────┬───────────────────┘
               │                           │
     Direct SDK fetch            KMSSecret CRD (backup)
     (startup time)              (kms-operator sync)
               │                           │
               ▼                           ▼
┌──────────────────────┐    ┌──────────────────────────┐
│     IAM Pod          │    │   iam-secrets K8s Secret  │
│  (reads from KMS     │    │   (auto-synced every 60s) │
│   via kms-go SDK)    │    │                           │
└──────────────────────┘    └──────────────────────────┘

IAM uses two complementary mechanisms:

  1. Direct SDK fetch — At startup, IAM uses the kms-go SDK to pull secrets directly from KMS. This is the primary path.
  2. KMSSecret CRD — The kms-operator syncs secrets to a iam-secrets K8s Secret every 60 seconds as a backup/fallback.

Machine Identity Setup

IAM authenticates to KMS using a Machine Identity with Universal Auth credentials:

FieldValue
Identity nameiam-service
Auth methodUniversal Auth
Project accesshanzo-iam (Viewer)
Credential mount/etc/kms/auth/clientId, /etc/kms/auth/clientSecret

The credentials are stored in a K8s Secret and mounted as files:

apiVersion: v1
kind: Secret
metadata:
  name: iam-kms-auth
  namespace: hanzo
type: Opaque
stringData:
  clientId: ""      # KMS Machine Identity Client ID
  clientSecret: ""  # KMS Machine Identity Client Secret

Secrets Inventory

The hanzo-iam KMS project contains 23 secrets:

Application Client Secrets

Every IAM-registered application has its OAuth client secret stored in KMS:

KMS KeyApplication
IAM_APP_HANZO_CLIENT_SECRETapp-hanzo (hanzo.ai)
IAM_APP_CLOUD_CLIENT_SECRETapp-cloud (cloud.hanzo.ai)
IAM_APP_COMMERCE_CLIENT_SECRETapp-commerce (api.hanzo.ai)
IAM_APP_CONSOLE_CLIENT_SECRETapp-console (console.hanzo.ai)
IAM_APP_CHAT_CLIENT_SECRETapp-chat (hanzo.chat)
IAM_APP_PLATFORM_CLIENT_SECRETapp-platform (platform.hanzo.ai)
IAM_APP_ZOO_CLIENT_SECRETapp-zoo (zoo.ngo)
IAM_APP_LUX_CLIENT_SECRETapp-lux (lux.network)
IAM_APP_PARS_CLIENT_SECRETapp-pars (pars.ai)
IAM_APP_HANZOBOT_CLIENT_SECRETapp-hanzobot (app.hanzo.bot)
IAM_APP_BOOTNODE_CLIENT_SECRETapp-bootnode
IAM_APP_HANZO_WEB3_CLIENT_SECRETapp-hanzo-web3
IAM_APP_LUX_WEB3_CLIENT_SECRETapp-lux-web3
IAM_APP_ZOO_WEB3_CLIENT_SECRETapp-zoo-web3
IAM_APP_TEAM_CLIENT_SECRETapp-team
IAM_APP_ADNEXUS_CLIENT_SECRETapp-adnexus
IAM_APP_ZT_CONSOLE_CLIENT_SECRETapp-zt-console

Social Provider Credentials

KMS KeyProvider
IAM_GITHUB_CLIENT_IDGitHub OAuth
IAM_GITHUB_CLIENT_SECRETGitHub OAuth
IAM_GOOGLE_CLIENT_IDGoogle OAuth
IAM_GOOGLE_CLIENT_SECRETGoogle OAuth

Admin Credentials

KMS KeyPurpose
IAM_ADMIN_PASSWORDBuilt-in admin account
IAM_Z_HANZO_PASSWORDHanzo org admin
IAM_Z_LUX_PASSWORDLux org admin

KMSSecret CRD Configuration

The backup sync uses the KMSSecret custom resource:

apiVersion: secrets.lux.network/v1alpha1
kind: KMSSecret
metadata:
  name: iam-kms-sync
  namespace: hanzo
spec:
  hostAPI: http://kms.hanzo.svc.cluster.local/api
  resyncInterval: 60
  authentication:
    universalAuth:
      credentialsRef:
        secretName: iam-kms-auth
        secretNamespace: hanzo
      secretsScope:
        projectSlug: hanzo-iam
        envSlug: prod
        secretsPath: /
  managedSecretReference:
    secretName: iam-secrets
    secretNamespace: hanzo
    secretType: Opaque

Key fields:

FieldDescription
hostAPIKMS internal endpoint (in-cluster, no TLS needed)
resyncIntervalSync frequency in seconds
credentialsRefK8s secret containing Universal Auth credentials
secretsScopeKMS project, environment, and path to sync
managedSecretReferenceTarget K8s Secret to write synced values into

Adding a New Application Secret

When registering a new application in IAM:

  1. Create the secret in KMS at kms.hanzo.ai under the hanzo-iam project:
    Key: IAM_APP_MYAPP_CLIENT_SECRET
    Value: <generated-secret>
    Environment: prod
  2. Reference it in IAM's init_data.json (or update via API):
    {
      "name": "app-myapp",
      "clientSecret": "${IAM_APP_MYAPP_CLIENT_SECRET}"
    }
  3. The KMSSecret CRD auto-syncs the new secret to the iam-secrets K8s Secret within 60 seconds.

How Other Services Consume IAM Secrets

Each service that authenticates via IAM OIDC stores its own copy of the client secret in KMS. For example, Hanzo Chat stores OPENID_CLIENT_SECRET under the /chat path in the shared secrets-639-c project:

# chat/kms-secrets.yaml
apiVersion: secrets.lux.network/v1alpha1
kind: KMSSecret
metadata:
  name: chat-kms-sync
spec:
  authentication:
    universalAuth:
      credentialsRef:
        secretName: universal-auth-credentials
      secretsScope:
        projectSlug: secrets-639-c
        envSlug: prod
        secretsPath: /chat
  managedSecretReference:
    secretName: chat-secrets

The deployment then references the synced K8s Secret:

env:
  - name: OPENID_CLIENT_SECRET
    valueFrom:
      secretKeyRef:
        name: chat-secrets
        key: OPENID_CLIENT_SECRET

This pattern is consistent across all services — see KMS Service Integration for the full list.

Security Model

  • No plaintext secrets in manifests — All K8s Secrets are populated by KMS, never checked into git
  • Least-privilege access — IAM's Machine Identity has Viewer (read-only) access to its own project only
  • Separate projects — IAM secrets (hanzo-iam) are isolated from service secrets (secrets-639-c)
  • In-cluster communication — KMS API is accessed via kms.hanzo.svc.cluster.local, never exposed externally for secret sync
  • 60-second resync — Rotated secrets propagate to K8s within one minute
  • Audit trail — All secret reads/writes are logged in KMS audit log

Next Steps

Hanzo KMS architecture and features

How all Hanzo services consume secrets from KMS

Register and configure IAM applications

How is this guide?

Last updated on

On this page