Comment utiliser AWS CloudTrail pour restaurer du paramétrage, avec AWS Boto3 ?
15 janvier 2021

Comment utiliser AWS CloudTrail pour restaurer du paramétrage, avec AWS Boto3 ?

Dans cet article, je vais vous parler de 2 outils très intéressants et complémentaires de l’environnement AWS :

  • Cloudtrail
  • API Boto3

AWS Cloudtrail tout d’abord, suit le qui, quoi, où et quand de l’activité qui se produit dans votre environnement AWS et enregistre cette activité sous la forme de journaux d’audit. Les journaux contiennent donc les informations sur tout ce qui se passe. Ils permettent naturellement de surveiller les actions effectuées sur vos comptes AWS, remonter à la cause des problèmes rencontrés (et qui en est à l’origine !) et faire apparaître des parties de votre infrastructure qui pourraient ne pas être configurées correctement. Il est activé sur votre compte AWS lorsque vous le créez.

Boto3 est le kit de développement logiciel (SDK) d’AWS, qui permet aux développeurs Python d’interagir et d’automatiser des taches avec la plupart des services AWS. A l’heure de l’écriture de cet article, Boto3 couvre plus de 250 services, ce qui en fait un acteur incontournable de l’environnement !

Fonctionnement de Cloudtrail

Cloudtrail génère des évènements pour chaque activité réalisée dans un compte AWS. Ainsi, tout ce qui est effectué par un service, un rôle ou un utilisateur est surveillé et stocké. Nous avons donc à notre disposition un précieux historique d’activité en JSON à notre disposition.

Dans l’interface AWS Cloudtrail, l’ensemble des évènements sont consultables via l’Historique des évènements :

CloudTrail
Interface Cloudtrail

En ouvrant un évènement, nous avons accès à toutes les informations recueillies sous forme de fichier JSON :

Une masse d’information gigantesque, puisque nous avons accès aux actions réalisées durant les 90 derniers jours et cela dans chaque des régions utilisées par le compte.

Capter les données avec Boto3

Pour utiliser Boto3, il faut commencer par appeler les librairies nécessaires et initialiser l’appel à Cloudtrail :

import boto3
import datetime
import json
dev = boto3.session.Session(profile_name='MONPROFIL_DEV', region_name='eu-west-3')
cloudtrail = dev.client('cloudtrail')

La quantité d’information est potentiellement assez importante, afin de sécuriser les transactions et garantir un code qui fonctionne, il faut donc utiliser les fonctions de pagination.

paginator = cloudtrail.get_paginator('lookup_events')
StartingToken = None
page_iterator = paginator.paginate(
    LookupAttributes=[
            {'AttributeKey': 'EventName', 'AttributeValue': 'CreateTags'},
            {'AttributeKey': 'userAgent', 'AttributeValue': 'backup.amazonaws.com'},
            {'AttributeKey': 'eventSource', 'AttributeValue': 'ec2.amazonaws.com'}
        ],
    StartTime=datetime.datetime(2021, 1, 11),
    EndTime=datetime.datetime(2021, 1, 13),
    PaginationConfig={'PageSize':10, 'StartingToken':StartingToken }
)

Ici, nous allons analyser les Tags apposés sur des instances EC2, mais nous pourrions tout à fait analyser n’importe quel paramètre parmi les plus de 3000 proposés. Nous pouvons ainsi filtrer le périmètre de recherche en cumulant les différents paramètres. En bouclant finalement sur les évènements filtrés, nous pouvons ainsi récupérer une masse d’information à exploiter :

for page in page_iterator:
    for event in page["Events"]:
        CloudTrailEvent = json.loads(event["CloudTrailEvent"])
        requestParameters = CloudTrailEvent.get('requestParameters')
        ressourceType = requestParameters.get('resourcesSet').get('items')[0]['resourceId'].split("-")[0]
        print(requestParameters)
    try:
        token_file = open("token","w") 
        token_file.write(page["NextToken"]) 
        StartingToken = page["NextToken"]
    except KeyError:
        exit()

Exploiter les résultats

Nous avons maintenant accès à toutes les informations dont nous avons besoin pour restaurer les tags dans nos EC2. Les informations reçues étant un mélange de nombreuses sources (snap, ami, …), il faudra faire encore quelques filtres afin de garantir la valeur de notre analyse. Pour cela, il faudra parcourir le JSON pour récupérer la valeur du ressourceType :

ressourceType = requestParameters.get('resourcesSet').get('items')[0]['resourceId'].split("-")[0]

Et utiliser le résultat afin de limiter une nouvelle fois le périmètre d’analyse. Pour finir, nous pourrions utiliser le code ci-dessous pour appliquer l’historique d’un Tag sur une EC2 existante, en récupérant son état d’origine parmi les 90 derniers jours d’historique :

if ressourceType == 'ami' :
    InstanceName = ''
    police = ''
    for tag in requestParameters.get('tagSet').get('items') :
        if tag['key'] == 'Name':
            InstanceName = tag['value']
        if tag['key'] == 'backup-policy' : 
            police = tag['value']
    if InstanceName in ['instance1','instance2','instance3','instance4','instance5','instance6','instance7','instance8']:
        print ('Chargement de ' + InstanceName + ' avec le tag ' + police)
        InstanceId = ec2.describe_instances(Filters=[{'Name':'tag:Name','Values': [InstanceName]}])['Reservations'][0]['Instances'][0]['InstanceId']
        ec2.create_tags(Resources=[InstanceId],Tags=[{'Key': 'backup-policy','Value': police}])

Conclusion

Les possibilités de restauration d’information de paramétrage sont donc infinies. Il est très simple avec cette méthode de boucler sur les différents historiques proposés par Cloudtrail pour remettre en état une plateforme. Pour aller plus loin, il serait même envisageable de faire des backups dans S3 de tous ces JSON dans un état réputé « stable », afin d’avoir toujours sous la main une sauvegarde des paramètres de vos environnements.

Add your Comment