Skip to main content

Améliorer la couverture des ressources cloud pour réduire les dérives de l’infrastructure

Écrit par:
Stephane Jourdan

Stephane Jourdan

wordpress-sync/feature-iac-drift-purple

23 mars 2022

0 minutes de lecture

Avis d’obsolescence : détection des dérives dans les ressources gérées

La détection des dérives dans les ressources gérées, y compris les commandes snyk iac describe --only-managed et snyk iac describe --drift, n’est plus active. La détection des dérives dans les ressources gérées est devenue obsolète le 30 septembre 2023.

Les développeurs ont besoin de la meilleure visibilité possible sur les ressources qui s’exécutent dans les environnements cloud pour les protéger. L’infrastructure en tant que code (IaC) les aide à automatiser les infrastructures cloud pour que toutes les ressources déployées dans le cloud soient contrôles et puissent être auditées facilement. Pour autant, il n’est pas facile d’atteindre et de maintenir une couverture à 100 % de votre infrastructure par l’IaC.

La sécurité dépend des ressources déployées et exécutées dans les environnements cloud. Or, bien souvent, de nombreuses actions manuelles interviennent régulièrement, que ce soit par nous-mêmes, par d’autres équipes ou par des services authentifiés. Ces modifications ne sont pas visibles dans l’IaC et les audits, et sont ainsi source de nombreux problèmes, notamment des erreurs de configuration et des failles de sécurité. C’est pour cette raison que la gestion des dérives est importante : il faut absolument avoir connaissance des ressources qui ne sont pas encore contrôlées par l’IaC ou qui ont changé pour une raison ou pour une autre.

Dans cet article, nous allons voir comment Snyk IaC aide les développeurs à détecter les ressources qui ne sont pas contrôlées par l’IaC (ressources non gérées) ou qui se sont écartées de leur état attendu (ressources gérées)

Configurer l’environnement

Snyk IaC vous aide à répertorier les ressources localisées en tant que ressources Terraform pour vous aider à déterminer quelle partie du service cloud fait l’objet de la détection. Par exemple, un service Amazon API Gateway v2 se compose d’au moins 12 ressources Terraform. Avec les informations de détection fournies par Snyk, vous pourrez décider rapidement si vous devez inverser la modification, importer une nouvelle ressource ou simplement supprimer cette nouvelle modification.

Pour suivre notre démonstration, vous pouvez utiliser le fichier Terraform ci-dessous afin de créer les deux ressources AWS que nous allons utiliser. Il crée un utilisateur IAM nommé « user1 » avec un suffixe aléatoire, une clé d’accès et une politique attachée d’accès en lecture seule.

Au moment de l’écriture de cet article, la version de Terraform utilisée était la 1.1.7 et celle du fournisseur AWS 3.74.2.

Réutilisez la configuration HCL suivante :

main.tf

1resource "random_string" "prefix" {
2  length  = 6
3  upper   = false
4  special = false
5}
6
7resource "aws_iam_user" "user1" {
8  name = "user1-${random_string.prefix.result}"
9
10  tags = {
11    Name = "user1-${random_string.prefix.result}"
12    manual = "true"
13  }
14}
15
16resource "aws_iam_access_key" "user1" {
17  user = aws_iam_user.user1.name
18}
19
20resource "aws_iam_user_policy_attachment" "user1" {
21  user       = aws_iam_user.user1.name
22  policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
23}

Appliquez la configuration Terraform :

1$ terraform init
2[...]
3$ terraform apply
4[...]

Vérifiez que vous disposez d’un fichier terraform.tfstate à la racine du répertoire :

1$ ls -al terraform.tfstate
2-rw-r--r--  1 sjourdan  staff  5049 Mar 16 18:31 terraform.tfstate

Vérifiez également que l’utilisateur IAM a bien été créé sur AWS.

Créer un environnement propre

Commençons par répertorier toutes les ressources cloud non contrôlées par Terraform :

1$ snyk iac describe --only-unmanaged

Vous allez probablement obtenir une liste très longue. Ces informations sont utiles, mais peu exploitables dans notre situation. Snyk IaC permet d’ignorer des ressources par lot : il suffit d’ajouter toutes les ressources détectées dans le fichier de politique .snyk.

