Si vous gérez du stockage S3 sur AWS, la plupart de vos buckets en production ont besoin d’une politique parmi six, et chacune a un exemple fonctionnel ci-dessous. Une politique de bucket est un document JSON attaché au bucket qui dit qui peut faire quoi avec lui et ses objets. Les six forcent les connexions chiffrées (TLS, Transport Layer Security), laissent une seule distribution CloudFront lire le bucket et accordent l’accès à un autre compte AWS. CloudFront est le réseau de diffusion de contenu d’AWS. Les autres limitent l’accès à un point de terminaison VPC, un chemin privé entre votre nuage privé virtuel et S3. Elles exigent aussi votre clé KMS (Key Management Service) au téléversement, ou servent un site statique public.
Deux règles vous évitent les ennuis. Testez chaque Deny contre votre propre accès administrateur avant de vous y fier, car un refus mal écrit vous bloque aussi. Pour un accès entre comptes, l’autre compte doit aussi accorder les permissions S3 à ses propres identités, car la politique de bucket ne couvre que la moitié de l’octroi.
Ce qui se passe
Une politique de bucket est une politique de ressource : elle accorde ou refuse l’accès à ce bucket peu importe ce que dit la politique IAM de l’appelant — avec une asymétrie qui compte. Les Allow s’additionnent aux politiques IAM pour les appelants du même compte, mais un Deny bat tout, incluant le root du compte à toutes fins pratiques. C’est de là que viennent les verrouillages : un deny avec une condition écrite à l’envers s’applique à vous aussi, et contrairement aux politiques IAM, vous ne pouvez pas le corriger avec une deuxième politique — il faut le retirer (en root, via delete-bucket-policy, ou avec un dossier au soutien AWS dans le pire cas).
L’autre fait structurel : les actions sur les objets et sur le bucket visent des ARN différents. s3:GetObject s’applique à arn:aws:s3:::bucket/*, s3:ListBucket à arn:aws:s3:::bucket. Chaque politique ci-dessous qui touche aux deux utilise les deux ARN ; celles qui en sautent un échouent de façon déroutante. La référence de chaque action et clé de condition est sur https://docs.aws.amazon.com/AmazonS3/ — gardez-la ouverte pendant que vous écrivez.
Quoi vérifier en premier
- L’état de Block Public Access —
BlockPublicPolicyrejettera une politique que S3 considère publique, etRestrictPublicBucketschange le comportement d’une politique publique existante. - Object Ownership — avec Bucket owner enforced (le défaut pour les nouveaux buckets), les ACL sont mortes et la politique est toute l’histoire ; c’est le mode que vous voulez.
- Qui d’autre a déjà accès via des politiques IAM d’identité — une politique de bucket n’est pas un inventaire complet des accès.
- Si une SCP applique déjà ce que vous vous apprêtez à dupliquer — les deny TLS et chiffrement appartiennent souvent au niveau de l’organisation.
Comment vérifier
# Politique actuelle, lisible
aws s3api get-bucket-policy --bucket my-bucket \
--query Policy --output text | python3 -m json.tool
# S3 traite-t-il ce bucket comme public?
aws s3api get-bucket-policy-status --bucket my-bucket
# Appliquer une politique depuis un fichier
aws s3api put-bucket-policy --bucket my-bucket --policy file://policy.json
Dans la console : S3 > Buckets > votre-bucket > Permissions > Bucket policy. Après application, testez avec une vraie identité non administratrice, pas seulement votre propre session.
Le runbook
- Forcer TLS (à mettre partout). Refuse toute requête en HTTP en clair. Sécuritaire : ça ne restreint pas qui, seulement comment.
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
"Condition": {"Bool": {"aws:SecureTransport": "false"}}
}
- Autoriser CloudFront (Origin Access Control). Le patron moderne utilise le principal de service CloudFront limité à une distribution — pas d’OAI, pas de bucket public :
{
"Sid": "AllowCloudFrontOAC",
"Effect": "Allow",
"Principal": {"Service": "cloudfront.amazonaws.com"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
}}
}
- Lecture/écriture entre comptes. Accordez le root de l’autre compte (en déléguant à son IAM) ou un rôle précis. Rappel : l’autre compte doit aussi accorder les permissions S3 à ses identités — la politique de bucket seule ne leur donne rien.
{
"Sid": "PartnerAccountAccess",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::444455556666:role/data-exchange"},
"Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
}
Gardez Bucket owner enforced activé, pour que les objets qu’ils téléversent vous appartiennent.
- Verrouiller le bucket sur un point de terminaison VPC. Pour les buckets qui ne devraient jamais être touchés que de l’intérieur de votre VPC — voir les points de terminaison passerelle pour S3 pour la moitié réseau :
{
"Sid": "DenyOutsideVpce",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
"Condition": {"StringNotEquals": {"aws:SourceVpce": "vpce-0abcd1234efgh5678"}}
}
C’est LA politique de verrouillage classique : elle bloque aussi la console et votre portable. Prévoyez une exception pour un rôle admin avec une deuxième condition (ArnNotLike sur aws:PrincipalArn) avant de l’appliquer.
- Exiger SSE-KMS au téléversement. Refuse les PUT qui ne demandent pas votre clé. Notez qu’avec le chiffrement par défaut du bucket réglé à SSE-KMS, les PUT non chiffrés sont déjà chiffrés au repos — cette politique sert quand vous devez garantir une clé précise :
{
"Sid": "DenyWrongEncryption",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {"StringNotEquals": {
"s3:x-amz-server-side-encryption-aws-kms-key-id":
"arn:aws:kms:ca-central-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
}}
}
- Lecture publique pour site statique. Seulement après avoir délibérément relâché Block Public Access sur ce seul bucket, et seulement pour du contenu vraiment public :
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-site-bucket/*"
}
En 2026, préférez le patron 2 (CloudFront + OAC) à celui-ci — vous obtenez TLS, la mise en cache et aucun bucket public.
Quand c’est la mauvaise approche
Les politiques de bucket sont le mauvais outil pour l’autorisation par utilisateur ou par locataire à l’intérieur d’une application — ça appartient à votre couche applicative avec des URL présignées ou des identifiants de session restreints, pas à un document de politique plafonné à 20 Ko. Et si vous vous retrouvez à accorder le même compte partenaire sur quinze buckets, le patron demande probablement des S3 Access Points ou un rôle dédié plutôt que quinze politiques.
Erreurs fréquentes
- Écrire un
DenyavecNotPrincipalou une condition inversée, ne rien tester, et barrer dehors toutes les identités incluant la vôtre. - Accorder
s3:GetObjectmais oubliers3:ListBucket, si bien que les clients qui listent puis téléchargent échouent dès la première étape. - Croire que l’octroi dans la politique de bucket suffit pour un appelant d’un autre compte dont la propre politique IAM ne mentionne jamais S3.
- Utiliser des conditions
aws:SourceIpcontre du trafic qui arrive en réalité par un point de terminaison VPC — les IP privées ne matchent jamais des plages CIDR publiques, alors le deny frappe tout le monde.
Prévention
- Gardez les politiques en contrôle de version et appliquez-les par IaC, pour qu’un mauvais deny soit à un
git revertprès. - Testez chaque nouvelle déclaration deny contre un bucket jetable d’abord, avec votre propre rôle, avant qu’elle touche la production.
- Faites rouler IAM Access Analyzer après chaque changement — il lit la politique comme AWS l’évalue, pas comme vous l’avez pensée.
- Standardisez les déclarations 1 et 5 comme base à l’échelle de l’organisation plutôt que de copier-coller par bucket.
Six patrons, deux ARN, une règle sur les deny non testés — ça couvre réellement l’essentiel de ce dont les buckets en production ont besoin. Si personne dans votre équipe ne possède vraiment l’environnement AWS de bout en bout, c’est la racine de la plupart de ces problèmes — Stack Harbor opère des comptes AWS au quotidien sous Opérations AWS, et vous pouvez réserver une revue AWS.