Skip to content

feat: SPIFFE-based Dynamic Client Registration (DCR)#349

Draft
Alan-Cha wants to merge 1 commit into
mainfrom
feat/spiffe-dcr-client-registration
Draft

feat: SPIFFE-based Dynamic Client Registration (DCR)#349
Alan-Cha wants to merge 1 commit into
mainfrom
feat/spiffe-dcr-client-registration

Conversation

@Alan-Cha
Copy link
Copy Markdown
Contributor

Summary

Implements #1421 - Eliminate admin credentials from client registration using SPIFFE JWT-SVID authentication with Keycloak's Dynamic Client Registration (DCR) endpoint.

Problem

Currently, the operator uses admin credentials to register OAuth clients via Keycloak Admin API. This has several security issues:

  • Admin credentials = full realm permissions (create/delete users, realms, clients, roles)
  • Long-lived credentials requiring manual rotation
  • Operator compromise = full realm admin access

Solution

Use the operator's SPIFFE JWT-SVID to authenticate with Keycloak's Dynamic Client Registration (DCR) endpoint instead.

Benefits

Current (Admin Creds) With DCR (This PR)
Admin username/password JWT-SVID
Full realm admin permissions DCR only (create clients)
Long-lived credentials Short-lived, auto-rotates
Manual rotation Automatic (hourly)
Audit trail: "admin" user Audit trail: operator SPIFFE ID

Implementation

New Components

  1. internal/spire/client.go - SPIRE workload API client wrapper

    • Connects to SPIRE agent socket
    • Fetches JWT-SVIDs with specified audience
    • Manages SVID lifecycle
  2. internal/keycloak/dcr.go - DCR client implementation

    • Implements Keycloak DCR endpoint communication
    • Authenticates with Bearer JWT-SVID
    • Registers OAuth clients with limited DCR permissions
  3. Feature flags:

    • --enable-dcr-registration (default: false, experimental)
    • --spire-socket-path (default: unix:///run/spire/sockets/agent.sock)

Updated Components

  • ClientRegistrationReconciler - Refactored to support both paths:
    • registerClientWithDCR() - New DCR path with JWT-SVID
    • registerClientWithAdminCreds() - Legacy path (default)

Usage

Enable DCR (experimental)

# In operator deployment args
- --enable-dcr-registration=true
- --spire-socket-path=unix:///run/spire/sockets/agent.sock

Requirements

  • SPIRE agent running and mounted at socket path
  • Operator pod has SPIFFE identity
  • Keycloak DCR endpoint accepts JWT-SVID authentication (needs testing)

Testing Status

⚠️ Critical Unknown: Does Keycloak's DCR endpoint accept SPIFFE JWT-SVID authentication?

This needs verification before enabling:

# Test DCR with JWT-SVID
kubectl exec -n kagenti-system deployment/kagenti-controller-manager -- \
  cat /opt/jwt_svid.token > /tmp/svid.token

curl -X POST "http://keycloak:8080/realms/kagenti/clients-registrations/default" \
  -H "Authorization: Bearer $(cat /tmp/svid.token)" \
  -H "Content-Type: application/json" \
  -d '{"clientId": "test-client", "clientName": "test"}' -v

Possible outcomes:

  • ✅ 201 Created → Ready to enable
  • ❌ 401 Unauthorized → Need Keycloak config for SPIFFE IdP DCR auth
  • ❌ 403 Forbidden → Need DCR permissions for SPIFFE IdP

Rollout Plan

  1. Phase 1: Test DCR + JWT-SVID compatibility (this PR, draft)
  2. Phase 2: Add E2E tests for DCR flow
  3. Phase 3: Enable in staging with feature flag
  4. Phase 4: Graduate from experimental, make default
  5. Phase 5: Deprecate admin credential path

Backward Compatibility

  • ✅ Default behavior unchanged (uses admin credentials)
  • ✅ Opt-in via feature flag
  • ✅ No breaking changes to existing deployments

Related

Assisted-By: Claude Code

Implements issue #1421 - eliminate admin credentials from client
registration using SPIFFE JWT-SVID authentication.

Changes:
- Add internal/spire/client.go: SPIRE workload API client wrapper
- Add internal/keycloak/dcr.go: DCR client for JWT-SVID authentication
- Add --enable-dcr-registration flag (disabled by default, experimental)
- Add --spire-socket-path flag for SPIRE agent socket location
- Update ClientRegistrationReconciler to support both DCR and admin paths
- Refactor registration logic into registerClientWithDCR() and
  registerClientWithAdminCreds() methods

DCR benefits over admin credentials:
- Short-lived JWT-SVID tokens (auto-rotates hourly)
- Limited DCR permissions instead of full realm admin
- Better audit trail (operator SPIFFE ID vs generic 'admin' user)
- No manual credential rotation required

When --enable-dcr-registration=true:
1. Operator fetches JWT-SVID from SPIRE
2. Uses JWT-SVID to authenticate with Keycloak DCR endpoint
3. Registers OAuth client with limited DCR permissions
4. No admin credentials needed

When false (default):
- Uses existing admin credential path from kagenti-system namespace
- Backward compatible with existing deployments

Note: DCR requires testing with Keycloak to verify JWT-SVID acceptance
at the DCR endpoint. This is currently unverified and marked experimental.

Assisted-By: Claude Code
Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New /:ToDo

Development

Successfully merging this pull request may close these issues.

2 participants