Files
vctp2/todo.md
T
nathan ae3e2be89a
continuous-integration/drone/push Build is passing
add auth support
2026-04-17 13:19:08 +10:00

5.6 KiB

VCTP Auth Design TODO (LDAP + JWT)

1. Goal

Add authentication and authorization to VCTP for sensitive endpoints, using the LDAP bind + JWT pattern from cbs2 as a reference, adapted to VCTP's net/http architecture.

2. Reference Findings from cbs2

2.1 Where auth lives in cbs2

  • Login handler: /tmp/cbs2/server/handler/auth.go
  • JWT middleware: /tmp/cbs2/server/handler/middlewares.go
  • Token utilities: /tmp/cbs2/utils/token/token.go
  • LDAP bind + group lookup: /tmp/cbs2/internal/ldap/ldap.go
  • Route protection split (public vs protected): /tmp/cbs2/server/router/router.go
  • Settings fields for LDAP/JWT: /tmp/cbs2/internal/settings/settings.go and /tmp/cbs2/src/cbs.yml

2.2 Pattern to reuse

  • LDAP username/password bind for authentication.
  • LDAP group membership check for authorization at login.
  • Signed JWT access token with expiry.
  • Middleware that validates Authorization: Bearer <token>.
  • Router-level grouping for protected routes.

2.3 Things to improve (do not copy as-is)

  • Avoid hardcoded fallback JWT secret (present in cbs2 middleware).
  • Avoid logging sensitive token/key values.
  • Avoid weak/ambiguous claim model; use explicit issuer/audience/subject/exp/iat.
  • Keep strict method/endpoint policy in one place instead of ad-hoc checks.

3. Proposed VCTP Auth Architecture

3.1 New packages/modules

  1. internal/auth/ldap.go
  • LDAP setup/connection helpers.
  • AuthenticateAndFetchGroups(username, password) ([]string, error).
  1. internal/auth/jwt.go
  • JWT issue and verify.
  • Claims struct with:
    • sub (username)
    • roles (derived roles)
    • groups (optional raw LDAP groups)
    • iss, aud, iat, exp, nbf, jti
  1. server/middleware/auth.go
  • RequireAuth(...) for token validation.
  • RequireRole(...) for endpoint authorization.
  • Context injection for user identity and roles.
  1. server/handler/auth.go
  • POST /api/auth/login
  • Optional GET /api/auth/me for debugging/whoami.

3.2 Route protection model

Define a central policy map in router startup (single source of truth):

  • Public (no auth):
    • /assets/*, /favicon*, /swagger* (optional decision), / (optional decision)
  • Authenticated read-only (viewer role):
    • /vcenters*, /snapshots/*, /vm/trace, /api/report/*, /metrics (optional decision)
  • Privileged write/admin (admin role):
    • /api/snapshots/* mutating endpoints
    • /api/vcenters/cache/rebuild
    • /api/encrypt
    • legacy mutating endpoints (/api/event/*, /api/import/vm, /api/inventory/vm/*, /api/cleanup/*)
  • Debug endpoints (/debug/pprof/*):
    • disabled by default via config
    • if enabled, require admin

4. VCTP Settings Additions

Add under settings: in internal/settings/settings.go and src/vctp.yml:

  1. auth_enabled: false
  2. auth_mode: "disabled" (disabled|optional|required)
  3. auth_jwt_signing_key: "" (base64-encoded, required when auth enabled)
  4. auth_token_lifespan_minutes: 120
  5. auth_jwt_issuer: "vctp"
  6. auth_jwt_audience: "vctp-api"
  7. auth_clock_skew_seconds: 60
  8. ldap_groups: []
  9. ldap_bind_address: ""
  10. ldap_base_dn: ""
  11. ldap_trust_cert_file: ""
  12. ldap_disable_validation: false
  13. ldap_insecure: false
  14. enable_pprof: false

5. Role Mapping

Use LDAP group DN mapping to roles (config-driven):

  • auth_group_role_mappings map/list, e.g.:
    • group DN -> admin
    • group DN -> viewer

Default behavior:

  • No mapped group: deny login.
  • Multiple matches: union roles.

6. API Contract

6.1 Login

POST /api/auth/login

  • Request: { "username": "...", "password": "..." }
  • Success: { "access_token": "...", "expires_at": <unix>, "token_type": "Bearer" }
  • Failure: 401 with generic message (no user/group leakage)

6.2 Auth header

  • Authorization: Bearer <jwt>

6.3 Error behavior

  • Missing/invalid token: 401
  • Valid token but insufficient role: 403

7. Rollout Plan

Phase 1: Foundation

  1. Implement settings fields and validation.
  2. Implement LDAP and JWT services.
  3. Add /api/auth/login.
  4. Add unit tests for token generation/validation and LDAP auth abstraction.

Phase 2: Middleware + policy

  1. Add auth middleware for net/http.
  2. Protect sensitive routes via central policy map.
  3. Keep auth_mode=optional initially for safe rollout.

Phase 3: Enforce + harden

  1. Switch production to auth_mode=required.
  2. Gate/disable pprof by config.
  3. Add structured audit logs for auth events.
  4. Update Swagger security docs and README.

8. Validation and Tests

  1. Unit tests
  • JWT: expired token, wrong signature, wrong issuer/audience, clock skew.
  • Role extraction and mapping.
  1. Integration tests (handler/middleware)
  • Unauthenticated access blocked on protected endpoints.
  • Viewer can read but cannot mutate.
  • Admin can mutate.
  1. Regression checks
  • Existing legacy endpoint gating (enable_legacy_api) still behaves correctly after auth layering.

9. Open Decisions

  1. Should /metrics require auth in your deployment? No there is no need for auth for this endpoint
  2. Should UI pages (/, /vcenters, /snapshots/*, /vm/trace) require login or stay public? These should stay public
  3. Should Swagger UI be public, authenticated, or disabled in production? These should stay public
  4. Do you want short-lived access tokens only, or access + refresh token flow? Short lived access tokens please, 2 hours is good enough

10. Implementation Notes for VCTP

  1. Reuse cbs2 LDAP flow shape, but avoid its fallback secret behavior.
  2. Keep all secret material redacted in logs.
  3. Validate required auth settings at startup when auth_enabled=true.
  4. Prefer fail-closed: if auth is enabled and misconfigured, abort startup.