Définir la rétention des exportations temporaires

CloudflareBeginner
Pratiquer maintenant

Introduction

Un service d’exportation doit supprimer les téléchargements temporaires sans effacer les documents conservés. Vous allez appliquer des règles d’expiration ciblées par préfixe, de transition de classe de stockage et de nettoyage des téléchargements incomplets à un nouveau bucket privé, puis inspecter les métadonnées réelles de la politique et des objets.

Commencez par terminer la gestion des objets et le nettoyage des téléchargements multipart. Cette nouvelle VM utilise Node.js 22.22.0, Wrangler 4.131.1 et AWS SDK 3.888.0. R2 doit être activé et vous devez disposer de l’autorisation de configurer le nouveau bucket. Consultez le fonctionnement du cycle de vie et la tarification, notamment la durée minimale et les frais de récupération d’Infrequent Access. Le jeu de données de test reste en stockage Standard et sera explicitement supprimé pendant cette session. Les vérifications d’acceptation portent sur les règles appliquées et les métadonnées actuelles, et non sur une suppression ou une transition observée plusieurs jours plus tard. Aucun domaine n’est nécessaire.

Créer votre bucket privé de documents

Dans cette étape, vous autorisez cette VM et créez un bucket temporaire. L’autorisation de l’appareil confirme votre compte d’apprentissage. La gestion des buckets R2 utilise un jeton API distinct, limité à ce compte.

Lancez Bash pour utiliser la syntaxe des commandes ci-dessous, puis accédez au projet préparé et vérifiez ses outils. Gardez ce même terminal ouvert afin que les variables contenant les noms de vos ressources restent disponibles :

bash
cd /home/labex/project/r2-lab
export PATH="$PWD/.tools/node-v22.22.0-linux-x64/bin:$PATH"
node --version
npx wrangler --version

Autorisez le code d’appareil affiché dans votre propre navigateur. Vérifiez le compte d’apprentissage ainsi que les autorisations de lecture du compte et de l’utilisateur demandées avant d’accorder votre consentement :

npx wrangler login --device --browser=false --scopes account:read user:read
npx wrangler whoami --json

Vérifiez que loggedIn: true est présent. Lisez le nom du compte, même si un seul compte est affiché. Remplacez YOUR_ACCOUNT_ID ci-dessous par l’ID réel de 32 caractères de ce compte. openssl rand -hex 6 génère douze caractères hexadécimaux aléatoires afin d’éviter tout conflit avec une exécution précédente. Le document here-document crée un fichier de configuration standard ; le shell y remplace vos variables.

ACCOUNT_ID=YOUR_ACCOUNT_ID
RUN_ID=$(openssl rand -hex 6)
NAME="labex-c05-r07-$RUN_ID"
BUCKET="$NAME-docs"
cat > wrangler.jsonc <<JSON
{"name":"$NAME","account_id":"$ACCOUNT_ID","compatibility_date":"2026-07-30","r2_buckets":[{"binding":"DOCUMENTS","bucket_name":"$BUCKET"}]}
JSON

Pour gérer le bucket, ouvrez la page API Tokens de votre profil Cloudflare et créez un jeton personnalisé portant un nom lié à ce laboratoire. Accordez l’autorisation Account → Workers R2 Storage → Edit, puis limitez Account Resources au compte d’apprentissage dont vous avez enregistré l’ID. Définissez une expiration courte. N’incluez aucun autre compte ni aucune autorisation sans rapport. Ce jeton de gestion sert à administrer les buckets, notamment à les créer et à les supprimer. Plus loin dans cette même étape, vous créez un jeton distinct limité aux objets de ce bucket pour les opérations du SDK S3.

Copiez le jeton une seule fois dans cette invite de la VM masquée. umask 077 limite l’accès au fichier à votre utilisateur ; read -s masque la saisie. Le fichier utilise la variable de jeton standard de Wrangler et est exclu de Git.

