62 lines
6.6 KiB
Markdown
62 lines
6.6 KiB
Markdown
# Corrections supplémentaires — 10 septembre 2026
|
||
|
||
Branche `check_secu`. Les modifications antérieures sont conservées. Deux problèmes supplémentaires ont été traités successivement ; aucun commit, déploiement, accès à une base réelle ou envoi d’email réel n’a été effectué.
|
||
|
||
## 1. SMTP : certificat non vérifié et STARTTLS facultatif
|
||
|
||
**Résultat local : corrigé (`fixed`).**
|
||
|
||
L’unique transport Nodemailer désactivait `rejectUnauthorized`. La production et la préproduction utilisent le port 587 avec `SMTP_SECURE=false`, donc STARTTLS plutôt que TLS implicite. Sans `requireTLS`, un serveur ou intermédiaire refusant STARTTLS pouvait conduire à une authentification sans chiffrement. Les messages concernés comprennent les liens de réinitialisation et d’invitation.
|
||
|
||
Le correctif dans `apps/backend/src/infrastructure/email/email.adapter.ts` active la vérification des certificats et impose STARTTLS lorsque `NODE_ENV=production`. Le nom SMTP d’origine reste utilisé pour vérifier le certificat après résolution de l’adresse IP. Le TLS implicite et les serveurs SMTP locaux de développement sans TLS restent supportés ; cette exception de développement ne doit pas servir en production.
|
||
|
||
Preuve : `email.adapter.spec.ts` contient quatre tests. Un serveur SMTP éphémère sur loopback, qui n’annonce pas STARTTLS et refuse sa commande, est rejeté avant AUTH. Le contrôle local explicitement sans TLS peut s’authentifier sur ce même serveur simulé. Les options de vérification de certificat, le nom d’origine, le TLS implicite et la propagation d’un échec d’envoi sont vérifiés. Aucun email n’est transmis.
|
||
|
||
Limite : le rejet d’un certificat SMTP invalide est vérifié via les options de transport et une erreur d’envoi simulée, pas par une connexion au fournisseur réel. Une investigation indépendante et une revue du correctif n’ont retenu aucun contournement confirmé.
|
||
|
||
## 2. PostgreSQL : paramètres TLS incohérents entre clients
|
||
|
||
**Résultat local : corrigé (`fixed`). Déploiement conditionné à la configuration de confiance.**
|
||
|
||
L’API et le script de démarrage ignoraient `DATABASE_SSL`, tandis que la CLI TypeORM acceptait les certificats non authentifiés. La configuration de production exige pourtant `hostssl`. Outre l’absence de vérification d’identité côté CLI, cette incohérence pouvait empêcher le démarrage de l’API face à la configuration PostgreSQL fournie.
|
||
|
||
Une fonction commune `databaseTlsOptions` est désormais utilisée par :
|
||
|
||
- la configuration TypeORM de l’API dans `app.module.ts` ;
|
||
- la source de données de la CLI TypeORM ;
|
||
- les clients de disponibilité et de migration de `scripts/setup/startup.js` ;
|
||
- le script `scripts/setup/run-migrations.js` ;
|
||
- le client du script d’entrypoint historique, bien que l’image actuelle utilise `startup.js`.
|
||
|
||
Lorsque `DATABASE_SSL=true`, tous ces clients vérifient le certificat et l’identité de `DATABASE_HOST`, y compris une adresse IP. `DATABASE_SSL_CA` accepte le certificat public PEM de confiance pour le certificat auto-signé déjà généré par l’infrastructure. L’absence de CA spécifique conserve les autorités reconnues par Node ; elle n’entraîne jamais une désactivation de la vérification. Une valeur de drapeau invalide est refusée. Les chaînes majuscules/minuscules suivent le comportement de validation Joi. Le mode local explicitement sans TLS reste disponible.
|
||
|
||
Les chemins des scripts ont également été alignés sur la racine backend : copie Docker à `/app/startup.js` et copie du dépôt sous `scripts/setup`. Les modules compilés, entités et migrations sont ainsi résolus au même endroit. Le chargement de `startup.js` depuis un test n’établit aucune connexion et ne lance pas de migration.
|
||
|
||
Preuves :
|
||
|
||
- 11 tests dans `database-tls.spec.ts` : drapeaux de configuration et véritables handshakes TLS locaux avec certificat de test éphémère. Le certificat approuvé avec le SAN correspondant à l’IP est accepté ; un certificat non approuvé ou une IP incorrecte sont refusés.
|
||
- 2 tests dans `database-startup.spec.ts` : mêmes paramètres SSL transmis au client de disponibilité et aux deux scripts de migration, dans les dispositions Docker et dépôt. PostgreSQL et TypeORM sont simulés, aucune migration réelle n’est exécutée.
|
||
- Chargement du script avec le helper réellement compilé : réussi, sans connexion.
|
||
- Investigation et revue indépendantes : aucun contournement ou régression confirmé. Le reviewer était limité par le sandbox pour ses handshakes ; les handshakes du parent ont été exécutés avec autorisation sur loopback et ont réussi.
|
||
|
||
**Avant déploiement :** renseigner `DATABASE_SSL_CA` dans le Secret backend SOPS avec le certificat **public** de db-01 récupéré via un canal d’administration authentifié. Ne jamais copier sa clé privée. L’API et le Job de migration consomment ce même Secret. Le gabarit de secrets et le README de production décrivent cette préparation. Aucun certificat de production n’a été lu ou modifié. Ne pas déployer le nouveau client contre un certificat auto-signé sans avoir distribué cette confiance.
|
||
|
||
Les scripts ponctuels de maintenance hors des chemins de démarrage n’ont pas tous été harmonisés ; leur revue reste à effectuer avant une utilisation sur une base TLS.
|
||
|
||
## Vérifications finales
|
||
|
||
- `npm test -- --runInBand` (backend) : **451 tests réussis**, 5 tests déjà ignorés, 32 suites réussies et 1 ignorée. Les tests réseau utilisent uniquement des serveurs éphémères sur `127.0.0.1`.
|
||
- `npm run build` (backend) : réussi.
|
||
- ESLint sur les fichiers TypeScript concernés : réussi.
|
||
- Vérifications de syntaxe Node des deux scripts de démarrage/migration : réussies.
|
||
- Vérification de syntaxe de l’entrypoint shell : réussie.
|
||
- `git diff --check` : réussi.
|
||
|
||
Les essais ont détecté puis permis de corriger une configuration de test masquée par `NODE_ENV=test`, ainsi qu’un type TLS trop large pour les options TypeORM. Aucun contrôle de sécurité n’a été assoupli pour contourner ces échecs.
|
||
|
||
## Analyse des dépendances en attente
|
||
|
||
La tentative initiale de `npm audit --package-lock-only --omit=dev --json` n’a pas pu joindre le registre npm (`ENOTFOUND`). La demande d’accès réseau a ensuite été refusée par la validation automatique : la liste des dépendances et versions aurait été envoyée vers une destination externe non explicitement autorisée.
|
||
|
||
Une demande d’autorisation est en attente. Aucun contournement ni nouvel envoi n’a été effectué. Cette analyse ne transmettrait ni le code source ni les fichiers `.env`. L’audit exhaustif du dépôt et des dépendances n’est donc toujours pas déclaré terminé.
|