Cloner un Security Group inter-région / inter-compte

Aujourd’hui, nous allons voir comment automatiser le clone d’un Security Group d’un compte vers un autre, ou d’une région vers une autre dans un même compte, ou encore un mix des deux.

La fonctionnalité de duplication d’un Security Group n’est disponible que dans une même région d’un compte. Dans le cas d’une migration d’une stack applicative complète d’une zone vers une autre … nous sommes obligés de faire cette copie à la main. Pour éviter une copie longue, fastidieuse et source d’erreurs, nous allons automatiser cette création de nouveaux Security Groups depuis l’existant via Python.

 

Depuis une machine ayant un AWS cli installé et configuré (tuto dans cet article), nous allons utiliser un environnement Python 2.7.14 avec le module aws boto3 installé.

Créons un emplacement dédié :

[root@monHost ~]# mkdir monModule
[root@monHost ~]# cd monModule
[root@monHost ~]# mkdir {bin, lib}

Une petite librairie pour EC2 est à créer (une partie du moins). Créons le fichier lib/EC2.py :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Jonathan LAMBERT"

import boto3
from botocore.exceptions import ClientError

class EC2:

        def __init__(self):
                self.client = None
                self.resource = None
                self.securityGroups = []

        def connect(self, session=None):
                if session == None:
                        self.client = boto3.client('ec2')
                        self.resource = boto3.resource('ec2')
                else:
                        self.client = session.client('ec2')
                        self.resource = session.resource('ec2')

        def getSecurityGroup(self, sgIds):
                for sgId in sgIds:
                        resp = self.client.describe_security_groups(GroupIds=[sgId])
                        self.securityGroups.append(resp['SecurityGroups'][0])
                        for elem in self.securityGroups[-1]['IpPermissions']:
                                if elem['UserIdGroupPairs'] != []:
                                        elem['UserIdGroupPairs'] = []
                        for elem in self.securityGroups[-1]['IpPermissionsEgress']:
                                if elem['UserIdGroupPairs'] != []:
                                        elem['UserIdGroupPairs'] = []
                                if elem['IpProtocol'] == '-1' and len(elem['IpRanges']) == 1 and elem['IpRanges'][0]['CidrIp'] == '0.0.0.0/0':
                                        self.securityGroups[-1]['IpPermissionsEgress'].remove(elem)
                                        continue
                return self.securityGroups

        def createSecurityGroup(self, sgList, newVPC=None):
                for sg in sgList:
                        if newVPC == None:
                                response = self.client.create_security_group(GroupName=sg['GroupName'], Description=sg['Description'], VpcId=sg['VpcId'])
                        else:
                                response = self.client.create_security_group(GroupName=sg['GroupName'], Description=sg['Description'], VpcId=newVPC)
                        if sg['IpPermissions'] != []:
                                self.client.authorize_security_group_ingress(GroupId=response['GroupId'], IpPermissions=sg['IpPermissions'])
                        if sg['IpPermissionsEgress'] != []:
                                self.client.authorize_security_group_egress(GroupId=response['GroupId'], IpPermissions=sg['IpPermissionsEgress'])
                        sgObj = self.resource.SecurityGroup(response['GroupId'])
                        sgObj.create_tags(Tags=sg['Tags'])

 

Pour utiliser ces quelques fonctions, nous allons faire un petit script avec appels aux fonctions ci-dessus. Nous l’appellerons bin/copySecurityGroup.py :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Jonathan LAMBERT"

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
from EC2 import EC2
import boto3

def main():
        ec2 = EC2()
        print "Copy from ..."
        ec2.connect(boto3.Session(profile_name='prod_irlande', region_name='eu-west-1'))
        sgList = ec2.getSecurityGroup(['sg-e2b6xxxx', 'sg-8c48xxxx', 'sg-bb4bxxxx', 'sg-ce1exxxx'])
        print "Copy to ..."
        ec2.connect(boto3.Session(profile_name='prod_paris', region_name='eu-west-3'))
        ec2.createSecurityGroup(sgList, 'vpc-fd29xxxx')

if __name__ == '__main__':
        main()

Passer le main en exécutable :

[root@monHost ~]# chmod +x bin/copySecurityGroup.py

 

Ici, on crée une session sur notre zone Irlande et on utilise par exemple notre profile prod_irlande.

On désire ensuite copier les 4 Security Groups listés : ‘sg-e2b6xxxx’, ‘sg-8c48xxxx’, ‘sg-bb4bxxxx’, ‘sg-ce1exxxx’.

La zone de destination est dans notre exemple celle de Paris, donc notre profile de destination est prod_paris.

Les Security Groups vont être rattachées à un nouveau VPC, il convient d’indiquer celui qui vous intéresse.

 

On exécute le script pour tester :

[root@monHost ~]# ./bin/copySecurityGroup.py
Copy from ...
Enter MFA code for arn:aws:iam::067591xxxxxx:mfa/jonathan.lambert@easyxxxx.fr:
Copy to ...
Enter MFA code for arn:aws:iam::067591xxxxxx:mfa/jonathan.lambert@easyxxxx.fr:

 

Je vérifie via l’interface web AWS : mes Security Groups sont bien dupliqués et disponibles dans ma nouvelle zone de Paris !

On voit dans l’exemple que je suis interrogé 2 fois pour le MFA. Cela correspond à l’authentification via le premier profile pour la source (prod_irlande) et pour la destination (prod_paris).

 

Vous pouvez bien entendu ajouter à votre guise un petit parser d’arguments afin d’améliorer la lisibilité de l’outil 🙂