Structure de base d'une politique IAM : Effect, Action, Resource et Condition expliqués

La première fois qu'on ouvre une politique IAM JSON en production pour diagnostiquer un accès refusé, les quatre éléments Effect, Action, Resource et Condition semblent évidents — jusqu'au moment où une permission ne se comporte pas comme prévu et qu'on réalise qu'on avait mal compris la portée d'un seul de ces champs. Comprendre la structure d'une politique IAM, c'est comprendre comment AWS évalue chaque requête API avant de l'autoriser ou de la rejeter.

TL;DR — Structure d'une politique IAM

Élément Rôle Obligatoire
Effect Autorise (Allow) ou refuse (Deny) explicitement Oui
Action Quelle(s) opération(s) API sont ciblées Oui
Resource Sur quel(s) objet(s) AWS s'applique la règle Oui
Condition Contraintes contextuelles supplémentaires (IP, MFA, tag…) Non

Comment AWS évalue une politique IAM

Avant d'examiner chaque élément, il faut comprendre le modèle d'évaluation. Par défaut, toute action est implicitement refusée. Un Allow explicite est nécessaire pour qu'une requête passe. Mais un Deny explicite écrase toujours un Allow, quelle que soit la source de ce dernier — politique d'identité, politique de ressource, ou permission de limite (Permissions Boundary). C'est la règle la plus importante du moteur d'évaluation IAM.

graph TD A["Requête API reçue"] --> B{"Deny explicite
dans une politique ?"} B -- Oui --> C["REFUS — AccessDenied"] B -- Non --> D{"Allow explicite
dans une politique ?"} D -- Non --> E["REFUS implicite — AccessDenied"] D -- Oui --> F{"Condition présente
et satisfaite ?"} F -- Non satisfaite --> E F -- Satisfaite ou absente --> G["ACCÈS AUTORISÉ"]
  1. Deny explicite — si une instruction Deny correspond à la requête, AWS rejette immédiatement, sans évaluer le reste.
  2. Allow explicite — si aucune instruction Deny ne correspond, AWS cherche un Allow dans l'ensemble des politiques applicables.
  3. Deny implicite — si aucun Allow n'est trouvé, la requête est refusée par défaut.
  4. Condition — si présente, elle doit être satisfaite pour que l'instruction soit considérée comme correspondante.

Anatomie d'une instruction de politique IAM

Une politique IAM est un document JSON composé d'un tableau Statement. Chaque élément du tableau est une instruction indépendante. Voici la structure minimale :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ExempleInstruction",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::mon-bucket/*"
    }
  ]
}

Le champ Version doit toujours être 2012-10-17 — c'est la version du langage de politique qui supporte les variables de politique comme ${aws:username}. L'ancienne valeur 2008-10-17 ne les supporte pas.

L'élément Effect : Allow ou Deny

L'élément Effect n'accepte que deux valeurs : Allow ou Deny. C'est la décision que cette instruction prend si toutes les autres conditions sont remplies.

Le piège classique : on suppose qu'un Allow dans une politique d'identité suffit, mais une politique de ressource (bucket S3, clé KMS) ou une SCP (Service Control Policy) au niveau du compte peut contenir un Deny explicite qui écrase tout. Quand un accès est refusé de manière inattendue, vérifier les Deny explicites dans toutes les couches est la première étape — pas d'ajouter un autre Allow.

Un Deny explicite fonctionne comme un verrou physique sur une porte : peu importe combien de clés (Allow) vous avez, le verrou gagne toujours.

L'élément Action : cibler des opérations API spécifiques

L'élément Action spécifie quelle(s) opération(s) API AWS sont concernées par l'instruction. Le format est service:OperationAPI, par exemple s3:PutObject, ec2:DescribeInstances, ou iam:CreateRole.

Plusieurs actions peuvent être spécifiées sous forme de liste, et le caractère générique * est supporté :