Ignorons donc toutes ces ressources non gérées pour profiter d’un environnement contrôlé comportant uniquement les deux ressources que nous avons créées ci-dessus :

1$ snyk iac describe --only-unmanaged --json  | snyk iac update-exclude-policy

Renouvelez l’analyse pour confirmer que votre environnement ignore bien les dérives découvertes (vous pourrez programmer leur importation plus tard). 

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found 3 resource(s)
5 - 100% coverage
6Congrats! Your infrastructure is fully in sync.

Nous sommes maintenant prêts à partir d’un environnement propre.

Partons à la dérive avec l’IAM !

Nous allons maintenant créer trois types de dérives afin de simuler des scénarios susceptibles de survenir dans le monde réel :

  1. Une modification de l’utilisateur IAM actuel (que nous devrons annuler)

  2. L’attachement manuel d’une nouvelle politique IAM (que nous devrons supprimer)

  3. La création d’un nouvel utilisateur IAM (que nous devrons améliorer)

Pour ce faire, rendez-vous dans la console AWS pour IAM.

Modifier l’utilisateur IAM existant en ajoutant une balise

  1. Sur la page des utilisateurs IAM, cliquez sur « user1 ».

  2. Cliquez sur l’onglet Tags (Balises).

  3. Cliquez sur le bouton Edit Tags (Modifier les balises).

  4. Ajoutez une nouvelle clé (« environment ») et une nouvelle valeur (« production »).

  5. Cliquez sur Save (Enregistrer).

Attacher une politique importante à l’utilisateur IAM existant

  1. Sur la page des utilisateurs IAM, cliquez sur « user1 ».

  2. Cliquez sur l’onglet Permissions (Autorisations).

  3. Cliquez sur le bouton Add permissions (Ajouter des autorisations).

  4. Cliquez sur Attach existing policies directly (Attacher directement des politiques existantes).

  5. Sélectionnez Administrator Access (Accès administrateur).

  6. Cliquez sur Next: Review (Suivant : revue).

  7. Validez en cliquant sur Add permissions (Ajouter autorisations).

Créer un autre utilisateur IAM manuellement

  1. Sur la page des utilisateurs IAM, cliquez sur le bouton Add Users (Ajouter des utilisateurs).

  2. Saisissez « user2 » dans le champ User name: (Nom d’utilisateur :).

  3. Sélectionnez Access key (Clé d’accès).

  4. Cliquez sur le bouton Next: Permissions (Suivant : autorisations).

  5. Ne définissez aucune autorisation ni aucune balise.

  6. Cliquez sur Create user (Créer l’utilisateur). Les informations d’identification qui s’affichent ne nous intéressent pas, n’en tenez pas compte.

Nous sommes maintenant prêts à gérer les modifications manuelles à l’aide de la fonction de détection des dérives de Snyk IaC.

Dérives des ressources gérées et non gérées

Voyons comment ces modifications sont détectées par Snyk IaC, en commençant par les ressources qui ne sont pas gérées du tout par Terraform.

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found resources not covered by IaC:
5  aws_iam_access_key:
6    - AKIASBXWQ3AYQETE6OFR
7        User: user2
8  aws_iam_policy_attachment:
9    - user1-84i30k-arn:aws:iam::aws:policy/AdministratorAccess
10  aws_iam_user:
11    - user2
12Found 6 resource(s)
13 - 50% coverage
14 - 3 resource(s) managed by Terraform
15 - 3 resource(s) not managed by Terraform
16 - 0 resource(s) found in a Terraform state but missing on the cloud provider

L’analyse donne les résultats suivants, en utilisant les dénominations de ressources Terraform :

  • Utilisateur IAM « user2 » créé manuellement, avec sa clé d’accès IAM

  • Politique IAM attachée manuellement à l’utilisateur IAM « user1 » géré par Terraform

Regardons maintenant les modifications concernant uniquement les ressources gérées par Terraform et présentées dans les différents états Terraform :

1$ snyk iac describe –only-managed
2Scanned states (1)
3Found changed resources:
4  From tfstate://terraform.tfstate
5    - user1-84i30k (aws_iam_user.user1):
6        + tags.environment: <nil> => "production"
7Found 5 resource(s)
8 - 100% coverage
9 - 5 resource(s) managed by Terraform
10     - 1/5 resource(s) out of sync with Terraform state
11 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Cette analyse génère des résultats très différents et a pris nettement plus longtemps (36 s contre 9 s en mode d’analyse « non géré »).

