- Add Workspace domain (entity, repository, service, handler, DTO) - Add multi-tenant K8s client with tenant binding and quota management - Add K8s diagnostics client (instance diagnostics) - Add authorization middleware (authz package) - Restructure frontend to feature-based architecture (features/) - Add User Management page in configuration - Add AccessDenied page and route guards - Refactor shared components (form inputs, layout, UI) - Update Tailwind config for new design system - Add comprehensive documentation (docs/, tasks/, plans) - Improve cluster service with better kubeconfig handling - Add tests for crypto, config, helm client, tenant binding
5.4 KiB
QA Report: Permission Isolation & Multi-Tenancy Testing — test-user-c
Tester: test-user-c (role: user)
Date: 2026-05-11
Environment: http://10.6.80.114:18080
Summary
Test-user-c is a standard user role with namespace ocdp-u-test-c, workspace 71459030-7166-4c79-b53c-81c61da4c313. Permissions follow the manage_own / view pattern — no admin-level permissions.
Test Results
1. Login & Basic Access ✅
| Test | Result | Notes |
|---|---|---|
| POST /auth/login | ✅ Pass | Token issued, role=user, workspace/namespace correctly assigned |
| GET /auth/me | ✅ Pass | Returns correct user profile with permissions |
| GET /clusters | ✅ Pass | Sees all global_shared clusters (k8s, k3s) |
| GET /registries | ✅ Pass | Sees all global_shared registries (harbor) |
2. Admin Endpoint Protection
| Test | Result | Notes |
|---|---|---|
| GET /api/v1/users | ✅ 403 Forbidden | Properly blocked — permission denied |
| POST /auth/register | ✅ 403 Forbidden | Cannot register new users as non-admin |
| GET /api/v1/admin/* | ✅ 404 | Admin route prefix doesn't exist (not a bypass risk) |
3. Frontend Access
| Test | Result | Notes |
|---|---|---|
| GET /configuration/users | ⚠️ 200 (OK) | SPA returns index.html — expected. Auth is enforced via API, not routes. |
| GET /configuration/clusters | ⚠️ 200 (OK) | Same — SPA behavior. |
| GET /configuration/registries | ⚠️ 200 (OK) | Same. |
Risk: Low. This is standard SPA behavior. Authorization is enforced at the API level. However, if the frontend relies solely on hiding UI elements rather than checking permissions, users who manually navigate could see empty/error states.
4. Namespace Isolation Enforcement
| Test | Result | Notes |
|---|---|---|
Deploy with namespace: ocdp-u-test-a |
⚠️ Silently overridden | Server ignored requested namespace and used ocdp-u-test-c instead. No warning or error returned. |
| PATCH to change namespace | ✅ 404 | PATCH endpoint doesn't exist — namespace cannot be changed after creation |
🔴 Bug: Silent namespace override (Low severity) When a user specifies a namespace that doesn't belong to them in the instance creation request, the server silently overrides it with the user's own namespace. This is secure (prevents cross-namespace deployment) but:
- The user receives HTTP 200 with the overridden value — no indication that their request was modified
- The response does not differentiate between "user's own namespace" and "requested namespace"
- This could lead to user confusion about where their resources were actually deployed
- It's unclear whether the user's Helm values also get silently overridden (e.g., the
values.namespacefield)
5. Resource Isolation
| Test | Result | Notes |
|---|---|---|
| GET instances with other workspaceId query param | ✅ Isolated | Returns only own instances (workspaceId filter is server-enforced) |
| DELETE on own instance | ⚠️ Async deletion | Returns HTTP 404 on DELETE itself, but instance transitions to pending-delete then disappears |
🔴 Bug: DELETE returns 404 on success (Medium severity)
When deleting an instance via DELETE /clusters/{clusterId}/instances/{instanceId}:
- The instance transitions to
pending-deletestatus - But the HTTP response status code is 404 rather than 200/202/204
- The first raw DELETE call returns an empty body (causing JSON parse errors)
- This is an API inconsistency — async deletions should return HTTP 202 Accepted
6. Monitoring & Other Endpoints
| Test | Result | Notes |
|---|---|---|
| GET /monitoring/clusters/.../pods | ✅ 404 | Monitoring endpoints not implemented for this cluster type |
| POST /kubeconfig | ✅ 404 | Kubeconfig endpoint not implemented |
These endpoints return 404 which is acceptable behavior for features not yet implemented.
Security Assessment
Works as Intended ✅
- Admin endpoints (
/users,/auth/register) properly return 403 - User cannot access other users' instances via workspaceId manipulation
- User cannot deploy into other users' Kubernetes namespaces
- No PATCH/PUT verbs available to modify existing instance namespaces
- No admin-specific route paths leak data
Bugs Found
-
DELETE returns 404 on successful async deletion (Medium)
- Endpoint:
DELETE /clusters/{id}/instances/{id} - After call, instance status becomes
pending-deleteand eventually disappears - But the HTTP response is
404with empty body - Expected:
202 Acceptedwith astatus: "deleted"or similar response - Risk: Clients interpreting HTTP 404 as "not found" will retry or report errors incorrectly
- Endpoint:
-
Silent namespace override without user feedback (Low)
- Endpoint:
POST /clusters/{id}/instances - When requesting deployment into another user's namespace, the server silently uses the caller's namespace
- No warning, no error, no indication in the response
- Expected: Either
403 Forbiddenwith "cannot deploy into namespace owned by another user" or a response field indicating the override occurred - Risk: Low for security (the override correctly prevents cross-tenant deployment), but could cause user confusion
- Endpoint:
No Critical Vulnerabilities Found
- No privilege escalation vectors identified
- No data leakage across workspaces
- No ability to access or manipulate other users' resources