Compare commits
10
Commits
136db1d47e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27242aed5e | ||
|
|
e200d850f9 | ||
|
|
c90858f45c | ||
|
|
92c456c7d1 | ||
|
|
9a5ce6e4af | ||
|
|
8825f6c639 | ||
|
|
d87edf0530 | ||
|
|
c89b82c6f4 | ||
|
|
f7536d3a3f | ||
|
|
6d8ed567b0 |
@@ -17,6 +17,8 @@ API_ANON_RATE=120/minute
|
||||
API_USER_RATE=600/minute
|
||||
CALCULATOR_RATE=30/minute
|
||||
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 头。
|
||||
DEPLOY_HEALTH_HOST=math.example.com
|
||||
|
||||
@@ -100,11 +100,14 @@ jobs:
|
||||
|
||||
chmod +x scripts/deploy_production.sh
|
||||
|
||||
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
|
||||
DJANGO_HSTS_AT_EDGE=true \
|
||||
PROJECT_DIR="$PROJECT" \
|
||||
PYTHON_BIN="$PYTHON_BIN" \
|
||||
PREVIOUS_REVISION="$PREVIOUS_REVISION" \
|
||||
DEPLOY_SMOKE_BASE_URL="http://127.0.0.1:4321" \
|
||||
DEPLOY_SMOKE_WS_URL="ws://127.0.0.1:4321/ws/health/" \
|
||||
DEPLOY_HEALTH_HOST="math.jacky0987.xyz" \
|
||||
DEPLOY_SMOKE_BASE_URL="https://math.jacky0987.xyz" \
|
||||
DEPLOY_SMOKE_WS_URL="wss://math.jacky0987.xyz/ws/health/" \
|
||||
bash scripts/deploy_production.sh
|
||||
|
||||
echo "========================================"
|
||||
@@ -114,13 +117,9 @@ jobs:
|
||||
EOF
|
||||
|
||||
- name: 从 Runner 验证 Nginx 健康状态
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PUBLIC_HOST: 117.72.28.96
|
||||
run: |
|
||||
curl --fail --silent --show-error \
|
||||
--retry 5 \
|
||||
--retry-delay 2 \
|
||||
--header "Host: $DEPLOY_PUBLIC_HOST" \
|
||||
"http://$DEPLOY_HOST:4321/health/" \
|
||||
"https://math.jacky0987.xyz/health/" \
|
||||
| grep -q '"status": "ok"'
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
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 "SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" in workflow
|
||||
assert 'DEPLOY_HEALTH_HOST="math.jacky0987.xyz"' in workflow
|
||||
assert 'DEPLOY_SMOKE_BASE_URL="https://math.jacky0987.xyz"' in workflow
|
||||
assert 'DEPLOY_SMOKE_WS_URL="wss://math.jacky0987.xyz/ws/health/"' in workflow
|
||||
assert '"https://math.jacky0987.xyz/health/"' in workflow
|
||||
assert "127.0.0.1:4321" not in workflow
|
||||
assert "curl --silent --show-error --head" in deploy
|
||||
assert "curl --fail --silent --show-error --head" not in deploy
|
||||
assert "strict-transport-security:.*max-age=[1-9][0-9]*" in deploy
|
||||
assert "unverified" not in deploy.lower()
|
||||
assert "DJANGO_HSTS_AT_EDGE=false" in example
|
||||
@@ -189,6 +189,12 @@ SECURE_HSTS_SECONDS = int(
|
||||
)
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = 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 = {
|
||||
"version": 1,
|
||||
|
||||
@@ -234,6 +234,16 @@ if [ -d "$PROJECT_DIR/backend/staticfiles" ]; then
|
||||
fi
|
||||
cd "$PROJECT_DIR/backend"
|
||||
if [ "${DJANGO_USE_HTTPS:-true}" = "true" ]; then
|
||||
if [ "${DJANGO_HSTS_AT_EDGE:-false}" = "true" ]; then
|
||||
curl --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
|
||||
else
|
||||
log "临时 HTTP 模式:部署安全检查只阻断 ERROR;绑定域名后应启用 HTTPS"
|
||||
|
||||
Reference in New Issue
Block a user