Créer la page Sécurité du wiki
109
S%C3%A9curit%C3%A9.md
Normal file
109
S%C3%A9curit%C3%A9.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# Sécurité
|
||||||
|
|
||||||
|
## Principes
|
||||||
|
|
||||||
|
Le projet applique trois règles absolues pour protéger les secrets :
|
||||||
|
|
||||||
|
- **Aucun secret en clair** : ni dans le code source, ni dans les logs, ni dans les messages d'erreur, ni dans les fixtures de test.
|
||||||
|
- **Masquage systématique** : utiliser `redact_url()`, `redact_secrets()` et `redact_exception()` depuis `utils/redaction.py`.
|
||||||
|
- **Chaînage d'exceptions** : ne jamais conserver une exception externe brute comme `__cause__` ou `__context__`. Journaliser la version expurgée puis utiliser `raise ... from None`, ou chaîner une cause elle-même expurgée.
|
||||||
|
|
||||||
|
## Masquage des données sensibles
|
||||||
|
|
||||||
|
### Masquage des URLs
|
||||||
|
|
||||||
|
La fonction `redact_url()` masque les paramètres sensibles dans les URLs. Les clés sensibles (insensibles à la casse) sont : `icalsecurise`, `token`, `key`, `password`, `secret`. Elle utilise `urlsplit`/`urlunsplit`/`parse_qsl` pour reconstruire l'URL. En cas d'erreur de parsing, elle retourne `REDACTED_URL`.
|
||||||
|
|
||||||
|
### Masquage des secrets dans le texte
|
||||||
|
|
||||||
|
La fonction `redact_secrets()` masque les URLs et les tokens isolés dans un texte. Elle traite les motifs comme : `icalsecurise=XXX`, `token=XXX`, `password=XXX`, `secret=XXX`. Les secrets supplémentaires (`extra_secrets`) sont triés par longueur décroissante pour éviter les masquages partiels.
|
||||||
|
|
||||||
|
### Masquage des exceptions
|
||||||
|
|
||||||
|
La fonction `redact_exception(exc, extra_secrets=())` applique `redact_secrets` au message de l'exception et aux secrets configurés. La méthode `Settings.redaction_secrets()` retourne un tuple de tous les secrets configurés (mots de passe, clés API) à transmettre.
|
||||||
|
|
||||||
|
## Configuration des logs
|
||||||
|
|
||||||
|
Le *formatter* `RedactingFormatter` dans `utils/logging.py` masque les secrets dans tous les enregistrements de log :
|
||||||
|
|
||||||
|
- Masquage de `record.msg`
|
||||||
|
- Masquage de `record.args` (gère les tuples et les dictionnaires)
|
||||||
|
- `setup_logging()` configure un *handler* `stdout` avec ce *formatter*
|
||||||
|
- Les loggers tiers (`urllib3`, `slixmpp`) sont positionnés sur `WARNING`
|
||||||
|
|
||||||
|
## Types sécurisés
|
||||||
|
|
||||||
|
Les mots de passe et clés API utilisent `pydantic.SecretStr` :
|
||||||
|
|
||||||
|
- Ils ne sont jamais sérialisés en clair.
|
||||||
|
- Ils sont masqués dans les messages d'erreur Pydantic (`hide_input_in_errors` pour les paramètres XMPP).
|
||||||
|
|
||||||
|
## Vérification avant déploiement
|
||||||
|
|
||||||
|
### Règles de détection
|
||||||
|
|
||||||
|
Le script `scripts/check_secrets.py` analyse le dépôt pour détecter les secrets littéraux avec trois motifs regex :
|
||||||
|
|
||||||
|
- **Affectation littérale** : `key = "value"` ou `key: "value"` (valeur de 3+ caractères entre guillemets)
|
||||||
|
- **Affectation non quotée** : pour les fichiers de configuration (`.conf`, `.ini`, `.toml`, `.yaml`, `.yml`), `key = value` (valeur de 3+ caractères non quotée)
|
||||||
|
- **Paramètre d'URL** : `?token=XXX` ou `&api_key=XXX` (valeur de 3+ caractères)
|
||||||
|
|
||||||
|
### Exclusions
|
||||||
|
|
||||||
|
Le script exclut :
|
||||||
|
|
||||||
|
- Les répertoires `.git`, `.venv`, `.worktrees`, `__pycache__`
|
||||||
|
- Les fichiers `.env` (jamais versionnés)
|
||||||
|
- Le fichier `GUIDE_DEV_PYTHON.md` (exemples intentionnels)
|
||||||
|
- Le répertoire `tests/`
|
||||||
|
- Les lignes marquées avec `secret-check: allow` (liste blanche locale pour les fixtures/exemples)
|
||||||
|
|
||||||
|
### Utilisation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier tout le dépôt
|
||||||
|
python scripts/check_secrets.py
|
||||||
|
|
||||||
|
# Vérifier uniquement les fichiers indexés (avant un commit)
|
||||||
|
python scripts/check_secrets.py --staged
|
||||||
|
```
|
||||||
|
|
||||||
|
Les codes de sortie sont :
|
||||||
|
|
||||||
|
- `0` : aucun secret détecté
|
||||||
|
- `1` : secrets trouvés
|
||||||
|
- `2` : erreur lors de l'exécution
|
||||||
|
|
||||||
|
Les résultats n'exposent **jamais** la valeur détectée, seulement le chemin, le numéro de ligne et le nom de la règle.
|
||||||
|
|
||||||
|
## Tests de non-fuite
|
||||||
|
|
||||||
|
La suite de tests inclut des **tests de non-fuite obligatoires** :
|
||||||
|
|
||||||
|
- Injecter des valeurs sentinelles distinctes dans l'URL, les identifiants, le mot de passe et la clé API
|
||||||
|
- Provoquer une erreur externe
|
||||||
|
- Vérifier l'absence dans :
|
||||||
|
- Le message d'erreur
|
||||||
|
- Les logs
|
||||||
|
- `__cause__` et `__context__`
|
||||||
|
- Le *traceback* complet
|
||||||
|
|
||||||
|
Chaque secret utilise une sentinelle distincte pour identifier précisément toute fuite éventuelle.
|
||||||
|
|
||||||
|
## Fichier `.env`
|
||||||
|
|
||||||
|
Le fichier `.env` n'est **jamais** commité (couvert par `.gitignore`). Utiliser `.env.example` comme modèle. En production, le fichier doit être local et lisible uniquement par le compte de service :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo install -d -m 0700 -o <service-user> -g <service-group> <config-dir>
|
||||||
|
sudo install -m 0600 -o <service-user> -g <service-group> .env <env-file>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bonnes pratiques
|
||||||
|
|
||||||
|
- Ne jamais placer de secrets dans les unités systemd, les commandes shell ou les journaux système.
|
||||||
|
- Éviter de partager les exports de logs sans revue : les données sensibles de l'environnement ou des outils tiers ne doivent pas être supposées sûres par défaut.
|
||||||
|
- Après modification des identifiants, relancer `check_secrets.py` et un `--dry-run` avant de redémarrer le service.
|
||||||
|
- En cas d'échec, ne pas redémarrer automatiquement après modification des identifiants : corriger la configuration, relancer les vérifications, puis consulter le journal expurgé.
|
||||||
|
|
||||||
|
Voir aussi : [Configuration](Configuration) pour les variables d'environnement, [Déploiement](Déploiement) pour la configuration en production.
|
||||||
Reference in New Issue
Block a user