Commit Graph

8 Commits

Author SHA1 Message Date
hsiegeln
9d2e6f30a7 Move OIDC config from env vars to database with admin API
All checks were successful
CI / build (push) Successful in 1m9s
CI / docker (push) Successful in 41s
CI / deploy (push) Successful in 2m11s
OIDC provider settings (issuer, client ID/secret, roles claim) are
now stored in ClickHouse and managed via admin REST API at
/api/v1/admin/oidc. This allows runtime configuration from the UI
without server restarts.

- New oidc_config table (ReplacingMergeTree, singleton row)
- OidcConfig record + OidcConfigRepository interface in core
- ClickHouseOidcConfigRepository implementation
- OidcConfigAdminController: GET/PUT/DELETE config, POST test
  connectivity, client_secret masked in responses
- OidcTokenExchanger: reads config from DB, invalidateCache()
  on config change
- OidcAuthController: always registered (no @ConditionalOnProperty),
  returns 404 when OIDC not configured
- Startup seeder: env vars seed DB on first boot only, then admin
  API takes over
- HOWTO.md updated with admin OIDC config API examples

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:01:05 +01:00
hsiegeln
a4de2a7b79 Add RBAC with role-based endpoint authorization and OIDC support
Some checks failed
CI / build (push) Successful in 1m19s
CI / docker (push) Successful in 1m38s
CI / deploy (push) Has been cancelled
Implement three-phase security upgrade:

Phase 1 - RBAC: Extend JWT with roles claim, populate Spring
GrantedAuthority in filter, enforce role-based access (AGENT for
data/heartbeat/SSE, VIEWER+ for search/diagrams, OPERATOR+ for
commands, ADMIN for user management). Configurable JWT secret via
CAMELEER_JWT_SECRET env var for token persistence across restarts.

Phase 2 - User persistence: ClickHouse users table with
ReplacingMergeTree, UserRepository interface + ClickHouse impl,
UserAdminController for CRUD at /api/v1/admin/users. Local login
upserts user on each authentication.

Phase 3 - OIDC: Token exchange flow where SPA sends auth code,
server exchanges it server-side (keeping client_secret secure),
validates id_token via JWKS, resolves roles (DB override > OIDC
claim > default), issues internal JWT. Conditional on
CAMELEER_OIDC_ENABLED=true. Uses oauth2-oidc-sdk for standards
compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:35:45 +01:00
hsiegeln
4253751ef1 Redirect to login on expired/invalid auth
All checks were successful
CI / build (push) Successful in 1m1s
CI / docker (push) Successful in 46s
CI / deploy (push) Successful in 29s
Backend now returns 401 instead of 403 for unauthenticated requests
via HttpStatusEntryPoint. UI middleware handles both 401 and 403,
triggering token refresh and redirecting to /login on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 17:39:29 +01:00
hsiegeln
3eb83f97d3 Add React UI with Execution Explorer, auth, and standalone deployment
Some checks failed
CI / build (push) Failing after 1m53s
CI / docker (push) Has been skipped
CI / deploy (push) Has been skipped
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
  system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
  expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
  JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
  FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
  hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
  NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
  resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
  deploy step for UI, UI credential secrets

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
hsiegeln
539b85f307 test(04-02): adapt all ITs for JWT auth and add 4 security integration tests
- Replace TestSecurityConfig permit-all with real SecurityConfig active in tests
- Create TestSecurityHelper for JWT-authenticated test requests
- Update 15 existing ITs to use JWT Bearer auth and bootstrap token headers
- Add SecurityFilterIT: protected/public endpoint access control (6 tests)
- Add BootstrapTokenIT: registration requires valid bootstrap token (4 tests)
- Add RegistrationSecurityIT: registration returns tokens + public key (3 tests)
- Add JwtRefreshIT: refresh flow with valid/invalid/mismatched tokens (5 tests)
- Add /error to SecurityConfig permitAll for proper error page forwarding
- Exclude register and refresh paths from ProtocolVersionInterceptor
- All 91 tests pass (18 new security + 73 existing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:38:28 +01:00
hsiegeln
387e2e66b2 feat(04-02): wire Spring Security filter chain with JWT auth, bootstrap registration, and refresh endpoint
- JwtAuthenticationFilter extracts JWT from Authorization header or query param, validates via JwtService
- SecurityConfig creates stateless SecurityFilterChain with public/protected endpoint split
- AgentRegistrationController requires bootstrap token, returns accessToken + refreshToken + serverPublicKey
- New POST /agents/{id}/refresh endpoint issues new access JWT from valid refresh token

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:13:53 +01:00
hsiegeln
ac9e8ae4dd feat(04-01): implement security service foundation
- JwtServiceImpl: HMAC-SHA256 via Nimbus JOSE+JWT with ephemeral 256-bit secret
- Ed25519SigningServiceImpl: JDK 17 KeyPairGenerator with ephemeral keypair
- BootstrapTokenValidator: constant-time comparison with dual-token rotation
- SecurityBeanConfig: bean wiring with fail-fast validation for CAMELEER_AUTH_TOKEN
- SecurityProperties: config binding for token expiry and bootstrap tokens
- TestSecurityConfig: permit-all filter chain to keep existing tests green
- application.yml: security config with env var mapping
- All 18 security unit tests pass, all 71 tests pass in full verify

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:08:30 +01:00
hsiegeln
51a02700dd test(04-01): add failing tests for security services
- JwtService: 7 tests for access/refresh token creation and validation
- Ed25519SigningService: 5 tests for keypair, signing, verification
- BootstrapTokenValidator: 6 tests for token matching and rotation
- Core interfaces and stub implementations (all throw UnsupportedOperationException)
- Added nimbus-jose-jwt and spring-boot-starter-security dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:58:59 +01:00