Terraform et comptes multiples dans AWS
Disclaimer : Cet article est assez technique et peut nécessiter des connaissances sur le fonctionnement de la gestion des accès et des droits dans AWS. Pour plus d’informations sur le sujet, la documentation AWS est très complète et permet d’avoir une connaissance minimale pour aborder cet article.
Que ce soit pour des raisons de sécurité ou pour de la gestion administrative, il est possible dans AWS de créer plusieurs comptes AWS (visible dans AWS organization) reliés à un même compte maître.
Un exemple simple, vous possédez 2 comptes :
- Un compte de production qui va faire tourner votre site web de vente en ligne par exemple. Seule l’équipe d'exploitation aura le droit de créer de l’infrastructure dessus.
- Un compte de R&D où les droits seront ouverts à l’ensemble des équipes pour tester les nouveaux services AWS, des technologies, des frameworks ...
Chaque compte AWS existant va alors pouvoir créer sa propre base d’utilisateurs avec des droits différents. Par exemple, Bob, faisant partie de l’équipe d’exploitation est Administrateur sur les 2 comptes et possède donc un utilisateur IAM sur chacun d’eux.
Afin de sécuriser ces accès, chaque utilisateur va donc s’authentifier avec des identifiants (Login / Mot de passe, Access / Secret Key) différents par compte. Chaque compte est alors autonome dans sa gestion des utilisateurs et dans les autorisations qui leurs sont données . Rien n’empêche Bob d’ajouter Alice en tant qu’Auditrice du compte de production.
Plus le nombre d’utilisateurs augmente, plus la gestion des droits devient complexe :
D’un point de vue utilisateur, avoir un IAM User sur chaque compte oblige à avoir un mot de passe / Access Key / Secret Key par compte.
Dans cet article, nous allons voir comment centraliser notre base d’utilisateurs au sein d’un compte, permettant une authentification unique sur l’ensemble des comptes. Cela nécessitera d’utiliser les rôles AWS pour gérer les droits de chacun des utilisateurs sur chacun des comptes.
Piqûre de rappel
Dans un compte AWS, nous pouvons déployer des ressources et avoir une gestion des utilisateurs. Ces utilisateurs, IAM Users pour AWS, peuvent être organisés par groupe.
Un service AWS (telle qu’une instance) peut avoir des droits sur le APIs AWS via des Roles. Un rôle donne donc le droit à un service AWS d’exécuter des appels aux APIs AWS. Chaque groupe, IAM User ou Role possède une ou plusieurs IAM policy. Elles permettent de donner ou de restreindre des droits sur les appels aux APIs AWS permettant ainsi de gérer les accès aux différents services d’AWS (par exemple : le droit de créer des Instances).
Un Role qui a des Policies peut aussi être utilisé par un IAM User pour avoir des droits dans un autre compte, ce qui s’appelle assumer un rôle dans le langage AWS. Dans cet article, nous allons décrire la procédure pour qu’un utilisateur d’un compte AWS assume un rôle dans un autre compte. Ce qui est décrit par AWS comme AWS Assume Role Cross Account.
Un compte pour les gouverner tous
“Trois comptes pour les rois Clients sous le ciel,
Sept pour les Seigneurs Ops dans leurs demeures de pierre,
Neuf pour les Dev Mortels destinés au trépas,
Un pour le Seigneur Administrateur sur son sombre trône”
J.R.R. Tolkien (version Ops)
Pour notre exemple, nous allons avoir seulement 2 comptes. Un compte R&D qui contiendra l’ensemble des utilisateurs ainsi que la gestion de leurs droits et un compte production qui est un second compte de l’organisation.
Nous allons créer un rôle administrateur ayant tous les droits sur le compte de production. Nous allons ensuite donner les droits aux utilisateurs du compte de R&D d’utiliser le rôle Administrateur du compte de production.
Nous aurons donc à terme, le schéma de gestion d’authentifications et d’autorisations suivant :
Terraform pour automatiser
Afin d’automatiser les deux côtés (production et R&D) de la création du rôle, nous utilisons Terraform, qui avec son approche infrastructure as code, nous permet d’avoir un code maintenable et compréhensible.
Dans les exemples de code suivants, nous allons utiliser les conventions suivantes :
- Aws Account Id du compte R&D :”${var.retd_account_id}”
- Aws Account Id du compte Production : ”${var.production_account_id}
- Rôle que les utilisateurs utiliseront dans le compte cible : Administrator
Compte Production
Nous devons créer sur ce compte un rôle Administrateur possédant tous les droits sur le compte. Puis nous donnerons l'autorisation au compte maître d’assumer le rôle du compte production.
Dans un premier temps, il nous définir le provider AWS avec les crédentials AWS (Access Key et Secret Key) du compte de production. Si vous ne souhaitez pas les faire apparaître dans votre code, vous pouvez aussi les mettre en variables d’environnement.
provider "aws" { access_key = "XXXXXXXXXX" secret_key = "XXXXXXXXXX" }
Il faut créer 2 ressources dans terraform et une datasource pour répondre à notre besoin :
resource "aws_iam_role" "role" { name = "Administrator" assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}" }
data "aws_iam_policy_document" "assume_role" { statement { actions = [****"sts:AssumeRole"] principals { type = "AWS" identifiers = [****"arn:aws:iam::${var.retd_account_id}:root"] } } }
resource "aws_iam_role_policy_attachment" "attach-role" { role = "${aws_iam_role.role.name}" policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" }
Dans le code ci-dessus, la ressource “role” définit le rôle que nous allons créer sur le compte production. Dans la définition du role, nous lui donnons le nom "Administrator" et lui attachons la policy qui va permettre d’utiliser ce rôle, décrite ci-dessous.
La datasource “assume_role” décrit quels sont les utilisateurs qui ont le droit d’assumer le rôle auquel ils sont associés. Il faut décrire les permissions (statement) qui vont constituer notre policy et qui correspondent aux différents droits de celle ci. Dans notre statement, nous déclarons que la liste de compte ["arn:aws:iam::${var.retd_account_id:root"] (compte de R&D) possède les droits ["sts:AssumeRole"].
Les deux premières ressources ont défini le rôle ainsi que sa politique d’assumation.
La troisième ressource va associer les droits d’administrateur au rôle que l’on vient de créer.
Compte R&D
Nous venons de créer le rôle sur le compte production et tous les utilisateurs du compte maître sont maintenant éligibles à l’assumation du rôle. Nous allons maintenant gérer les utilisateurs pouvant utiliser le rôle au moyen de Terraform.
Il faut noter que si les utilisateurs du compte maître ont la policy AdministratorAccess, ils possèdent le droit d’assumer le rôle du compte production.
Nous allons maintenant exécuter des actions sur le compte de R&D. Il faut donc mettre un autre provider avec d’autres crédentials (nous verrons plus tard qu’avec les assumes roles, cela ne sera plus nécessaire).
provider "aws" { access_key = "YYYYYYYYY" secret_key = "YYYYYYYYY" }
data "aws_iam_policy_document" "policy_document" { statement { effect = "Allow" actions = [****"sts:AssumeRole"] resources = ["arn:aws:iam::${var.production_account_id}****:role/Administrator"] } }
resource "aws_iam_group_policy" "my_policy" { name = "assume-to-production-account" group = "mygroup" policy = "${data.aws_iam_policy_document.policy_document.json}"
}
Dans la première ressource Terraform nous déclarons une policy qui autorise d’assumer la liste de rôles ["arn:aws:iam::${var.production_account_id}:role/Administrator"] (compte production), puis nous attachons, dans la deuxième ressource, cette policy au groupe d’utilisateurs "mygroup". Il est aussi possible d’attacher la policy à un seul utilisateur en utilisant la ressource ”aws_iam_user_policy” de Terraform.
Vous avez maintenant un rôle administrateur assumable par un groupe d’utilisateurs présents sur un seul et unique compte, vous permettant de gouverner vos utilisateurs et leurs droits plus facilement.
_“_Un anneau pour les gouverner tous. Un anneau pour les trouver,
Un anneau pour les amener tous et dans les ténèbres les lier_”_
J.R.R. Tolkien
Utilisation de notre Assume Rôle
Maintenant que tout est configuré, comment peut-on utiliser le rôle créé pour se connecter à notre compte production?
La console AWS
Dans la console web, nous pouvons voir sous le nom de l’utilisateur, le champ changer de rôle, ce lien va nous permettre d’assumer le rôle.
Deux informations sont nécessaires :
- Compte : soit l’Id du compte, soit l’alias du compte AWS cible
- Rôle : le rôle à assumer sur le compte cible
Une fois l’action faite, nous somme maintenant sur le compte production.
Le CLI
Avec la Command Line Interface, on peut faire un assume role via la ligne de commande :
$ aws sts assume-role --role-arn arn:aws:iam::<Production-Account-ID>:role/Administrator --role-session-name my-username
Cette commande renvoie les AccessKeyId, SecretAccessKey et SessionToken qu’on pourra exporter en variables d’environnement pour effectuer les actions sur le compte production.
Terraform
Avec Terraform, lors de la définition du provider AWS, il est possible de lui faire assumer un rôle :
# Provider Compte de Production
provider "aws" { access_key = "YYYYYYYYY" secret_key = "YYYYYYYYY" assume_role { role_arn = "arn:aws:iam::${var.production_account_id}:role/Administrator" } region = "eu-west-1" }
Toutes les ressources créées ensuite seront exécutées avec le rôle que nous avons créé sur le compte production, ici, administrateur.
Conclusion
Nous avons vu comment mettre en place des Assume Role Cross-Account à travers Terraform et comment les utiliser via la console Web, le CLI et Terraform.
L’utilisateur n’a besoin que d’un accès au compte de R&D et passe par des Assume Role pour faire des actions sur les autres comptes.
AWS Organization vient par ailleurs de sortir avec la promesse de pouvoir créer des comptes via des APIs. Quand on vient créer un compte via Organization, on donne le nom d’un rôle à la création et AWS se charge de faire la création de la Policy, du Role … Ce rôle permet depuis le compte de R&D de faire un Assume Rôle sur ce nouveau compte. Seul la configuration du compte R&D est alors nécessaire.