umask 077
read -r -s -p 'R2 management API token: ' R2_MANAGEMENT_TOKEN; printf '\n'
printf 'CLOUDFLARE_API_TOKEN=%s\n' "$R2_MANAGEMENT_TOKEN" > .env.management
unset R2_MANAGEMENT_TOKEN

Utilisez --env-file=.env.management uniquement pour les commandes de gestion R2 ; la commande whoami normale continue de vérifier l’autorisation de l’appareil de la VM.

Placez --env-file à la fin de chaque commande Wrangler pour que sa liste de fichiers ne soit pas étendue au nom de la commande. Après la création de chaque compartiment, si Wrangler propose d’ajouter une liaison à la configuration, saisissez n et appuyez sur Entrée. La configuration contient déjà la liaison prévue.

npx wrangler r2 bucket create "$BUCKET" --env-file=.env.management

Listez vos buckets et recherchez le nom généré exact. Les autres buckets appartiennent à d’autres travaux ; ne les modifiez pas.

npx wrangler r2 bucket list --env-file=.env.management

Dans le Dashboard, ouvrez Storage & databases → R2 → Overview, sélectionnez ce bucket exact et vérifiez que la liste des objets est vide. Dans ses paramètres, laissez l’URL de développement publique et les domaines personnalisés désactivés. Le nom du bucket dans le Dashboard confirme son identité ; les vérifications de téléchargement ultérieures prouveront que les octets sont bien stockés.

L’API compatible S3 permet aux SDK de stockage standard d’accéder à R2. Elle utilise une paire de clés d’accès distincte du jeton d’appareil de Wrangler. Dans R2 Overview, sélectionnez Account Details → API Tokens → Manage, puis créez un User API token portant le nom de la ressource générée pour ce laboratoire. Choisissez Object Read & Write, limitez le jeton à ce nouveau bucket exact et sélectionnez une expiration courte si le formulaire le propose. Ne choisissez pas tous les buckets ni l’accès Admin. Gardez cette page de jeton ouverte jusqu’à avoir enregistré le secret à usage unique.

Utilisez les invites Bash suivantes dans la VM. read -s masque la saisie ; umask 077 rend le fichier d’identifiants lisible uniquement par votre utilisateur. Ces noms sont les variables d’environnement standard de l’AWS SDK. Collez l’Access Key ID et la Secret Access Key dans les invites correspondantes, puis appuyez sur Entrée. Ne collez pas la valeur du jeton API général.

umask 077
read -r -s -p 'Access Key ID: ' AWS_ACCESS_KEY_ID; printf '\n'
read -r -s -p 'Secret Access Key: ' AWS_SECRET_ACCESS_KEY; printf '\n'
printf 'AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\n' "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" > .env.s3
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY

Écrivez un client SDK standard réutilisable. Le SDK exige une chaîne de région ; R2 utilise auto. La lecture de la configuration existante garantit que les opérations de la CLI et du SDK ciblent le même compte et le même bucket.

