feat: add Django project scaffold, configuration and container
Environment-variable configuration that fails fast, database-only health check, JSON request logs with a request id, security headers with a strict CSP, and a multi-stage non-root Docker image with compose file. Ticket 1.1. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sk72AxLwQnYttF6VFSxQLt
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
24de5878ed
commit
f8b0584687
@@ -0,0 +1,39 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_security_headers_present(client):
|
||||
response = client.get("/healthz")
|
||||
csp = response["Content-Security-Policy"]
|
||||
assert "script-src 'self'" in csp
|
||||
assert "default-src 'self'" in csp
|
||||
assert "frame-ancestors 'none'" in csp
|
||||
assert "unsafe-inline" not in csp
|
||||
assert "http" not in csp
|
||||
assert response["X-Content-Type-Options"] == "nosniff"
|
||||
assert response["X-Frame-Options"] == "DENY"
|
||||
assert response["Referrer-Policy"] == "same-origin"
|
||||
assert response["X-Request-ID"]
|
||||
|
||||
|
||||
def test_headers_also_on_error_responses(client):
|
||||
response = client.get("/missing")
|
||||
assert response.status_code == 404
|
||||
assert "Content-Security-Policy" in response
|
||||
assert response["X-Request-ID"]
|
||||
|
||||
|
||||
def test_valid_incoming_request_id_is_kept(client):
|
||||
response = client.get("/missing", headers={"X-Request-ID": "abc12345-req"})
|
||||
assert response["X-Request-ID"] == "abc12345-req"
|
||||
|
||||
|
||||
def test_invalid_incoming_request_id_is_replaced(client):
|
||||
response = client.get("/missing", headers={"X-Request-ID": "bad id\twith junk"})
|
||||
assert response["X-Request-ID"] != "bad id\twith junk"
|
||||
|
||||
|
||||
def test_csp_on_bad_host_response(client):
|
||||
response = client.get("/healthz", HTTP_HOST="unlisted.example")
|
||||
assert response.status_code == 400
|
||||
assert "script-src 'self'" in response["Content-Security-Policy"]
|
||||
Reference in New Issue
Block a user