Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt

Use this file to discover all available pages before exploring further.

Object Lock — runbook anti-ransomware sur les buckets DR

Quoi et pourquoi

Les buckets mssp-backup-ovh (OVH Gravelines) et mssp-backup-scw (Scaleway Paris) qui hébergent les backups Postgres + Vault + artifacts sont configurés en Object Lock COMPLIANCE mode, rétention 90 jours (cf. scripts/dr/setup/bootstrap-buckets.sh). Conséquence concrète :
Un attaquant qui obtient les credentials DR Vault ou les access keys S3 OVH/Scaleway ne peut pas supprimer ou overwriter les backups écrits dans les 90 derniers jours. Pas même le détenteur du compte root du provider. Pas de bypass.
C’est la dernière ligne de défense contre un ransomware qui aurait passé tous les autres remparts (compromise de Vault, exfiltration des creds, accès SSH).

Modes Object Lock

ModeQuoiChoix SnakySec
COMPLIANCEPersonne ne peut désactiver/raccourcir le lock pendant la rétention. Attendre l’expiration ou détruire le bucket.Activé
GOVERNANCEUn user avec le permission spécifique s3:BypassGovernanceRetention peut overrider.❌ Trop laxiste pour un cas anti-ransomware
OFFPas de lock.❌ Risque ransomware non couvert

Implications opérationnelles

Le storage va grossir au-delà des cibles théoriques

pgbackrest.conf configure repo-retention-full=4 (= ~30 jours d’historique) ; restic --keep-daily 14 --keep-weekly 8 --keep-monthly 3 (= ~90 jours). Avec Object Lock 90j actif :
  • pgbackrest tentera de DELETE les fulls > 4 → DELETE bloqué, fichiers non supprimés
  • restic forget --prune tentera de purger les snapshots forgottens → DELETE bloqué
Le storage va donc augmenter au-dessus du steady-state théorique pendant ~90 jours, jusqu’à ce que les premières ondes de locks expirent. Après J+90 c’est en flux tendu : ce qui s’efface en J = ce qui est libéré du lock en J-90. Estimation steady-state (ordre de grandeur, à ajuster sur ton volume réel) :
  • Postgres : ~200 MB par full × 12 fulls (90j) + ~50 MB/jour de WAL × 90j = 6.7 GB par bucket
  • Vault : ~2 MB par snapshot × 90 = 180 MB par bucket
  • Artifacts : croît avec le nombre de clients, ~100 MB/mois × 3 mois = 300 MB par bucket
Total ~7 GB par bucket × 2 buckets = ~15 GB cumulés en steady-state. Largement dans le free tier OVH/Scaleway (5 TB inclus chez OVH HSP, 75 GB free chez Scaleway Multi-AZ).

Les warnings DELETE dans les logs sont normaux

WARN: [pgbackrest] expire failed for archive 16/000000010000... — Access Denied
WARN: [restic] forget could not delete pack 7a4f9d... — locked
Ne pas remédier. C’est le comportement voulu. Les scripts postgres-pgbackrest.sh, vault-snapshot.sh, artifacts-restic.sh tagguent ces warnings comme informatifs. Tu peux confirmer la santé via la métrique storage utilisée dans la console provider — si elle plafonne ~J+90 c’est que les locks expirent comme prévu.

Cas d’urgence : besoin réel de purger un objet

Réponse courte : tu ne peux pas, c’est le point. Si vraiment vital (genre fuite légale RGPD d’un objet contenant des données personnelles client qui aurait dû être anonymisé) :
  1. Attendre l’expiration naturelle du lock (max 90 jours)
  2. OU recréer le bucket : créer un nouveau bucket sans Object Lock (ou avec rétention plus courte), drainer ce qu’on veut garder, supprimer l’ancien bucket. Côté OVH/Scaleway il faut généralement contacter le support pour forcer la suppression d’un bucket Object-Locked. Procédure semaine + paperasse.
Pas d’autre voie. C’est la promesse du compliance mode et c’est ce qu’on veut.

Migration d’un bucket legacy (sans Object Lock)

Si bootstrap-buckets.sh détecte un bucket existant SANS Object Lock, il refuse l’opération avec un message clair. La migration manuelle :
# 1. Créer un nouveau bucket "mssp-backup-ovh-v2" avec Object Lock
docker exec mssp-dr-runner aws --endpoint-url=https://s3.gra.io.cloud.ovh.net \
  s3api create-bucket \
  --bucket mssp-backup-ovh-v2 \
  --object-lock-enabled-for-bucket

# 2. Configurer Versioning + Object Lock retention 90j compliance
# (commandes dans bootstrap-buckets.sh)

# 3. Drainer les backups de l'ancien bucket vers le nouveau
docker exec mssp-dr-runner rclone --config=/dr-runtime/rclone-ovh.conf \
  copy ovh:mssp-backup-ovh ovh:mssp-backup-ovh-v2 \
  --progress --transfers 4

# 4. Mettre à jour les configs qui pointent sur l'ancien bucket :
#    • platform/docker/postgres/pgbackrest.conf (repo1-s3-bucket)
#    • platform/compose/dr.yml (env vars OVH_REPO_URL, OVH_ARTIFACTS_REPO, etc)
# 5. Renommer ou supprimer l'ancien bucket via le support OVH

# 6. Vérifier que les backups continuent de tourner sur le nouveau bucket
docker exec mssp-cron ofelia exec --config=/etc/ofelia/config.ini --job=vault-snapshot
docker exec mssp-dr-runner rclone --config=/dr-runtime/rclone-ovh.conf \
  ls ovh:mssp-backup-ovh-v2/vault | tail -3

Vérifier que le lock est actif (sanity check post-bootstrap)

# OVH
docker exec mssp-dr-runner aws --endpoint-url=https://s3.gra.io.cloud.ovh.net \
  s3api get-object-lock-configuration --bucket mssp-backup-ovh

# Sortie attendue :
# {
#   "ObjectLockConfiguration": {
#     "ObjectLockEnabled": "Enabled",
#     "Rule": {
#       "DefaultRetention": {
#         "Mode": "COMPLIANCE",
#         "Days": 90
#       }
#     }
#   }
# }

# Tester la non-suppression
docker exec mssp-dr-runner sh -c '
  echo "test-immutable" > /tmp/test-lock.txt
  aws --endpoint-url=https://s3.gra.io.cloud.ovh.net \
    s3 cp /tmp/test-lock.txt s3://mssp-backup-ovh/test-lock.txt
  aws --endpoint-url=https://s3.gra.io.cloud.ovh.net \
    s3 rm s3://mssp-backup-ovh/test-lock.txt
'
# La suppression doit échouer avec "AccessDenied: object is in compliance mode"

Audit régulier

À ajouter au script scripts/dr/verify/dr-verify.sh ou comme job Ofelia distinct (cf. plan Volet 3) :
  • Hebdomadaire : appeler get-object-lock-configuration sur les 2 buckets, vérifier que Mode=COMPLIANCE et Days=90. Si l’un des deux a divergé (downgrade vers GOVERNANCE ou OFF), Sentry alert tag dr.object-lock.drift.

Décisions historiques

DateDécisionRaison
2026-04-XXObject Lock listé comme “V2 manual follow-up” dans bootstrap-buckets.shSetup initial DR, focus first on backup pipeline correctness
2026-05-02Object Lock COMPLIANCE 90d activé via bootstrap-buckets.sh (Volet 1 du plan backup hardening)Anti-ransomware, dernière ligne de défense