Qui décide quelle porte s’ouvre ?
Une carte d’élève ouvre la porte du CDI mais pas celle de la salle des professeurs. Quelqu’un a écrit quelles portes chaque carte peut ouvrir.
Le cloud fonctionne pareil. Une politique IAM est la liste écrite de ce qu’une personne ou un programme peut faire. Cette leçon montre comment lire une politique et dire si un appel est permis.
À la fin de cette leçon
Remarque
Je peux lire une politique et dire si un appel est permis.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Politique | un document qui liste ce qui est permis et ce qui ne l’est pas | policy |
| Déclaration | une règle à l’intérieur d’une politique | Statement |
| Effet | ce qui dit si une déclaration permet ou refuse | Effect |
| Action | l’appel qui est fait | s3:GetObject |
| Ressource | la chose sur laquelle l’appel est fait | Resource |
| Moindre privilège | donner seulement l’accès dont un travail a besoin |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une politique est une liste de déclarations
Une politique est un document JSON. Elle a une Version et une liste nommée Statement. Chaque déclaration dit trois choses : l’effet, l’action et la ressource.
L’effet est Allow (permettre) ou Deny (refuser). L’action est l’appel, comme s3:GetObject, qui lit un fichier. La ressource est ce sur quoi l’appel est fait, nommée par un long texte appelé ARN. Ces politiques sont inventées. Rien ici ne demande de compte.
Essayez : lire une politique
politique = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::photos-boutique/*",
},
{
"Effect": "Deny",
"Action": "s3:*",
"Resource": "arn:aws:s3:::photos-boutique/prive/*",
},
],
}
for declaration in politique["Statement"]:
print(declaration["Effect"], declaration["Action"], declaration["Resource"])
# Remplacez "Deny" par "Allow". Le programme la lit toujours. Le sens change-t-il ?
Une étoile remplace n’importe quelle suite
Écrire chaque nom de fichier prendrait un temps infini. Un modèle peut donc contenir une étoile. Une étoile remplace n’importe quelle suite de caractères, même aucun.
La ressource "arn:aws:s3:::photos-boutique/" correspond à chaque objet de ce bucket. L’action "s3:" correspond à chaque appel S3. Un modèle sans étoile doit être identique au texte.
Exemple travaillé : les textes qu’un modèle accepte
| Modèle | Texte | Correspond ? |
|---|---|---|
| s3:* | s3:GetObject | Oui |
| s3:* | sqs:SendMessage | Non, il ne commence pas par s3: |
| s3:Get* | s3:GetObject | Oui |
| s3:Get* | s3:PutObject | Non |
| photos/* | photos/ | Oui, l’étoile remplace rien |
| *.jpg | chat.jpg | Oui |
| s3:GetObject | s3:GetObjectAcl | Non, pas d’étoile, donc identique |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un refus l’emporte toujours
Pour décider d’un appel, cherchez chaque déclaration dont l’action et la ressource correspondent toutes deux. Appliquez ensuite trois règles.
Si une déclaration qui correspond dit Deny, l’appel est refusé. C’est un refus explicite, et il l’emporte sur tout Allow. Si aucune ne refuse mais qu’une permet, l’appel est permis. Si rien ne correspond, l’appel est refusé quand même. C’est un refus implicite.
Exemple : trois appels sur la politique des photos
| Appel | Déclarations qui correspondent | Résultat |
|---|---|---|
| s3:GetObject sur photos-boutique/chat.jpg | Allow seulement | Permis |
| s3:GetObject sur photos-boutique/prive/identite.jpg | Allow et Deny | Refusé : le refus explicite l’emporte |
| sqs:SendMessage sur une file | Aucune | Refusé : refus implicite |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Erreur fréquente
Attention
Beaucoup croient qu’un appel est permis tant qu’une politique ne l’interdit pas. C’est l’inverse. Un appel est refusé tant qu’une déclaration ne le permet pas, et un Deny l’emporte sur tout Allow.
Essayez : les trois règles en code
trouvees = ["Allow", "Deny"]
if "Deny" in trouvees:
resultat = "refusé : refus explicite"
elif "Allow" in trouvees:
resultat = "permis"
else:
resultat = "refusé : refus implicite"
print(resultat)
# Remplacez trouvees par ["Allow"], puis par []. Que donne chaque essai ?
Donner le moins qui suffit
Un site de photos doit lire et ajouter des photos. Il n’a pas besoin de les supprimer ni de toucher aux files. Sa politique nomme donc seulement ces deux actions, sur ce seul bucket.
C’est le moindre privilège. Si le site est un jour détourné, les dégâts s’arrêtent à ce que la politique permettait.