cat > storage.mjs <<'JS'
import { S3Client } from "@aws-sdk/client-s3";
import { readFileSync } from "node:fs";
const config = JSON.parse(readFileSync("wrangler.jsonc", "utf8"));
export const Bucket = config.r2_buckets[0].bucket_name;
export const s3 = new S3Client({
  region: "auto",
  endpoint: `https://${config.account_id}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
  }
});
JS

Appliquer des règles de cycle de vie spécifiques aux préfixes

Dans cette étape, vous configurez une politique de cycle de vie, c’est-à-dire un ensemble d’actions de stockage que R2 applique avec le vieillissement des objets. Les exportations temporaires doivent expirer, tandis que les manuels conservés restent en dehors de ces règles. Une transition de classe de stockage modifie la classe de facturation et d’accès ; elle ne supprime pas l’objet.

Ce nouveau bucket temporaire utilise deux règles : les objets temporary/ expirent après deux jours et les téléchargements non terminés sous ce préfixe sont annulés après un jour ; les objets archive/ passent à Infrequent Access après trente jours. Rien ne cible retained/.

L’API exprime les durées en secondes : un jour correspond à 86 400 secondes. Écrivez la politique avec un here-document entre apostrophes afin de conserver son JSON :

cat > lifecycle.json <<'JSON'
{
  "rules": [
    {
      "id": "temporary-exports",
      "enabled": true,
      "conditions": {
        "prefix": "temporary/"
      },
      "deleteObjectsTransition": {
        "condition": {
          "type": "Age",
          "maxAge": 172800
        }
      },
      "abortMultipartUploadsTransition": {
        "condition": {
          "type": "Age",
          "maxAge": 86400
        }
      }
    },
    {
      "id": "archive-transition",
      "enabled": true,
      "conditions": {
        "prefix": "archive/"
      },
      "storageClassTransitions": [
        {
          "condition": {
            "type": "Age",
            "maxAge": 2592000
          },
          "storageClass": "InfrequentAccess"
        }
      ]
    }
  ]
}
JSON
npx wrangler r2 bucket lifecycle set "$BUCKET" --file lifecycle.json --env-file=.env.management
npx wrangler r2 bucket lifecycle list "$BUCKET" --env-file=.env.management

La commande set remplace la politique ; vérifiez donc uniquement ce nouveau bucket de laboratoire. Exigez les deux préfixes exacts, l’état activé et les durées correctes. N’appliquez pas ce remplacement à un bucket d’application existant. Dans le Dashboard, ouvrez Settings → Object Lifecycle Rules du même bucket et inspectez les actions sans les modifier.

Limite de coût : Infrequent Access entraîne des frais de récupération et une durée minimale de stockage. Ce laboratoire configure une transition future et supprime ses nouveaux objets Standard pendant le nettoyage. Vous n’attendrez pas trente jours, ne forcerez pas de transition et n’affirmerez pas qu’une transition a réellement eu lieu.

Cette vue réelle du Dashboard montre des actions futures configurées : supprimer les objets temporary/ après 2 jours, abandonner les chargements incomplets de ce préfixe après 1 jour et passer les objets archive/ en Infrequent Access après 30 jours. Elle ne prouve pas que ces délais sont écoulés ni que les actions ont eu lieu. L’étape suivante vérifie les métadonnées actuelles ; retained/ est hors des deux préfixes.

Règles de cycle de vie par préfixe activées

Inspecter les métadonnées d’expiration nouvellement appliquées

Dans cette étape, vous téléversez de nouveaux objets après avoir appliqué la politique. R2 indique que les nouveaux objets reflètent une expiration applicable dans x-amz-expiration ; les objets existants peuvent mettre plus de temps à refléter une règle modifiée. Le SDK expose cet en-tête sous le nom Expiration.

cat > seed.mjs <<'JS'
import { PutObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "node:fs";
import { s3, Bucket } from "./storage.mjs";
for (const Key of ["temporary/export.txt", "archive/export.txt"]) {
  await s3.send(new PutObjectCommand({ Bucket, Key, Body: readFileSync("document.txt"), ContentType: "text/plain" }));
}
await s3.send(new PutObjectCommand({ Bucket, Key: "retained/handbook.txt", Body: readFileSync("retained.txt"), ContentType: "text/plain" }));
for (const Key of ["temporary/export.txt", "archive/export.txt", "retained/handbook.txt"]) {
  const head = await s3.send(new HeadObjectCommand({ Bucket, Key }));
  console.log({ key: Key, expiration: head.Expiration || "none", storageClass: head.StorageClass || "STANDARD" });
}
JS
node --env-file=.env.s3 seed.mjs

Exigez une date d’expiration pour temporary/export.txt, aucune expiration de suppression pour le manuel conservé et un stockage Standard pour le nouvel objet d’archive. La transition future est prouvée par la règle distante, et non par une classe de stockage IA actuelle. Si les métadonnées d’expiration attendues pour le nouvel objet sont absentes, inspectez le préfixe et la politique appliqués ; ne considérez pas cela comme une vérification d’expiration réussie.

Téléchargez l’objet conservé et comparez ses octets avec ceux d’origine :

npx wrangler r2 object get "$BUCKET/retained/handbook.txt" --remote --file retained-download.txt --env-file=.env.management
cmp retained.txt retained-download.txt

La lecture réussie de la politique et la possibilité de lire l’objet conservé établissent le résultat limité de ce laboratoire. La suppression réelle du cycle de vie est asynchrone et peut se produire après l’expiration nominale ; ce laboratoire n’évalue pas un événement survenant plusieurs heures plus tard.

Vider explicitement le stockage du laboratoire

Dans cette étape, vous supprimez maintenant les trois objets de test au lieu de dépendre de leurs futures actions de cycle de vie. Aucun téléchargement incomplet n’a été créé dans ce laboratoire, mais vous devez également inventorier cette catégorie : une simple liste d’objets ne permet pas de prouver qu’un bucket ne contient aucune partie inachevée.

cat > empty.mjs <<'JS'
import { DeleteObjectCommand, ListObjectsV2Command, ListMultipartUploadsCommand } from "@aws-sdk/client-s3";
import { s3, Bucket } from "./storage.mjs";
for (const Key of ["temporary/export.txt", "archive/export.txt", "retained/handbook.txt"]) await s3.send(new DeleteObjectCommand({ Bucket, Key }));
const objects = await s3.send(new ListObjectsV2Command({ Bucket }));
const uploads = await s3.send(new ListMultipartUploadsCommand({ Bucket }));
console.log("Objects:", objects.Contents || []);
console.log("Incomplete uploads:", uploads.Uploads || []);
JS
node --env-file=.env.s3 empty.mjs

Exigez des tableaux vides pour les objets et les téléchargements incomplets. Si vous avez créé une session multipart pendant vos essais, utilisez l’opération d’annulation du laboratoire précédent avec la clé détenue et l’ID de téléchargement exacts, puis répétez ces listes en lecture seule. N’ignorez jamais silencieusement les échecs des requêtes de liste.

Supprimer le bucket vide et sa politique

Dans cette étape, vous supprimez le bucket qui vous appartient une fois la vérification des objets et des téléchargements terminée. La politique fait partie de la configuration du bucket et disparaît avec lui.

npx wrangler r2 bucket delete "$BUCKET" --env-file=.env.management
npx wrangler r2 bucket list --env-file=.env.management

Confirmez le nom généré exact. Exigez que ce nom soit absent d’une liste authentifiée exécutée avec succès. Effectuez la vérification de suppression sur la plateforme avant de révoquer l’identifiant de gestion.

Révoquer l’identifiant du laboratoire et se déconnecter

Dans cette étape, vous fermez les accès laissés par cet exercice. Sur la page R2 API Tokens, révoquez uniquement le jeton d’objet nommé pour ce laboratoire. Sur la page API Tokens de votre profil, révoquez le jeton de gestion R2 distinct que vous avez créé pour ce laboratoire. La suppression d’un bucket ne révoque pas un jeton, et la déconnexion de Wrangler ne révoque pas les identifiants S3.

Après la révocation, supprimez le fichier d’identifiants local et déconnectez cette VM :

rm .env.s3 .env.management
npx wrangler logout

Inspectez l’identité structurée. Son état différent de zéro est attendu lorsque vous êtes déconnecté :

npx wrangler whoami --json || true

Exigez loggedIn: false et conservez votre connexion habituelle au Dashboard. La plateforme vérifie la suppression locale des identifiants et la déconnexion de Wrangler. Les deux révocations de jetons sont des vérifications manuelles dans le Dashboard pour ce laboratoire ; elles ne sont pas déduites de la suppression des fichiers.

Résumé

Appliquez des règles d’expiration ciblées, de transition future du stockage et de nettoyage des téléchargements multipart, inspectez les métadonnées actuelles, préservez les données conservées et effectuez un nettoyage explicite.