Merge pull request 'fix: verify edge-owned HSTS during deployment' (#42) from fix/edge-hsts-deploy-check into main
This commit was merged in pull request #42.
This commit is contained in:
@@ -17,6 +17,8 @@ API_ANON_RATE=120/minute
|
|||||||
API_USER_RATE=600/minute
|
API_USER_RATE=600/minute
|
||||||
CALCULATOR_RATE=30/minute
|
CALCULATOR_RATE=30/minute
|
||||||
SECURE_HSTS_SECONDS=31536000
|
SECURE_HSTS_SECONDS=31536000
|
||||||
|
# Set true only when the HTTPS reverse proxy emits a non-zero HSTS max-age.
|
||||||
|
DJANGO_HSTS_AT_EDGE=false
|
||||||
|
|
||||||
# 仅供部署脚本直接访问 127.0.0.1:8000 时设置 Host 头。
|
# 仅供部署脚本直接访问 127.0.0.1:8000 时设置 Host 头。
|
||||||
DEPLOY_HEALTH_HOST=math.example.com
|
DEPLOY_HEALTH_HOST=math.example.com
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ jobs:
|
|||||||
|
|
||||||
chmod +x scripts/deploy_production.sh
|
chmod +x scripts/deploy_production.sh
|
||||||
|
|
||||||
|
DJANGO_HSTS_AT_EDGE=true \
|
||||||
PROJECT_DIR="$PROJECT" \
|
PROJECT_DIR="$PROJECT" \
|
||||||
PYTHON_BIN="$PYTHON_BIN" \
|
PYTHON_BIN="$PYTHON_BIN" \
|
||||||
PREVIOUS_REVISION="$PREVIOUS_REVISION" \
|
PREVIOUS_REVISION="$PREVIOUS_REVISION" \
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def test_edge_hsts_ownership_is_explicit_and_verified():
|
||||||
|
settings = (ROOT / "backend/config/settings.py").read_text(encoding="utf-8")
|
||||||
|
deploy = (ROOT / "scripts/deploy_production.sh").read_text(encoding="utf-8")
|
||||||
|
workflow = (ROOT / ".gitea/workflows/deploy.yml").read_text(encoding="utf-8")
|
||||||
|
example = (ROOT / ".env.production.example").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert 'os.getenv("DJANGO_HSTS_AT_EDGE", "false")' in settings
|
||||||
|
assert '["security.W004"]' in settings
|
||||||
|
assert "DJANGO_HSTS_AT_EDGE=true" in workflow
|
||||||
|
assert "strict-transport-security:.*max-age=[1-9][0-9]*" in deploy
|
||||||
|
assert "DJANGO_HSTS_AT_EDGE=false" in example
|
||||||
@@ -189,6 +189,12 @@ SECURE_HSTS_SECONDS = int(
|
|||||||
)
|
)
|
||||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = USE_HTTPS
|
SECURE_HSTS_INCLUDE_SUBDOMAINS = USE_HTTPS
|
||||||
SECURE_HSTS_PRELOAD = USE_HTTPS
|
SECURE_HSTS_PRELOAD = USE_HTTPS
|
||||||
|
HSTS_AT_EDGE = os.getenv("DJANGO_HSTS_AT_EDGE", "false").lower() == "true"
|
||||||
|
SILENCED_SYSTEM_CHECKS = (
|
||||||
|
["security.W004"]
|
||||||
|
if USE_HTTPS and HSTS_AT_EDGE and SECURE_HSTS_SECONDS == 0
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
|
|||||||
@@ -234,6 +234,16 @@ if [ -d "$PROJECT_DIR/backend/staticfiles" ]; then
|
|||||||
fi
|
fi
|
||||||
cd "$PROJECT_DIR/backend"
|
cd "$PROJECT_DIR/backend"
|
||||||
if [ "${DJANGO_USE_HTTPS:-true}" = "true" ]; then
|
if [ "${DJANGO_USE_HTTPS:-true}" = "true" ]; then
|
||||||
|
if [ "${DJANGO_HSTS_AT_EDGE:-false}" = "true" ]; then
|
||||||
|
curl --fail --silent --show-error --head \
|
||||||
|
--noproxy '*' \
|
||||||
|
--resolve "${HEALTH_HOST}:443:127.0.0.1" \
|
||||||
|
--max-time 10 \
|
||||||
|
"https://${HEALTH_HOST}/" |
|
||||||
|
tr -d '\r' |
|
||||||
|
grep -Eiq '^strict-transport-security:.*max-age=[1-9][0-9]*'
|
||||||
|
log "边缘代理 HSTS 已验证"
|
||||||
|
fi
|
||||||
"$VENV_DIR/bin/python" manage.py check --deploy --fail-level WARNING --database default
|
"$VENV_DIR/bin/python" manage.py check --deploy --fail-level WARNING --database default
|
||||||
else
|
else
|
||||||
log "临时 HTTP 模式:部署安全检查只阻断 ERROR;绑定域名后应启用 HTTPS"
|
log "临时 HTTP 模式:部署安全检查只阻断 ERROR;绑定域名后应启用 HTTPS"
|
||||||
|
|||||||
Reference in New Issue
Block a user