"Action": [
  "s3:GetObject",
  "s3:PutObject",
  "s3:DeleteObject"
]

Ou avec un générique de service :

"Action": "s3:*"

Un point souvent mal compris : certaines actions de lecture ou de liste (Describe*, List*, Get*) ne supportent pas la restriction au niveau de la ressource — elles nécessitent "Resource": "*". Tenter de les restreindre à un ARN spécifique résulte en une politique invalide ou en un comportement inattendu. La référence d'autorisation de service AWS documente explicitement quelles actions supportent la restriction par ressource.

L'élément Resource : définir la portée des objets AWS

L'élément Resource identifie le ou les objets AWS sur lesquels l'instruction s'applique, exprimés sous forme d'ARN (Amazon Resource Name). C'est ici que la précision du principe du moindre privilège se joue concrètement.

"Resource": "arn:aws:s3:::mon-bucket/*"

Quelques formats ARN courants :

Service Exemple d'ARN
S3 (bucket) arn:aws:s3:::mon-bucket
S3 (objets) arn:aws:s3:::mon-bucket/*
Lambda arn:aws:lambda:us-east-1:123456789012:function:MaFonction
IAM Role arn:aws:iam::123456789012:role/MonRole
DynamoDB table arn:aws:dynamodb:us-east-1:123456789012:table/MaTable

Le générique * seul signifie 'toutes les ressources'. C'est parfois inévitable pour certaines actions qui ne supportent pas la restriction par ressource, mais son usage doit être justifié explicitement dans toute revue de politique.

Un détail important pour S3 : pour autoriser à la fois les opérations sur le bucket lui-même (s3:ListBucket) et sur ses objets (s3:GetObject), deux ARN distincts sont nécessaires dans la même instruction ou dans deux instructions séparées — arn:aws:s3:::mon-bucket et arn:aws:s3:::mon-bucket/*. Utiliser uniquement le générique /* ne couvre pas les actions au niveau du bucket.

L'élément Condition : restreindre le contexte d'application

L'élément Condition est facultatif mais puissant. Il permet d'ajouter des contraintes contextuelles qui doivent être satisfaites pour que l'instruction s'applique. Si les conditions ne sont pas remplies, l'instruction est ignorée — comme si elle n'existait pas.

La structure d'une condition est :

"Condition": {
  "OperateurDeCondition": {
    "CleDeCondition": "Valeur"
  }
}

Exemple concret — autoriser l'accès uniquement depuis une plage IP spécifique :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::mon-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}

Exemple avec MFA obligatoire :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:DeleteAccessKey",
      "Resource": "arn:aws:iam::123456789012:user/${aws:username}",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Les opérateurs de condition les plus courants incluent StringEquals, StringLike, ArnEquals, IpAddress, Bool, DateLessThan, et leurs variantes négatives (StringNotEquals, etc.). La liste complète est documentée dans la référence des opérateurs de condition IAM.

graph LR COND["Condition"] --> OP["Opérateur
ex: StringEquals"] OP --> KEY["Clé de condition
ex: aws:SourceIp"] KEY --> VAL["Valeur attendue
ex: 203.0.113.0/24"] VAL --> EVAL{"Condition
satisfaite ?"} EVAL -- Oui --> MATCH["Instruction applicable"] EVAL -- Non --> SKIP["Instruction ignorée"]
  1. Opérateur de condition — définit le type de comparaison (égalité de chaîne, plage IP, booléen…).
  2. Clé de condition — la variable contextuelle évaluée (adresse IP source, présence MFA, tag de ressource…).
  3. Valeur — la valeur attendue pour que la condition soit satisfaite.
  4. Si plusieurs clés sont présentes dans un même opérateur, toutes doivent être satisfaites (AND logique).
  5. Si plusieurs opérateurs sont présents dans Condition, tous doivent être satisfaits (AND logique).

Erreur de diagnostic classique : le Deny implicite confondu avec un Deny explicite

Symptôme observé : un développeur reçoit une erreur AccessDenied sur s3:GetObject. Il vérifie sa politique d'identité — le Allow est bien là. Il ajoute une deuxième politique avec un Allow plus large. L'erreur persiste.

Mauvais diagnostic : la politique n'est pas attachée correctement, ou il y a un problème de propagation.

Cause réelle : la politique de bucket S3 contient un Deny explicite sur s3:GetObject pour toutes les requêtes qui ne passent pas par un VPC Endpoint spécifique. Ce Deny explicite écrase tous les Allow, peu importe leur nombre ou leur source.

Correction : utiliser le simulateur de politique IAM ou aws iam simulate-principal-policy pour identifier la source du refus, puis examiner la politique de ressource du bucket.

aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:user/mon-utilisateur \
  --action-names s3:GetObject \
  --resource-arns arn:aws:s3:::mon-bucket/mon-objet.txt

La réponse inclut un champ EvalDecision et un champ MatchedStatements qui identifie précisément quelle instruction a causé le refus — y compris les politiques de ressource.

Politique IAM complète : exemple annoté

🔽 Cliquer pour afficher — Exemple de politique IAM avec les quatre éléments
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LectureS3AvecCondition",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::mon-bucket",
        "arn:aws:s3:::mon-bucket/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "eu-west-1"
        },
        "Bool": {
          "aws:SecureTransport": "true"
        }
      }
    },
    {
      "Sid": "RefusDeSuppression",
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "arn:aws:s3:::mon-bucket/*"
    }
  ]
}

Cette politique autorise la lecture des objets et la liste du bucket uniquement depuis la région eu-west-1 et uniquement via HTTPS (aws:SecureTransport). Elle refuse explicitement toute suppression d'objet, quelle que soit la source de la requête.

Vérifier et valider une politique IAM avec la CLI

Avant de déployer une politique, deux commandes sont particulièrement utiles pour éviter les erreurs silencieuses.

Valider la syntaxe JSON d'une politique :

aws iam validate-policy \
  --policy-document file://ma-politique.json \
  --policy-type IDENTITY

Simuler l'évaluation d'une politique pour un principal donné :

aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:role/MonRole \
  --action-names ec2:DescribeInstances \
  --resource-arns "*"

La commande validate-policy fait partie d'IAM Access Analyzer et peut détecter des problèmes comme des actions inexistantes, des ARN malformés, ou des combinaisons action/ressource incompatibles.

Conclusion et prochaines étapes sur la structure des politiques IAM

Les quatre éléments Effect, Action, Resource et Condition forment le vocabulaire de base de toute politique IAM. Maîtriser leur interaction — en particulier la priorité du Deny explicite et les contraintes de restriction par ressource selon le type d'action — est ce qui sépare une politique fonctionnelle d'une politique sécurisée.

Pour aller plus loin :

Glossaire

Terme Définition
ARN Amazon Resource Name — identifiant unique et global d'une ressource AWS, au format arn:aws:service:region:compte:ressource.
Deny implicite Comportement par défaut d'IAM : toute action sans Allow explicite est refusée, même en l'absence de Deny.
Deny explicite Instruction "Effect": "Deny" dans une politique. Écrase tout Allow, quelle que soit sa source.
SCP Service Control Policy — politique appliquée au niveau d'une unité organisationnelle AWS Organizations. Définit les permissions maximales autorisées dans un compte.
Clé de condition Variable contextuelle utilisée dans l'élément Condition, comme aws:SourceIp ou aws:MultiFactorAuthPresent, évaluée au moment de la requête.

Related Posts

Commentaires

Posts les plus consultés de ce blog

Groupes IAM AWS : Pourquoi Attacher les Politiques aux Groupes Plutôt qu'aux Utilisateurs

LSI vs GSI dans DynamoDB : choisir le bon index secondaire

NAT Gateway vs NAT Instance : Quelle solution choisir pour vos instances privées ?