Exposition et sécurité¶
Principe¶
Un seul service publie des ports vers Internet : Traefik (80 et 443). Tout
le reste écoute sur 127.0.0.1 et n'est joignable que par tunnel SSH.
flowchart LR
I[Internet] -->|443| T[Traefik]
T -->|"/"| W[nginx]
T -->|"/public/ /app/ /api/public/"| M[Metabase]
S[Poste administrateur] -.->|tunnel SSH| L["127.0.0.1<br/>:3000 :8080 :5432"]
L -.-> M
L -.-> A[Airflow]
L -.-> P[(PostgreSQL)]
Ce qui est public, ce qui ne l'est pas¶
| Chemin | Réponse | Servi par |
|---|---|---|
/ |
200 | nginx — la vitrine |
/docs/ |
200 | nginx — cette documentation |
/public/dashboard/… |
200 | Metabase — tableaux de bord partagés |
/api/public/… |
200 | Metabase — données des tableaux de bord |
/app/… |
200 | Metabase — ressources statiques nécessaires à l'affichage |
/auth/login |
404 | — |
/admin |
404 | — |
/api/card, /api/setting, /api/dashboard/… |
404 | — |
Le routage Metabase est une liste blanche de chemins, pas un domaine
dédié. La console d'administration est servie sur /, chemin qui appartient à
nginx : elle est donc structurellement injoignable depuis Internet.
Vérifier après toute modification des étiquettes
Les règles Traefik sont portées par les étiquettes Docker du conteneur
Metabase. Modifier le docker-compose.yml ne suffit pas : il faut
recréer le conteneur (docker compose up -d --force-recreate metabase),
sinon il continue de porter les anciennes étiquettes. Cette erreur a été
commise pendant la mise en place et a produit des 404 déroutants.
TLS¶
Certificat Let's Encrypt obtenu par défi HTTP-01, stocké dans
data/letsencrypt/acme.json. Renouvellement automatique 30 jours avant
échéance, sans intervention.
# Vérifier le certificat servi
echo | openssl s_client -connect demo.metrika.fr:443 -servername demo.metrika.fr 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Tester avant de consommer le quota
Let's Encrypt limite les échecs de validation à 5 par heure et par nom.
Pour tout test, basculer ACME_CASERVER sur l'environnement de test dans
.env, puis supprimer data/letsencrypt/acme.json avant de repasser en
production — un compte de test n'est pas valide en production.
Le compromis assumé sur les tableaux de bord¶
Les tableaux de bord sont exposés via les liens publics Metabase. Ce choix a des conséquences qu'il faut connaître :
| Lien public (retenu) | Embarquement signé (écarté) | |
|---|---|---|
| Backend requis | non | oui |
| Durée de validité | permanente | jeton expirable |
| Filtrage par visiteur | impossible | possible |
| Qui peut voir | quiconque a l'URL | qui présente un jeton valide |
Acceptable ici : les données commerciales sont fictives et l'open data est
public par nature. Ce ne le serait pas pour des données client réelles — il
faudrait alors l'embarquement signé, donc un composant serveur capable de
signer un JWT avec MB_EMBEDDING_SECRET_KEY (ce calcul ne peut pas se faire
dans le navigateur, la clé fuiterait).
Les liens se révoquent à tout moment depuis Metabase.
Comptes et secrets¶
Tous les mots de passe sont générés aléatoirement à l'installation et stockés
dans .env — permissions 600, exclu de Git.
| Rôle PostgreSQL | Portée |
|---|---|
warehouse |
propriétaire de l'entrepôt, lecture et écriture |
metabase_reader |
lecture seule, limité aux schémas de l'entrepôt |
metabase, airflow |
leurs bases de métadonnées respectives |
metrika |
superutilisateur |
Metabase se connecte à l'entrepôt avec metabase_reader : il ne peut rien
modifier. C'est le principe du moindre privilège appliqué à l'outil qui a le
plus de chances d'être exposé.
Messagerie¶
SMTP OVH (ssl0.ovh.net:587, STARTTLS) avec une boîte dédiée
notification@metrika.fr. Le mot de passe est chiffré par Metabase dans sa
base de métadonnées via MB_ENCRYPTION_SECRET_KEY.
Authentification du courrier en place
Le domaine metrika.fr publie les trois mécanismes attendus :
| Mécanisme | Valeur |
|---|---|
| SPF | v=spf1 include:mx.ovh.com ~all — un seul enregistrement |
| DKIM | actif, sélecteurs ovhmo-selector-1 et -2 |
| DMARC | v=DMARC1; p=none; rua=mailto:notification@metrika.fr; sp=none; aspf=r |
Un point de vigilance permanent : il ne doit jamais y avoir qu'un seul
enregistrement SPF. La RFC 7208 impose un résultat permerror en présence
de plusieurs, ce qui fait échouer l'évaluation entièrement — pire que
l'absence d'enregistrement. L'éditeur de zone OVH range les SPF sous un type
distinct de TXT, ce qui les rend invisibles si l'on filtre sur TXT.
~all (softfail) est le bon qualificateur au démarrage. Une fois que les
rapports DMARC confirment que tout le courrier légitime passe — comptez
deux à quatre semaines — on peut durcir en -all puis passer DMARC en
p=quarantine, et enfin p=reject.