feat: implement HTTP Security Headers management (Issue #20)

Add comprehensive security header management system with reusable
profiles, interactive builders, and security scoring.

Features:
- SecurityHeaderProfile model with 11+ header types
- CRUD API with 10 endpoints (/api/v1/security/headers/*)
- Caddy integration for automatic header injection
- 3 built-in presets (Basic, Strict, Paranoid)
- Security score calculator (0-100) with suggestions
- Interactive CSP builder with validation
- Permissions-Policy builder
- Real-time security score preview
- Per-host profile assignment

Headers Supported:
- HSTS with preload support
- Content-Security-Policy with report-only mode
- X-Frame-Options, X-Content-Type-Options
- Referrer-Policy, Permissions-Policy
- Cross-Origin-Opener/Resource/Embedder-Policy
- X-XSS-Protection, Cache-Control security

Implementation:
- Backend: models, handlers, services (85% coverage)
- Frontend: React components, hooks (87.46% coverage)
- Tests: 1,163 total tests passing
- Docs: Comprehensive feature documentation

Closes #20
This commit is contained in:
GitHub Actions
2025-12-18 02:58:26 +00:00
parent 01ec910d58
commit 8cf762164f
33 changed files with 7978 additions and 69 deletions

View File

@@ -0,0 +1,160 @@
import client from './client';
// Types
export interface SecurityHeaderProfile {
id: number;
uuid: string;
name: string;
hsts_enabled: boolean;
hsts_max_age: number;
hsts_include_subdomains: boolean;
hsts_preload: boolean;
csp_enabled: boolean;
csp_directives: string;
csp_report_only: boolean;
csp_report_uri: string;
x_frame_options: string;
x_content_type_options: boolean;
referrer_policy: string;
permissions_policy: string;
cross_origin_opener_policy: string;
cross_origin_resource_policy: string;
cross_origin_embedder_policy: string;
xss_protection: boolean;
cache_control_no_store: boolean;
security_score: number;
is_preset: boolean;
preset_type: string;
description: string;
created_at: string;
updated_at: string;
}
export interface SecurityHeaderPreset {
type: 'basic' | 'strict' | 'paranoid';
name: string;
description: string;
score: number;
config: Partial<SecurityHeaderProfile>;
}
export interface ScoreBreakdown {
score: number;
max_score: number;
breakdown: Record<string, number>;
suggestions: string[];
}
export interface CSPDirective {
directive: string;
values: string[];
}
export interface CreateProfileRequest {
name: string;
description?: string;
hsts_enabled?: boolean;
hsts_max_age?: number;
hsts_include_subdomains?: boolean;
hsts_preload?: boolean;
csp_enabled?: boolean;
csp_directives?: string;
csp_report_only?: boolean;
csp_report_uri?: string;
x_frame_options?: string;
x_content_type_options?: boolean;
referrer_policy?: string;
permissions_policy?: string;
cross_origin_opener_policy?: string;
cross_origin_resource_policy?: string;
cross_origin_embedder_policy?: string;
xss_protection?: boolean;
cache_control_no_store?: boolean;
}
export interface ApplyPresetRequest {
preset_type: string;
name: string;
}
// API Functions
export const securityHeadersApi = {
/**
* List all security header profiles
*/
async listProfiles(): Promise<SecurityHeaderProfile[]> {
const response = await client.get<SecurityHeaderProfile[]>('/security/headers/profiles');
return response.data;
},
/**
* Get a single profile by ID or UUID
*/
async getProfile(id: number | string): Promise<SecurityHeaderProfile> {
const response = await client.get<SecurityHeaderProfile>(`/security/headers/profiles/${id}`);
return response.data;
},
/**
* Create a new security header profile
*/
async createProfile(data: CreateProfileRequest): Promise<SecurityHeaderProfile> {
const response = await client.post<SecurityHeaderProfile>('/security/headers/profiles', data);
return response.data;
},
/**
* Update an existing profile
*/
async updateProfile(id: number, data: Partial<CreateProfileRequest>): Promise<SecurityHeaderProfile> {
const response = await client.put<SecurityHeaderProfile>(`/security/headers/profiles/${id}`, data);
return response.data;
},
/**
* Delete a profile (not presets)
*/
async deleteProfile(id: number): Promise<void> {
await client.delete(`/security/headers/profiles/${id}`);
},
/**
* Get built-in presets
*/
async getPresets(): Promise<SecurityHeaderPreset[]> {
const response = await client.get<SecurityHeaderPreset[]>('/security/headers/presets');
return response.data;
},
/**
* Apply a preset to create/update a profile
*/
async applyPreset(data: ApplyPresetRequest): Promise<SecurityHeaderProfile> {
const response = await client.post<SecurityHeaderProfile>('/security/headers/presets/apply', data);
return response.data;
},
/**
* Calculate security score for given settings
*/
async calculateScore(config: Partial<CreateProfileRequest>): Promise<ScoreBreakdown> {
const response = await client.post<ScoreBreakdown>('/security/headers/score', config);
return response.data;
},
/**
* Validate a CSP string
*/
async validateCSP(csp: string): Promise<{ valid: boolean; errors: string[] }> {
const response = await client.post<{ valid: boolean; errors: string[] }>('/security/headers/csp/validate', { csp });
return response.data;
},
/**
* Build a CSP string from directives
*/
async buildCSP(directives: CSPDirective[]): Promise<{ csp: string }> {
const response = await client.post<{ csp: string }>('/security/headers/csp/build', { directives });
return response.data;
},
};