Skip to content

CLI: agent public-key registration against the agent-identity registry (defang identity) #2166

Description

@defangdevs

Goal

Let the CLI register an agent's public key with the Defang agent-identity registry (DefangLabs/openauth PR 8 — OpenAuth as a per-tenant OIDC key registry), so AI agents can federate into clouds (AWS AssumeRoleWithWebIdentity, etc.) with locally-held keys instead of long-lived cloud credentials.

Registry contract (from the openauth PR)

  • POST https://<tenant>.<auth-domain>/keys — bearer-authenticated; body {project_id, stack_id, jwk, pop_jwt, ttl_seconds?}; pop_jwt is a short-lived JWT {iat, jwk_thumb} self-signed by the key being registered (proof of possession); kid is derived server-side from the RFC 7638 thumbprint; idempotent re-registration; 409 if the same JWK is used for a different (project, stack).
  • GET /keys — list registered keys.
  • DELETE /keys/:kid — revoke.

Proposed CLI design

New defang identity command group (not defang agentpkg/agent is already the AI chat agent):

  • defang identity register [--ttl …] — generate an RS256 keypair if absent (private key never leaves the machine), sign the PoP JWT, POST to the tenant registry, print the kid.
  • defang identity list
  • defang identity revoke <kid>
  • (follow-up) defang identity mint --aud sts.amazonaws.com for the runtime half.

Integration points (all plumbing already exists):

  • Bearer token: the stored defang login token (pkg/tokenstore, GetExistingToken).
  • Tenant URL: issuer apex from DEFANG_ISSUER (default https://auth.defang.io) + tenant label from WhoAmI (the tenant is the subdomain).
  • Project/stack: LoadProjectNameWithFallback + stacks.Manager, same as other commands.
  • Key storage: ~/.local/state/defang/identity/<tenant>/<project>/<stack>/private.pem (0600), one key per (project, stack) since the registry enforces stack isolation via 409.
  • Crypto: golang-jwt/jwt/v5 (already direct) for the PoP JWT; go-jose/v4 (already indirect → promote) for JWK marshaling + RFC 7638 thumbprint; stdlib crypto/rsa keygen. RS256 because AWS OIDC federation does not support Ed25519. No new dependencies.
  • Transport: direct REST to the issuer (like the login flow in pkg/auth/client.go), not a Fabric RPC — the registry lives in OpenAuth, not Fabric.

New code: pkg/identity/ (keygen/PoP/HTTP client) + thin src/cmd/cli/command/identity.go.

Blockers / open questions

  1. Gated on DefangLabs/openauth PR 8 landing and the tenant-enabled issuer being deployed at auth.defang.io (production tenant onboarding was explicitly out of scope there).
  2. Should /keys accept plain defang login access tokens, or require a scoped token from defang token (pkg/scope)? A dedicated identity:write scope would be tighter.
  3. Key rotation UX: register on an existing key is idempotent; rotating means keygen + register + revoke old — worth a defang identity rotate convenience?

Draft implementation to follow as a PR from the defangdevs fork.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions