Quand un appel AWS échoue avec AccessDenied, le message d’erreur nomme habituellement le type de politique qui l’a refusé. IAM (Identity and Access Management, le service de permissions d’AWS) vérifie plusieurs couches de politiques à chaque requête, alors modifier la mauvaise peut faire perdre des heures. La clause à la fin du message, comme « because no identity-based policy allows the action » ou « with an explicit deny in a service control policy », indique la couche à corriger. Une politique de contrôle de service (SCP) est un garde-fou fixé pour toute une organisation dans AWS Organizations. Lisez le principal (l’utilisateur ou le rôle qui fait l’appel), l’action, la ressource et cette clause finale. Confirmez ensuite la décision avec le simulateur de politiques et CloudTrail, le journal des appels d’API d’AWS.
Ce qui se passe
Chaque appel d’API AWS passe par une seule évaluation : un Deny explicite gagne partout; sinon, la requête a besoin d’un Allow qui survit à chaque couche applicable. Les couches, dans l’ordre où elles mordent habituellement : les politiques de contrôle de service (SCP) d’AWS Organizations (comptes membres seulement), la frontière de permissions si le principal en a une, les politiques de session si les identifiants viennent d’un AssumeRole avec une politique restreinte, et enfin les politiques basées sur l’identité et sur la ressource que tout le monde regarde en premier. Pour certains services — KMS est le cas célèbre — la politique de ressource doit participer : une politique IAM seule ne peut pas accorder kms:Decrypt si la politique de la clé ne délègue pas à IAM.
Le message d’erreur encode quelle couche a dit non. « No identity-based policy allows » veut dire que rien n’accordait l’action — le cas plate et fréquent. « Explicit deny in a service control policy » veut dire que le garde-fou au niveau du compte a tiré, et aucune retouche IAM dans le compte membre ne va régler ça. « Explicit deny in a resource-based policy » pointe vers une politique de compartiment, de clé ou de file. « Because no permissions boundary allows » veut dire que la politique d’identité accorde l’action, mais que la frontière la plafonne. Comme la clause nomme la couche, la plupart des billets Access Denied se règlent en lisant l’erreur au complet plutôt que la première ligne.
Le deuxième piège, c’est l’identité. La moitié des billets Access Denied qu’on trie, c’est la bonne politique évaluée contre le mauvais principal — un développeur qui teste avec un vieux profil CLI, un conteneur qui roule sous le rôle de tâche au lieu du rôle d’exécution, ou un Lambda qui utilise son propre rôle pendant que l’ingénieur modifie un utilisateur sans rapport.
Quoi vérifier en premier
- Qui a vraiment fait l’appel. Exécutez
aws sts get-caller-identitydans l’environnement exact qui a échoué. Un ARN de rôle assumé ressemble àarn:aws:sts::111122223333:assumed-role/RoleName/session— la politique à inspecter est surRoleName, pas sur un utilisateur. - Le texte complet de l’erreur. Capturez le message au complet, incluant la clause « because »; elle nomme le type de politique en défaut.
- L’ARN de ressource dans l’erreur.
s3:ListBucketa besoin de l’ARN du compartiment,s3:GetObjecta besoin dearn:aws:s3:::bucket/*— un ARN de la mauvaise forme est le refus auto-infligé le plus fréquent. - Si une SCP s’applique. Si le compte est dans une organisation, les refus de région et de service viennent souvent du parent, pas du compte. Notre article sur la base SCP couvre ce que ces garde-fous bloquent typiquement.
- Le chiffrement sur la ressource. Un objet S3 sous SSE-KMS retourne Access Denied quand l’appelant n’a pas
kms:Decrypt, même avec des permissions S3 complètes.
Comment vérifier
Confirmez le principal, puis rejouez la décision :
# Qui suis-je, vraiment?
aws sts get-caller-identity
# Simuler l'appel exact contre les vraies politiques attachées
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:role/app-role \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::prod-assets/config.json
Le simulateur retourne un EvalDecision par action. Dans un compte membre, il inclut la décision de l’organisation (OrganizationsDecisionDetail.AllowedByOrganizations) et il respecte les frontières de permissions — mais il ne va pas chercher les politiques de ressource tout seul : passez --resource-policy quand une politique de compartiment ou de file est suspecte. La version console vit sous IAM > Policy simulator.
Ensuite, trouvez le vrai événement refusé dans CloudTrail — chemin console CloudTrail > Event history, filtre par nom d’utilisateur ou nom d’événement, ou depuis la CLI :
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetObject \
--max-results 20 \
--query 'Events[].CloudTrailEvent' --output text | grep -i accessdenied
L’enregistrement montre le userIdentity exact, le errorCode (AccessDenied ou Client.UnauthorizedOperation) et souvent un errorMessage qui correspond à la clause « because ». Notez que les événements de données S3 (GetObject, PutObject) n’apparaissent que si la journalisation des événements de données est activée sur le trail; les événements de gestion sont toujours dans Event history pendant 90 jours. La référence sur la logique d’évaluation dans la documentation IAM mérite de rester ouverte pendant la lecture.
Le correctif
- Corrigez d’abord la forme de l’ARN. Si la politique d’identité accorde l’action mais que la ressource dans l’erreur ne correspond pas à l’élément
Resource— compartiment vsbucket/*, région ou ID de compte manquant dans l’ARN, mauvaise partition — corrigez l’ARN. Ça règle plus de refus que n’importe quel autre changement. - Ajoutez le Allow manquant, étroitement. Quand la clause dit « no identity-based policy allows », ajoutez l’action précise sur la ressource précise à la politique du rôle. Résistez au
*— ça ferme le billet et ça échoue au prochain audit. - Remontez le deny explicite jusqu’à sa couche. Pour un refus SCP, le changement se fait dans le compte de gestion, habituellement contre un garde-fou de région ou de service. Pour un refus de politique de ressource, lisez la politique du compartiment, de la clé ou de la file à la recherche de
Denyavec des conditions (aws:SourceVpce,aws:SecureTransport, conditions d’ID d’organisation) que votre appel ne satisfait pas. - Traitez KMS comme un problème à part. Accordez
kms:Decrypt(etkms:GenerateDataKeypour les écritures) sur la clé précise, et confirmez que la politique de la clé accorde au principal ou contient l’énoncé standard qui active les politiques IAM pour le compte. - Vérifiez la frontière et la politique de session en dernier. Si le principal a une frontière de permissions, la permission effective est l’intersection — la politique d’identité seule ne prouve rien. Même chose pour des identifiants émis avec une politique de session.
Quand ce n’est pas la bonne approche
Si le même refus revient sans arrêt à travers plusieurs rôles, arrêtez de rapiécer des politiques une à la fois — le compte a besoin d’un modèle de permissions, pas d’une autre exception. Et si l’appelant refusé est un principal inconnu qui sonde S3 ou IAM, c’est un événement de sécurité, pas un bogue : laissez le refus en place et enquêtez via votre base CloudTrail et GuardDuty avant toute chose.
Erreurs fréquentes
- Modifier la politique d’un utilisateur pendant que la charge de travail roule sous un rôle — partez toujours de
get-caller-identity. - Lire seulement la première ligne de l’erreur et manquer la clause « because » qui nomme la couche en défaut.
- Supposer que le simulateur couvre les politiques de ressource par défaut — il faut les lui fournir explicitement.
- Accorder
Action: "*"« temporairement » pour débloquer un déploiement; les jokers temporaires sont les objets les plus permanents d’AWS.
Prévention
- Standardisez la clause d’erreur enrichie dans les runbooks : le triage commence par principal, clause d’erreur, simulateur, CloudTrail.
- Gardez CloudTrail actif dans chaque compte avec les événements de données sur les compartiments sensibles, pour que les refus restent cherchables après coup.
- Préférez les rôles aux utilisateurs partout, pour que « qui a fait l’appel » ait une seule réponse par charge de travail.
- Passez les nouvelles politiques dans
simulate-principal-policyen CI avant qu’elles soient déployées, pas après qu’elles refusent.
La plupart des incidents Access Denied prennent dix minutes quand l’ordre de lecture est principal, clause d’erreur, simulateur, CloudTrail — et des heures quand quelqu’un commence par modifier du JSON. 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.