All checks were successful
Deploy Development / deploy (push) Successful in 36s
Test Suite / pytest-backend (push) Successful in 23s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 7s
Test Suite / playwright-tests (push) Successful in 23s
- Added Content-Security-Policy header to nginx configuration for SPA, enhancing security against XSS attacks. - Introduced middleware in FastAPI to set X-Content-Type-Options header, preventing MIME-sniffing vulnerabilities. - Updated production readiness audit and access layer endpoint audit to reflect security enhancements and ongoing governance practices. - Added tests to verify the presence of security headers in API responses, ensuring compliance with security standards.
65 lines
2.8 KiB
Nginx Configuration File
65 lines
2.8 KiB
Nginx Configuration File
server {
|
|
listen 80;
|
|
server_name localhost;
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
|
|
|
# Docker-Embedded DNS: Hostname »backend« bei Container-Neustarts neu auflösen
|
|
# — verringert sporadische 502, wenn sich nur die Backend-Container-IP geändert hat.
|
|
resolver 127.0.0.11 valid=10s ipv6=off;
|
|
|
|
# Uploads (Übungsmedien) und API erreichen Clients unter derselben Host-URL wie die SPA —
|
|
# dafür muss Nginx zur FastAPI-Instanz im Compose-Netz weiterleiten.
|
|
client_max_body_size 64m;
|
|
|
|
location ^~ /api/ {
|
|
set $docker_backend_svc backend;
|
|
proxy_pass http://$docker_backend_svc:8000$request_uri;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 300s;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
location ^~ /media/ {
|
|
# Auslieferung Übungsdateien erfolgt geschützt über /api/exercises/.../media/.../file (?ssetoken).
|
|
# Optional: Backend mit ALLOW_PUBLIC_MEDIA_STATIC=1 → wieder /media/ ohne Auth.
|
|
set $docker_backend_svc backend;
|
|
proxy_pass http://$docker_backend_svc:8000$request_uri;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location = /health {
|
|
set $hc_upstream backend;
|
|
proxy_pass http://$hc_upstream:8000/health;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
}
|
|
|
|
location / {
|
|
# Document-CSP für SPA/PWA — React nutzt häufig inline-styles; Mediendateien & API sind same-origin (Proxy).
|
|
# Bei separater API-Origin: connect-src hier erweitern oder nginx-Envsubst nutzen.
|
|
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self'; media-src 'self' blob: data:; worker-src 'self' blob:; manifest-src 'self';" always;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
# Cache static assets
|
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
}
|