
S3 Inventory produit des rapports planifiés sur les objets d’un compartiment Amazon S3 et certaines de leurs métadonnées. Il permet d’examiner les classes de stockage, le chiffrement ou la réplication d’un ensemble de clés défini. Un rapport contient des métadonnées ; il ne contient pas les fichiers eux-mêmes et ne remplace pas une copie de récupération.
Ce guide configure un rapport CSV quotidien pour un petit préfixe dans un compartiment S3 à usage général, puis examine un manifeste et un fichier de données compressé. La configuration et le script ont été vérifiés localement avec des données fictives. Aucun déploiement AWS, aucune livraison réelle de rapport et aucune évaluation des permissions n’ont été réalisés.
Partez d’une question précise, par exemple : « Quels objets actuels sous exports/ indiquent un échec de réplication ? » Un préfixe et quelques champs choisis facilitent l’examen. Inventory fonctionne chaque jour ou chaque semaine et accepte CSV, ORC et Parquet. Selon AWS, la première livraison peut prendre jusqu’à 48 heures ; ce n’est pas une liste immédiate. Consultez la présentation d’Inventory.
Choisissez entre les objets actuels et toutes les versions. La référence de configuration définit Current et All. Les rapports incluant toutes les versions ajoutent des champs de version et de marqueur de suppression. Compter leurs lignes comme des fichiers actuels peut gonfler les totaux ou inclure ces marqueurs ; le script ci-dessous accepte donc uniquement les rapports Current.
Utilisez CSV pour un petit exercice d’inspection. Pour des analyses répétées, envisagez ORC ou Parquet avec Athena. Séparez les dates de rapport dans vos requêtes : réunir plusieurs rapports quotidiens peut compter le même objet plusieurs fois.
L’exemple utilise deux compartiments à usage général existants dans eu-west-1, détenus par le compte fictif 111122223333. Remplacez le compte, les noms des compartiments, la région et les profils CLI par ceux de votre environnement de test. Choisissez un nouvel identifiant de configuration pour préserver les rapports déjà utilisés.
Le compartiment source contient les objets et la configuration Inventory. La destination reçoit les rapports et doit se trouver dans la même région. Ici, exports/ sélectionne les objets source, tandis que inventory définit le préfixe des rapports à destination. Ces réglages sont distincts.
Enregistrez ce contenu dans inventory-config.json. La référence de destination explique la vérification du compte propriétaire. SSES3 configure le chiffrement des fichiers de rapport ; le champ facultatif EncryptionStatus décrit les objets source. Aucun de ces paramètres ne modifie le chiffrement des objets source.
{
"Destination": {
"S3BucketDestination": {
"AccountId": "111122223333",
"Bucket": "arn:aws:s3:::amzn-s3-demo-inventory-reports",
"Format": "CSV",
"Prefix": "inventory",
"Encryption": {"SSES3": {}}
}
},
"IsEnabled": true,
"Filter": {"Prefix": "exports/"},
"Id": "exports-daily",
"IncludedObjectVersions": "Current",
"OptionalFields": ["Size", "LastModifiedDate", "StorageClass", "ReplicationStatus", "EncryptionStatus"],
"Schedule": {"Frequency": "Daily"}
}
Pour chiffrer les rapports avec SSE-KMS, utilisez une clé gérée par le client et les autorisations nécessaires dans sa politique. AWS ne prend pas en charge la clé gérée aws/s3 pour le chiffrement SSE-KMS des rapports Inventory. Suivez les instructions de configuration actuelles avant ce changement.
Avec la CLI, un administrateur autorisé doit ajouter une permission de livraison à la politique du compartiment de destination. Cet exemple est une déclaration à intégrer au tableau Statement de la politique existante, pas un remplacement de la politique entière :
{
"Sid": "AllowInventoryFromDemoSource",
"Effect": "Allow",
"Principal": {"Service": "s3.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::amzn-s3-demo-inventory-reports/inventory/*",
"Condition": {
"ArnLike": {"aws:SourceArn": "arn:aws:s3:::amzn-s3-demo-source"},
"StringEquals": {
"aws:SourceAccount": "111122223333",
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
Les conditions sur le compte et le compartiment source limitent les sources autorisées à utiliser cette permission de livraison. La ressource limite les écritures au préfixe des rapports. Examinez aussi les déclarations Deny existantes. L’identité qui configure Inventory a besoin de s3:PutInventoryConfiguration sur la source ; la lecture de la configuration nécessite s3:GetInventoryConfiguration.
Le lecteur des rapports doit pouvoir accéder aux fichiers à destination et, si nécessaire, les déchiffrer. Lire un rapport est distinct de lire les objets d’origine. Les noms et les métadonnées peuvent révéler des informations sur les données stockées : limitez leur accès aux lecteurs prévus. Cet exemple de politique concerne les compartiments à usage général ; les compartiments de répertoire utilisent d’autres permissions et identités de service pour Inventory.
Après vérification de la politique de destination et remplacement des valeurs fictives, cette commande enregistre la configuration activée et lance la production planifiée des rapports. Elle modifie AWS ; ce n’est pas une simulation :
aws s3api put-bucket-inventory-configuration --bucket amzn-s3-demo-source --id exports-daily --inventory-configuration file://inventory-config.json --expected-bucket-owner 111122223333 --profile inventory-admin --region eu-west-1
La référence de la commande put décrit les paramètres. Vérifiez le code de sortie, puis récupérez la configuration enregistrée :
aws s3api get-bucket-inventory-configuration --bucket amzn-s3-demo-source --id exports-daily --expected-bucket-owner 111122223333 --profile inventory-admin --region eu-west-1
Comparez la configuration renvoyée aux valeurs prévues : filtre source, destination, compte, fréquence, sélection des versions, champs et chiffrement. Une relecture réussie prouve l’existence de la configuration. La livraison dépend encore du calendrier du service et de son accès à la destination.
Après livraison, repérez le rapport sous le préfixe de destination, le nom du compartiment source, l’identifiant de configuration et l’horodatage du rapport. Téléchargez ses fichiers manifest.json et manifest.checksum. Le manifeste indique les clés exactes des fichiers de données, leurs tailles, leurs sommes de contrôle et leur schéma. L’horodatage correspond au début de la génération. AWS décrit cette organisation dans Locating your inventory list.
Utilisez un nouveau dossier de travail local. Dans les commandes suivantes, remplacez REPORT_TIMESTAMP par l’horodatage livré et DATA_FILE_KEY par une clé complète du tableau files du manifeste. Cette clé est relative au compartiment de destination et contient déjà son préfixe. Réutilisez exactement la même clé pour lancer le script.
aws s3 cp "s3://amzn-s3-demo-inventory-reports/inventory/amzn-s3-demo-source/exports-daily/REPORT_TIMESTAMP/manifest.json" ./manifest.json --profile inventory-reader --region eu-west-1
aws s3 cp "s3://amzn-s3-demo-inventory-reports/inventory/amzn-s3-demo-source/exports-daily/REPORT_TIMESTAMP/manifest.checksum" ./manifest.checksum --profile inventory-reader --region eu-west-1
aws s3 cp "s3://amzn-s3-demo-inventory-reports/DATA_FILE_KEY" ./report-part.csv.gz --profile inventory-reader --region eu-west-1
Un rapport peut contenir plusieurs fichiers de données. La lecture d’un seul fichier donne un résultat partiel. Traitez tous les fichiers du manifeste sélectionné avant d’annoncer des totaux pour ce rapport ; ne mélangez pas tous les fichiers du dossier de données à destination, qui peuvent appartenir à plusieurs dates de rapport.
Enregistrez ce code Python 3 sous inspect-inventory.py. Il compare le manifeste téléchargé à sa somme de contrôle, vérifie le fichier compressé sélectionné avec l’entrée correspondante, puis lit le CSV avec les noms de champs de fileSchema. Il ne suppose ni que la première ligne contient un en-tête ni que les champs facultatifs occupent toujours les mêmes positions.
import csv, gzip, hashlib, json, sys
from collections import Counter
from pathlib import Path
from urllib.parse import unquote
manifest_path, checksum_path, data_key, local_file = sys.argv[1:]
manifest_bytes = Path(manifest_path).read_bytes()
expected = Path(checksum_path).read_text(encoding='utf-8').strip().lower()
if hashlib.md5(manifest_bytes, usedforsecurity=False).hexdigest() != expected:
raise SystemExit('Manifest checksum does not match.')
manifest = json.loads(manifest_bytes)
fields = [name.strip() for name in manifest['fileSchema'].split(',')]
required = {'Bucket', 'Key', 'Size', 'StorageClass', 'ReplicationStatus', 'EncryptionStatus'}
if manifest['fileFormat'] != 'CSV' or not required.issubset(fields):
raise SystemExit('Expected CSV with the configured metadata fields.')
if len(fields) != len(set(fields)) or {'VersionId', 'IsLatest', 'IsDeleteMarker'} & set(fields):
raise SystemExit('Use a Current-only report with unique field names.')
matches = [item for item in manifest['files'] if item['key'] == data_key]
if len(matches) != 1:
raise SystemExit('Data key must match exactly one manifest entry.')
entry = matches[0]
digest = hashlib.md5(usedforsecurity=False)
with open(local_file, 'rb') as stream:
for block in iter(lambda: stream.read(1024 * 1024), b''):
digest.update(block)
if Path(local_file).stat().st_size != entry['size'] or digest.hexdigest() != entry['MD5checksum'].lower():
raise SystemExit('Downloaded data file does not match its manifest.')
rows = total_bytes = review_count = 0
encryption, replication = Counter(), Counter()
with gzip.open(local_file, 'rt', encoding='utf-8', newline='') as stream:
for values in csv.reader(stream, strict=True):
if len(values) != len(fields):
raise SystemExit('Unexpected CSV column count.')
row = dict(zip(fields, values))
if row['Bucket'] != manifest['sourceBucket']:
raise SystemExit('Unexpected source bucket in data file.')
size = int(row['Size'])
if size < 0:
raise SystemExit('Invalid negative object size.')
rows += 1
total_bytes += size
encryption[row['EncryptionStatus'] or 'UNKNOWN'] += 1
replication[row['ReplicationStatus'] or 'UNKNOWN'] += 1
if row['EncryptionStatus'] == 'NOT-SSE' or row['ReplicationStatus'] == 'FAILED':
review_count += 1
print(json.dumps({'review_key': unquote(row['Key'], errors='strict'),
'encryption': row['EncryptionStatus'],
'replication': row['ReplicationStatus']}))
print(json.dumps({'scope': 'one data file', 'manifest_files': len(manifest['files']),
'rows': rows, 'object_bytes': total_bytes, 'review_count': review_count,
'encryption': dict(encryption), 'replication': dict(replication)}))
python inspect-inventory.py manifest.json manifest.checksum "DATA_FILE_KEY" report-part.csv.gz
Utilisez python3 si c’est le nom de votre commande Python. Traitez des rapports fiables téléchargés par votre connexion AWS authentifiée. MD5 vérifie ici la correspondance avec le manifeste fourni ; il ne garantit pas l’authenticité. Vérifiez le code de sortie du script avant d’exploiter ses résultats.
La sortie présente les éléments à examiner et un résumé du seul fichier sélectionné. Les statuts vides sont comptés comme UNKNOWN, pas comme des réussites. L’exemple repère NOT-SSE et FAILED ; il ne constitue pas une politique de conformité complète. Un objet chiffré avec une clé KMS différente de celle exigée demande par exemple un contrôle supplémentaire.
Notre fichier de test local contenait sept lignes, représentant 1 510 octets d’objets et trois éléments à examiner. Les tests ont confirmé le rejet des fichiers et manifestes modifiés, des colonnes manquantes, des lignes de largeur incorrecte, des clés de fichier absentes du manifeste et des schémas incluant toutes les versions. Le réordonnancement des colonnes et les clés encodées ont été traités correctement, y compris un signe plus littéral. Ces résultats viennent de données fictives, pas d’un compartiment AWS.
Inventory offre une cohérence éventuelle pour les ajouts, les remplacements et les suppressions. Un rapport peut donc avoir du retard sur l’état actuel. Avant d’agir sur un résultat, demandez les métadonnées récentes avec la clé décodée du rapport :
aws s3api head-object --bucket amzn-s3-demo-source --key "exports/review.csv" --expected-bucket-owner 111122223333 --profile inventory-reader --region eu-west-1
Cet exemple HeadObject lit les métadonnées de l’objet actuel et nécessite la permission de lecture source correspondante. Remplacez exports/review.csv par la clé examinée. L’examen d’une version précise demande aussi son identifiant. Une écriture ultérieure peut encore modifier l’objet après ce contrôle ; une correction automatisée doit donc gérer les modifications concurrentes.
Pour les résultats de chiffrement, notre guide du chiffrement S3 (en anglais) explique comment vérifier la méthode et la clé. Pour une réplication en échec ou en attente, consultez le guide de réplication. Un statut Inventory ne suffit pas à prouver qu’une réplique permet une récupération.
Si le premier rapport n’est pas arrivé, tenez compte du délai initial documenté, puis vérifiez l’activation, le filtre source, la région et la politique de destination, ainsi que les éventuelles permissions KMS. Un JSON valide ou une configuration enregistrée ne vérifient pas ces conditions d’exécution.
Prévoyez les frais Inventory et S3, le stockage des rapports et les éventuelles requêtes analytiques. Conservez assez de rapports pour les comparaisons, puis appliquez une politique de cycle de vie limitée aux anciens rapports. Séparez cette décision de rétention de la suppression des objets source.
Cette procédure utilise Amazon S3 Inventory. Une API de stockage compatible S3 ne garantit pas la prise en charge de cette fonction AWS, et aucune compatibilité Hivenet n’a été testée ici.
Choisissez une charge de travail d’IA, de calcul ou de stockage à tester sur Hivenet, ou échangez avec notre équipe sur sa mise en production.