Files
hantim-server/tests/test_security_headers.py
T
2026-03-20 15:20:29 -04:00

61 lines
1.9 KiB
Python

"""Test that security headers are present on all HTTPS sites."""
import glob
import os
import re
import urllib.request
import ssl
import pytest
CONF_DIR = os.path.join(os.path.dirname(__file__), "..", "docker", "nginx", "conf.d")
def discover_sites():
"""Build HTTPS URLs from nginx conf files that include security-headers.inc."""
sites = []
for conf in sorted(glob.glob(os.path.join(CONF_DIR, "*.conf"))):
text = open(conf).read()
if "security-headers.inc" not in text:
continue
# Use the first server_name in the block that includes the headers
for block in re.split(r"(?=server\s*\{)", text):
if "security-headers.inc" in block:
m = re.search(r"server_name\s+([^;]+);", block)
if m:
sites.append(f"https://{m.group(1).split()[0]}")
break
return sites
SITES = discover_sites()
EXPECTED_HEADERS = {
"Strict-Transport-Security": "max-age=63072000; preload",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "geolocation=(), microphone=(), camera=()",
}
def get_headers(url):
ctx = ssl.create_default_context()
req = urllib.request.Request(url, method="HEAD")
try:
resp = urllib.request.urlopen(req, context=ctx, timeout=10)
return dict(resp.headers)
except urllib.error.HTTPError as e:
return dict(e.headers)
@pytest.mark.parametrize("url", SITES, ids=lambda u: u.split("//")[1])
def test_security_headers(url):
headers = get_headers(url)
missing = []
for name, expected in EXPECTED_HEADERS.items():
actual = headers.get(name)
if actual != expected:
missing.append(f"{name}: expected '{expected}', got '{actual}'")
assert not missing, "\n".join(missing)