Universal Auth
Machine Identity authentication for service-to-KMS communication
Universal Auth
Universal Auth is the authentication method used by Hanzo services to access secrets in KMS. It uses Machine Identities — non-human credentials designed for automated service-to-service communication.
How It Works
┌──────────────┐ clientId + clientSecret ┌──────────────┐
│ Service │ ──────────────────────────────▶ │ KMS API │
│ (Pod) │ │ │
│ │ ◀────────────────────────────── │ │
│ │ access_token (JWT) │ │
│ │ │ │
│ │ Bearer <access_token> │ │
│ │ ──────────────────────────────▶ │ │
│ │ │ │
│ │ ◀────────────────────────────── │ │
│ │ { secrets } │ │
└──────────────┘ └──────────────┘- The kms-operator (or service SDK) presents
clientId+clientSecretto KMS - KMS validates credentials against the Machine Identity record
- KMS returns a short-lived JWT access token
- The token is used to fetch secrets from the authorized project/environment/path
- The token is refreshed automatically before expiry
Machine Identity Types
Shared Identity (Most Services)
A single Machine Identity is shared across all standard services. Each service is scoped to its own path via the KMSSecret CRD's secretsPath field.
# K8s Secret holding the shared credentials
apiVersion: v1
kind: Secret
metadata:
name: universal-auth-credentials
namespace: hanzo
type: Opaque
stringData:
clientId: "<machine-identity-client-id>"
clientSecret: "<machine-identity-client-secret>"Access scope: secrets-639-c project, prod environment, all paths.
Dedicated Identity (IAM)
IAM has its own Machine Identity (iam-service) to isolate its secrets in a separate KMS project.
apiVersion: v1
kind: Secret
metadata:
name: iam-kms-auth
namespace: hanzo
type: Opaque
stringData:
clientId: "<iam-machine-identity-client-id>"
clientSecret: "<iam-machine-identity-client-secret>"Access scope: hanzo-iam project, prod environment, all paths.
Creating a Machine Identity
Via KMS UI
- Navigate to kms.hanzo.ai → Organization Settings → Machine Identities
- Click Create Identity
- Set a descriptive name (e.g.,
my-service) - Under Authentication, enable Universal Auth
- Copy the generated
clientIdandclientSecret - Under Projects, grant access to the appropriate project with the required role (typically Viewer for read-only)
Via API
# Create identity
curl -X POST https://kms.hanzo.ai/api/v1/identities \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"name": "my-service", "role": "member"}'
# Enable Universal Auth
curl -X POST https://kms.hanzo.ai/api/v1/auth/universal-auth/identities/$IDENTITY_ID \
-H "Authorization: Bearer $ADMIN_TOKEN"
# Grant project access
curl -X POST https://kms.hanzo.ai/api/v1/projects/$PROJECT_ID/identity-memberships \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"identityId": "$IDENTITY_ID", "role": "viewer"}'Storing Credentials in K8s
After creating the Machine Identity, store the credentials as a K8s Secret:
kubectl create secret generic my-service-kms-auth \
--namespace hanzo \
--from-literal=clientId="<client-id>" \
--from-literal=clientSecret="<client-secret>"Then reference it in your KMSSecret CRD:
spec:
authentication:
universalAuth:
credentialsRef:
secretName: my-service-kms-auth
secretNamespace: hanzoToken Lifecycle
| Property | Value |
|---|---|
| Token type | JWT |
| Default TTL | 7200 seconds (2 hours) |
| Max TTL | Configurable per identity |
| Refresh | Automatic by kms-operator |
| Revocation | Delete the Machine Identity or its Universal Auth config |
Access Control
Machine Identities support fine-grained access control:
| Role | Capabilities |
|---|---|
| Viewer | Read secrets |
| Developer | Read/write secrets |
| Admin | Full project access including member management |
| No Access | Explicitly deny (overrides inherited permissions) |
Access is scoped per-project. A single identity can have different roles on different projects.
Next Steps
Complete CRD reference
Full service inventory and patterns
How is this guide?
Last updated on