Ces résultats nous apprennent que l’utilisateur IAM nommé « user1-84i30k », que nous trouvons dans le fichier HCL (sous forme de ressource) sous le nom « user1 », dispose d’une balise « environment » définie sur « production ».

Plan d’action

L’outil de détection des dérives de Snyk nous a aidés à détecter quatre différences inattendues par rapport à ce que nous anticipions. Dans le cadre de cet article, disons que l’équipe a pris les décisions suivantes :

  • L’utilisateur IAM « user2 » est utilisé en production et doit être importé dans Terraform.

  • La clé d’accès IAM de « user2 » doit être modifiée pour des questions de sécurité.

  • L’utilisateur « user1 » ne doit en aucun cas être administrateur.

  • La nouvelle balise de « user1 » est nécessaire en raison d’une obligation quelconque et doit être importée dans Terraform.

Objet

Type de ressource

Nom

Type de dérive

Action

Utilisateur IAM

aws_iam_user

user2

Non gérée

IMPORTER

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

MODIFIER

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

SUPPRIMER

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

IMPORTER

Les pipelines de déploiement ne sont pas synonymes de correction

Nous disposons d’un pipeline de déploiement Terraform très efficace. La prochaine fois que la commande terraform apply sera exécutée, il est donc probable que la situation revienne à la normale.

Dans notre cas, que fera Terraform ? Voici une tâche de déploiement :

