Quatre taches de la matrice du rapport, toutes sans dependance, qu aucune liste de « ce qui reste » ne reprenait. OPS-003 — app/.env.exemple disait « copiez ce fichier et remplissez les valeurs pour la production », puis posait FLASK_DEBUG=true, SESSION_COOKIE_SECURE=false et FORCE_HTTPS=false. Le debogueur Werkzeug execute du code soumis par le navigateur : cette ligne transformait un copier-coller en shell distant. Chaque valeur est desormais sure a la copie, et le fichier refuse de demarrer tant que les deux secrets obligatoires ne sont pas remplis plutot que de demarrer grand ouvert. Renomme en .env.example : l orthographe francaise ne correspondait pas a l exception !.env.example du .gitignore, donc le fichier n etait suivi que par accident de l ordre des regles. Les deux points de la decision ouverte du §8 tombent d un seul git mv. OPS-002 — trusted_proxy='*' et HOST ne sont plus soudes dans wsgi.py. Les defauts sont **inchanges**, deliberement : choisir sans connaitre la topologie coupe la prod si nginx est ailleurs, ou casse la limitation de debit pour tout le monde si on cesse de croire X-Forwarded-For alors que c etait la seule source d adresses. Ce sont maintenant des variables, les valeurs sures sont dans .env.example pour un nouveau deploiement, et docs/deployment.md donne les quatre topologies avec la valeur de chacune. wsgi.py avertit au demarrage tant que les deux defauts sont en place. Le commentaire de HOST annoncait « bind to localhost by default » a cote d un defaut a 0.0.0.0 : il decrivait l intention pendant que le code faisait l inverse. Il dit maintenant ce qu il fait. QUA-004 — Font Awesome et FullCalendar etaient charges sans empreinte, depuis des hotes que la CSP autorise nommement. Qui controle ces CDN controlait ce qui s execute sur chaque page. Empreintes posees, avec ce que SRI promet et ce qu il ne promet pas ecrit a cote : ca fige le fichier, ca ne prouve pas qu il etait honnete au moment du calcul. **Le CSS de FullCalendar n existait pas.** La v6 embarque ses styles dans le JS et ce fichier n est pas publie : le <link> repondait 404 a chaque ouverture du calendrier depuis la montee de version. Une feuille de style en echec est silencieuse dans le navigateur, c est ce qui l a fait durer. CI-003 — actions epinglees sur un commit, version en commentaire, dans les deux forges. Un tag est un pointeur mobile : deplacer v4 fait executer du code arbitraire dans le job qui detient la cle SSH de production. Ce job recoit aussi enfin un bloc permissions. 517 tests.
116 lines
5.0 KiB
Bash
116 lines
5.0 KiB
Bash
# Team Tryouts — environment variables
|
|
#
|
|
# Copy to .env and fill in. Every value here is a PRODUCTION-SAFE default:
|
|
# copying this file and changing nothing gives a locked-down configuration
|
|
# that refuses to start until the two required secrets are set, rather than
|
|
# a working one that happens to be wide open (OPS-003).
|
|
#
|
|
# The previous version shipped FLASK_DEBUG=true under a heading that said
|
|
# "fill in the values for production". The Werkzeug debugger executes code
|
|
# submitted through the browser, so that one line turned a copy-paste into a
|
|
# remote shell.
|
|
#
|
|
# For local development, see the DEVELOPMENT block at the bottom.
|
|
|
|
# =============================================================================
|
|
# Required — the application refuses to start without these
|
|
# =============================================================================
|
|
|
|
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
|
|
# Never reuse one between environments: this key signs session cookies, so
|
|
# whoever holds it can forge a session for any account.
|
|
SECRET_KEY=
|
|
|
|
# Expected form: postgresql://user:password@host:5432/database
|
|
# The psycopg 3 driver is named for you by create_app(); postgresql:// alone
|
|
# would send SQLAlchemy looking for psycopg2, which is not installed.
|
|
DATABASE_URL=
|
|
|
|
# =============================================================================
|
|
# Security — these defaults assume HTTPS in front. Do not relax them on a
|
|
# deployed instance.
|
|
# =============================================================================
|
|
|
|
# Session cookies are only sent over HTTPS.
|
|
SESSION_COOKIE_SECURE=true
|
|
|
|
# Plain HTTP is redirected to HTTPS.
|
|
FORCE_HTTPS=true
|
|
|
|
# The Werkzeug debugger is a remote code execution primitive by design.
|
|
# Never true on anything reachable from a network you do not control.
|
|
FLASK_DEBUG=false
|
|
|
|
# Inline <script> without a nonce. Off: every block carries one, and turning
|
|
# this on gives up the protection that would have blocked the stored XSS
|
|
# (SEC-WEB-001). It exists as an escape hatch, not as a setting to tune.
|
|
CSP_ALLOW_INLINE_SCRIPT=false
|
|
|
|
# Comma-separated origins allowed to call this API cross-site. Empty means
|
|
# no CORS policy at all, which is correct: the site renders its own HTML on
|
|
# one origin and needs none.
|
|
CORS_ALLOWED_ORIGINS=
|
|
|
|
# =============================================================================
|
|
# Networking
|
|
# =============================================================================
|
|
|
|
# Interface Waitress binds. 127.0.0.1 keeps it reachable only through the
|
|
# local reverse proxy; 0.0.0.0 exposes it directly and is only correct if
|
|
# something else in front is doing the filtering.
|
|
HOST=127.0.0.1
|
|
PORT=5000
|
|
|
|
# Whether to believe X-Forwarded-For, and from whom. This decides which IP
|
|
# the rate limiter and the audit log record.
|
|
#
|
|
# (empty) — trust nobody. Correct when nothing proxies the app.
|
|
# 127.0.0.1 — trust a reverse proxy on this same machine. The usual case.
|
|
# * — trust everyone. Only ever correct if the app cannot be reached
|
|
# except through the proxy, at the network level. Otherwise any
|
|
# caller can claim any IP and walk around the rate limit.
|
|
#
|
|
# See docs/deployment.md before changing this (OPS-002).
|
|
TRUSTED_PROXY=127.0.0.1
|
|
|
|
# =============================================================================
|
|
# Optional — Discord
|
|
# =============================================================================
|
|
|
|
# Leave ENABLE_DISCORD_BOT=false and the token empty to run without Discord.
|
|
ENABLE_DISCORD_BOT=false
|
|
DISCORD_BOT_TOKEN=
|
|
|
|
# OAuth2, for "Connect Discord" on the sign-up page.
|
|
# Create an application at https://discord.com/developers/applications
|
|
DISCORD_CLIENT_ID=
|
|
DISCORD_CLIENT_SECRET=
|
|
DISCORD_REDIRECT_URI=https://your-domain/auth/discord/callback
|
|
|
|
# =============================================================================
|
|
# Optional — storage
|
|
# =============================================================================
|
|
|
|
# Where uploaded contracts live. Empty means `documents/` beside the
|
|
# application. Set it to a path OUTSIDE the deployment directory if you move
|
|
# to a release-directory layout, or a deployment will take the documents with
|
|
# it (OPS-011, app/storage.py).
|
|
DOCUMENTS_ROOT=
|
|
|
|
# Tables are created at startup when missing. Set to false once Alembic owns
|
|
# the schema (DB-002/DB-004): create_all() never ALTERs, so a column added to
|
|
# a model is silently absent from an existing database.
|
|
AUTO_CREATE_TABLES=true
|
|
|
|
# =============================================================================
|
|
# DEVELOPMENT ONLY — the values to change on a laptop, and nowhere else
|
|
# =============================================================================
|
|
#
|
|
# FLASK_DEBUG=true reloader and interactive debugger
|
|
# SESSION_COOKIE_SECURE=false cookies over plain HTTP
|
|
# FORCE_HTTPS=false no redirect to HTTPS
|
|
# DISCORD_REDIRECT_URI=http://localhost:5000/auth/discord/callback
|
|
#
|
|
# `python run.py` reads DEV_HOST and DEV_PORT rather than HOST and PORT, so a
|
|
# development session cannot accidentally inherit a production binding.
|