refactor: full-stack restructure with multi-tenancy, workspace management, and K8s diagnostics

- 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
This commit is contained in:
Ivan087
2026-05-12 16:15:14 +08:00
parent c5e51ed069
commit 7f238a3168
172 changed files with 15703 additions and 3162 deletions

View File

@ -0,0 +1,284 @@
# OCDP Security Audit Report
**Date:** 2026-05-11
**Target:** http://10.6.80.114:18080
**API Base:** http://10.6.80.114:18080/api/v1
---
## Finding 1: User Enumeration via Login Error Messages
| Field | Value |
|-------|-------|
| **Test** | Authentication Error Disclosure |
| **Severity** | **Medium** |
| **Endpoint** | `POST /api/v1/auth/login` |
| **Status** | Confirmed |
### What I Did
```bash
# Non-existent user
curl -s -X POST http://10.6.80.114:18080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"nonexistent_user_xyz","password":"test123"}'
# Existing user with wrong password
curl -s -X POST http://10.6.80.114:18080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"wrongpassword"}'
```
### Expected
Both requests should return the same generic error message (e.g., "Invalid credentials") to prevent username enumeration.
### Actual
- Non-existent user: `{"error":"Login failed","message":"user not found","code":401}`
- Existing user: `{"error":"Login failed","message":"invalid password","code":401}`
The error messages are different, allowing an attacker to determine whether a username exists in the system.
### Impact
An attacker can enumerate valid usernames by observing the error message difference. This is the first step in a targeted brute force or credential stuffing attack.
### Recommendation
Return identical error messages for both cases, e.g., `"Invalid username or password"`.
---
## Finding 2: No Rate Limiting on Login Endpoint
| Field | Value |
|-------|-------|
| **Test** | Brute Force Protection |
| **Severity** | **Medium** |
| **Endpoint** | `POST /api/v1/auth/login` |
| **Status** | Confirmed |
### What I Did
```bash
for i in $(seq 1 10); do
curl -s -o /dev/null -w "%{http_code}" \
-X POST http://10.6.80.114:18080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"wrongpassword"}'
done
```
### Expected
After a threshold (e.g., 5 failed attempts), the server should return HTTP 429 Too Many Requests or temporarily lock the account.
### Actual
All 10 rapid sequential attempts returned HTTP 401. No rate limiting, no account lockout, no progressive delay.
### Impact
An attacker can brute force passwords without restriction. Combined with Finding 1 (user enumeration), the attack surface is increased.
### Recommendation
- Implement rate limiting on the login endpoint (e.g., max 5 attempts per minute per IP).
- Consider account lockout after N failed attempts.
- Add progressive response delays after repeated failures.
---
## Finding 3: Server Version Disclosure
| Field | Value |
|-------|-------|
| **Test** | Information Disclosure |
| **Severity** | **Low** |
| **Endpoint** | All (HTTP response headers) |
| **Status** | Confirmed |
### What I Did
```bash
curl -s -D - http://10.6.80.114:18080/ | head -10
```
### Expected
Server header should be generic (e.g., `Server: nginx`) or removed entirely.
### Actual
```http
Server: nginx/1.27.5
```
### Impact
Knowing the exact nginx version helps attackers target known vulnerabilities for that specific version.
### Recommendation
Disable or obfuscate the Server header in nginx configuration:
```nginx
server_tokens off;
```
---
## Finding 4: Permissive CORS Policy
| Field | Value |
|-------|-------|
| **Test** | CORS Misconfiguration |
| **Severity** | **Low** |
| **Endpoint** | All API endpoints |
| **Status** | Confirmed |
### What I Did
```bash
curl -s -D - http://10.6.80.114:18080/api/v1/auth/login \
-X POST -H "Content-Type: application/json" \
-d '{"username":"test","password":"test"}'
```
### Expected
CORS `Access-Control-Allow-Origin` should be restricted to the application's origin (e.g., `http://10.6.80.114:18080`) rather than allowing all origins.
### Actual
```http
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
Access-Control-Max-Age: 86400
```
### Impact
Any website can make cross-origin requests to the API. If a user is logged in, a malicious site could potentially make authenticated API calls on their behalf (CSRF-style attack, though mitigated by the Bearer token requirement).
### Recommendation
Restrict `Access-Control-Allow-Origin` to the specific frontend origin(s) instead of `*`.
---
## Finding 5: Missing Security Headers
| Field | Value |
|-------|-------|
| **Test** | Security Headers Audit |
| **Severity** | **Low** |
| **Endpoint** | All |
| **Status** | Confirmed |
### What I Did
```bash
curl -s -D - http://10.6.80.114:18080/ | head -20
```
### Expected
Security headers should include:
- `Strict-Transport-Security`
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `Content-Security-Policy`
### Actual
None of these security headers are present in responses.
### Impact
Increases attack surface for clickjacking, MIME-type confusion, and XSS attacks.
### Recommendation
Add the following headers to nginx configuration:
```
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "0" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;
```
---
## Finding 6: `/health` Endpoint Returns HTML Instead of Health Status
| Field | Value |
|-------|-------|
| **Test** | Health Endpoint Behavior |
| **Severity** | **Low** |
| **Endpoint** | `GET /health` |
| **Status** | Confirmed |
### What I Did
```bash
curl -s http://10.6.80.114:18080/health
```
### Expected
A health check endpoint should return a structured JSON response (e.g., `{"status":"healthy"}`) with HTTP 200.
### Actual
Returns the full `index.html` SPA page with HTTP 200:
```html
<!doctype html>
<html lang="en">
<head>
<title>OCDP Platform</title>
...
```
### Impact
Not a direct vulnerability, but misconfigured health checks can cause false positives in monitoring/load balancer health checks. It also means the SPA is served at `/health`, which is unexpected.
### Recommendation
Implement a dedicated health endpoint that returns `{"status":"ok"}` with appropriate content type, or remove the `/health` route if not needed.
---
## Tests Passed (No Issues Found)
| Test | Result |
|------|--------|
| **1. Unauthenticated Access** | **PASS** - All business endpoints return 401 |
| **2. JWT Token Manipulation** | **PASS** - Tampered tokens, alg=none, invalid formats all rejected (401) |
| **3. XSS/SQLi Testing** | **PASS** - Script injection, SQLi patterns safely handled |
| **4. IDOR - Instance Access** | **PASS** - No instances deployed to test; cluster/registry isolation confirmed working |
| **5. Sensitive Data Masking** | **PASS** - Cluster certs/keys and registry passwords masked as `••••••••` |
| **6. Self-Registration** | **PASS** - Registration endpoint requires authentication (401) |
| **7. Path Traversal** | **PASS** - Path traversal attempts return index.html (not /etc/passwd) |
| **8. Admin Permission Escalation** | **PASS** - Regular users blocked from admin endpoints (403) |
---
## Summary
| Severity | Count | Findings |
|----------|-------|----------|
| Critical | 0 | — |
| High | 0 | — |
| **Medium** | **2** | User enumeration, No rate limiting |
| **Low** | **4** | Server version disclosure, Permissive CORS, Missing security headers, `/health` returns HTML |
| **Total** | **6** | |
The platform's core security controls (authentication, JWT validation, authorization, sensitive data masking) are properly implemented. The main areas for improvement are authentication hardening (rate limiting, user enumeration) and HTTP security hardening (headers, CORS).