1$ terraform apply
2Terraform will perform the following actions:
3
4  # aws_iam_user.user1 will be updated in-place
5  ~ resource "aws_iam_user" "user1" {
6        id            = "user1-84i30k"
7        name          = "user1-84i30k"
8      ~ tags          = {
9          - "environment" = "production" -> null
10            # (1 unchanged element hidden)
11        }
12[...]
13
14Plan: 0 to add, 1 to change, 0 to destroy.

Terraform n’est pas conçue pour détecter les ressources créées ou attachées manuellement. La plateforme se contentera de rétablir les ressources modifiées dans leur état d’origine (ce qui n’est pas ce que nous souhaitons ici).

Objet

Type de ressource

Nom

Type de dérive

Action

Utilisateur IAM

aws_iam_user

user2

Non gérée

AUCUNE

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

AUCUNE

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

AUCUNE

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

RÉTABLIR

Nous n’obtenons le résultat attendu dans aucun des cas :

  • L’utilisateur IAM créé manuellement et sa clé d’accès ne sont pas signalés (inutile).

  • La politique d’administrateur attachée manuellement à un utilisateur géré n’est pas signalée (inutile).

  • La balise importante ajoutée manuellement à un utilisateur géré sera supprimée (dommageable).

Nous avons donc besoin d’un autre outil pour ce type de détection et d’action.

Amélioration de la couverture

Au départ, notre couverture des ressources non gérées atteint 50 %.

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found resources not covered by IaC:
5  aws_iam_access_key:
6    - AKIASBXWQ3AYQETE6OFR
7        User: user2
8  aws_iam_policy_attachment:
9    - user1-84i30k-arn:aws:iam::aws:policy/AdministratorAccess
10  aws_iam_user:
11    - user2
12Found 6 resource(s)
13 - 50% coverage
14 - 3 resource(s) managed by Terraform
15 - 3 resource(s) not managed by Terraform
16 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Améliorons ce chiffre avec notre plan d’action.

Supprimez la politique IAM pour « user1 »

Commençons par le plus urgent et le plus simple : supprimer la politique « administrateur » associée à l’utilisateur IAM géré « user1 ».

  • Accédez à IAM > Users > user1 (IAM > Utilisateurs > User1).

  • Cliquez sur Permissions (Autorisations) et supprimez « AdministratorAccess ».

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found resources not covered by IaC:
4  aws_iam_access_key:
5    - AKIASBXWQ3AYQETE6OFR
6        User: user2
7  aws_iam_user:
8    - user2
9Found 5 resource(s)
10 - 60% coverage
11 - 3 resource(s) managed by Terraform
12 - 2 resource(s) not managed by Terraform

Nous couvrons désormais 60 % des ressources AWS, contre 50 % précédemment.

Objet

Type de ressource

Nom

Type de dérive

Action

Statut

Utilisateur IAM

aws_iam_user

user2

Non gérée

IMPORTER

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

MODIFIER

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

SUPPRIMER

*

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

AJOUTER

Continuons.

Débloquer le pipeline de déploiement Terraform

Le pipeline est actuellement bloqué par la modification manuelle apportée aux balises de aws_iam_user.user1. Si un déploiement survient, les balises seront rétablies conformément aux valeurs du fichier HCL. La solution ? Utiliser le résultat de l’analyse des dérives de Snyk IaC pour adapter notre configuration Terraform.

Nous disposons des informations suivantes :

1Found changed resources:
2  From tfstate://terraform.tfstate
3    - user1-84i30k (aws_iam_user.user1):
4        + tags.environment: <nil> => "production"

Ces résultats nous donnent les indications suivantes :

  • Nous cherchons une ressource aws_iam_user nommée « user1 ».

  • Cette ressource se trouve dans le fichier terraform.tfstate (très utile lorsque vous disposez de dizaines ou de centaines d’états).

  • Nous avons une nouvelle clé de balise nommée environment dont la valeur est « production ».

Actualisons notre ressource d’utilisateur IAM en ajoutant environment = "production" pour que notre ressource se présente comme suit :

1resource "aws_iam_user" "user1" {
2 name = "user1-${random_string.prefix.result}"
3
4 tags = {
5   Name = "user1-${random_string.prefix.result}"
6   environment = "production"
7 }
8}

Nous pouvons maintenant débloquer notre pipeline de déploiement Terraform en toute sécurité :

1$ terraform apply
2No changes. Your infrastructure matches the configuration.
3Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Nous avons temporairement corrigé nos dérives « gérées » :

1$ snyk iac describe --only-managed
2Scanned states (1)
3Found 3 resource(s)
4 - 100% coverage
5Congrats! Your infrastructure is fully in sync.

Objet

Type de ressource

Nom

Type de dérive

Action

Statut

Utilisateur IAM

aws_iam_user

user2

Non gérée

IMPORTER

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

MODIFIER

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

SUPPRIMER

*

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

AJOUTER

*

Importer l’utilisateur IAM user2 et modifier sa clé

Intéressons-nous maintenant à l’utilisateur « user2 ». Nous voulons :

  • l’importer dans Terraform ;

  • modifier sa clé.

Commençons par importer l’utilisateur IAM dans Terraform. Nous avons à notre disposition une méthode très simple pour le faire :

Commençons par récupérer des informations depuis Snyk IaC :

Type de ressource

Nom

aws_iam_user

user2

Comment importer une ressource aws_iam_user ? D’après la documentation officielle de Terraform : il est possible d’importer des utilisateurs IAM avec leur nom, par exemple,$ terraform import aws_iam_user.lb loadbalancer.

La documentation indique également que le seul argument requis est le nom. Ajoutons cette structure de base à notre fichier HCL :

1resource "aws_iam_user" "user2" {
2 name = "user2" # required
3}

Importons maintenant cet utilisateur dans Terraform :

1$ terraform import aws_iam_user.user2 user2
2aws_iam_user.user2: Importing from ID "user2"...
3aws_iam_user.user2: Import prepared!
4  Prepared aws_iam_user for import
5aws_iam_user.user2: Refreshing state... [id=user2]
6
7Import successful!

Notre couverture a-t-elle changé ? Nous allons vite le savoir :

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found resources not covered by IaC:
4  aws_iam_access_key:
5    - AKIASBXWQ3AYQETE6OFR
6        User: user2
7Found 5 resource(s)
8 - 80% coverage
9 - 4 resource(s) managed by Terraform
10 - 1 resource(s) not managed by Terraform

Notre couverture atteint désormais 80 % (contre 60 % précédemment) et il ne reste qu’une seule ressource à traiter.

Objet

Type de ressource

Nom

Type de dérive

Action

Statut

Utilisateur IAM

aws_iam_user

user2

Non gérée

IMPORTER

*

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

MODIFIER

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

SUPPRIMER

*

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

AJOUTER

*

modifier sa clé.

Passons maintenant à cette opération. Nous savons que nous voulons modifier la clé lors de son ajout à Terraform. Commençons par ajouter la nouvelle clé au fichier HCL afin de la créer (nous pourrons par exemple la communiquer à l’équipe concernée). Nous supprimerons ensuite l’ancienne clé d’AWS.

Terraform documentation for aws_iam_access_key est une commande très simple. Nous pouvons simplement créer une ressource acceptant le nom user2 en tant qu’argument :

1resource "aws_iam_access_key" "user2" {
2 user = aws_iam_user.user2.name
3}

Le pipeline de déploiement ayant été débloqué, nous pouvons l’appliquer en toute sécurité en utilisant Terraform pour créer la nouvelle clé :

1$ terraform apply 
2[...]
3Terraform will perform the following actions:
4
5  # aws_iam_access_key.user2 will be created
6  + resource "aws_iam_access_key" "user2" {
7      + create_date          = (known after apply)
8      + encrypted_secret     = (known after apply)
9      + id                   = (known after apply)
10      + key_fingerprint      = (known after apply)
11      + secret               = (sensitive value)
12      + ses_smtp_password_v4 = (sensitive value)
13      + status               = "Active"
14      + user                 = "user2"
15    }
16
17Plan: 1 to add, 0 to change, 0 to destroy.
18
19aws_iam_access_key.user2: Creating...
20aws_iam_access_key.user2: Creation complete after 1s [id=AKIASBXWQ3AY4KPUNIHZ]
21
22Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Il nous reste à supprimer l’ancienne clé. Les résultats de Snyk IaC nous ont permis de déterminer que le nom de la clé est AKIASBXWQ3AYQETE6OFR.

Voici le moyen le plus simple de la supprimer :

  • Rendez-vous dans IAM > Users > user2 > Security Credentials (IAM > Utilisateurs >user2 > Informations de sécurité).

  • Supprimez la clé AKIASBXWQ3AYQETE6OFR signalée par Snyk IaC en commençant par la désactiver, puis en la supprimant.

À combien se monte désormais notre couverture ?

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found 5 resource(s)
4 - 100% coverage
5Congrats! Your infrastructure is fully in sync.

Félicitations ! Tout est sous contrôle grâce à l’outil de détection des dérives de Snyk IaC !

Objet

Type de ressource

Nom

Type de dérive

Action

Statut

Utilisateur IAM

aws_iam_user

user2

Non gérée

IMPORTER

*

Clé d’accès IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Non gérée

MODIFIER

*

Politique IAM attachée

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Non gérée

SUPPRIMER

*

Balise d’un utilisateur IAM

aws_iam_user

tags.environment

Gérée

AJOUTER

*

Conclusion

Dans cet article, nous avons vu que l’outil de détection des dérives de Snyk IaC permet de détecter des ressources AWS créées manuellement, et qu’il formule ses résultats en utilisant les dénominations Terraform et en fournissant les informations dont les développeurs ont besoin pour importer ces ressources dans leur code Terraform HCL. Nous avons aussi vu brièvement que l’annulation automatique des modifications n’est pas toujours la bonne solution et qu’il est nécessaire d’utiliser un système d’alerte de dérive léger en conjonction avec le pipeline de déploiement.

Nous sommes persuadés que toute l’infrastructure doit être intégrée au code pour que les ingénieurs disposent d’informations sur sa sécurité et d’une visibilité sur les problèmes dès que possible.

C’est pour cette raison que Snyk IaC peut aider les équipes à réintégrer rapidement l’ensemble de leurs ressources s’exécutant dans leur compte AWS dans le code Terraform afin d’étendre la couverture globale par l’IaC et réduire les problèmes de sécurité. Snyk IaC permet d’apporter des corrections plus rapides en bouclant la boucle de rétroaction entre les équipes de sécurité du cloud et les équipes techniques, et en fournissant des corrections exploitables directement aux ingénieurs, dans un format qu’ils comprennent.

wordpress-sync/feature-iac-drift-purple

Vous voulez l’essayer par vous-même ?

Find out which types of vulnerabilities are most likely to appear in your projects based on Snyk scan results and security research.