AWS – Python – Levantamento de instâncias EC2

Objetivo

Listar todas as instâncias EC2 em todas as regiões de todos os perfis que constam no arquivo credentials

Método

Execução:

  1. O script abre o arquivo credentials. Ele ignora o perfil “default” que são as 3 primeiras linhas.
  2. Busca pelas regiões habilitadas para o perfil criando um array com as regiões.
  3. Faz uma busca pelo account_id da conta relacionada ao perfil do arquivo credencials que está sendo analisada.
  4. Busca por todas as instâncias que tenham um IAM Instance Profile (IAM Role) em uma determinada região.
  5. Busca por todas as instâncias EC2 para cada uma das regiões onde perfil poderia ter instâncias criadas.

OBS:

Para que o script execute corretamente, o arquivo credentials só pode ter uma entrada de perfil para cada conta AWS.

Se houver mais de uma access key/secret key no arquivo credentials a saída do script ficará duplicada.

Se não houver uma credencial associada a alguma conta AWS, a conta em questão não será analisada.

Assim, se queremos analisar 20 contas AWS precisaremos de 20 credenciais cadastradas.

O formato de cada credencial no arquivo credentials deve ser semelhante a esta:

[aplicacoes]

aws_access_key_id = AKIACHAVEFAKEPYNDW2VF4

aws_secret_access_key = i7U!!9887chavefake34ll2678E4bgqW

Em máquinas Windows, por padrão, o arquivo credentials fica localizado em %USERPROFILE%\.aws\

O script também considera que as 3 primeiras linhas do arquivo credencials são destinadas para o perfil default.

Código
				
					import boto3
import os.path

'''
Objetivo: Listar todas as instâncias EC2 de todos os perfis que constam no arquivo credentials
Execução: 
1. O script abre o arquivo credentials. Ele ignora o perfil "default" que são as 3 primeiras linhas. 
2. Busca pelas regiões habilitadas para o perfil criando um array com as regiões.
3. Faz uma busca pelo account_id da conta relacionada ao perfil do arquivo credencials que está sendo analisada.
4. Busca por todas as instâncias que tenham um IAM Instance Profile (IAM Role) em uma determinada região.
5. Busca por todas as instâncias EC2 para cada uma das regiões onde perfil poderia ter instâncias criadas.

OBS:
Para que o script execute corretamente o arquivo credencials só pode ter uma entrada de perfil para cada conta AWS.
Se houver mais de uma access key/secret key no arquivo credecials a saída do script ficará duplicada.
Se não houver uma credencial associada a alguma conta AWS, a conta em questão não será analisada.
Assim, se queremos analisar 20 contas AWS precisaremos de 20 credenciais cadastradas.
O formato de cada credencial no arquivo credencials deve ser semelhante a esta:

[aplicacoes]
aws_access_key_id = AKIADF4CHAVEFAKEOPYNDW2VF4
aws_secret_access_key = i7U!!9887chavefakehKUuyh9ajQVnC6BE4bgqW

Em máquinas Windows, por padrão, o arquivo credentials fica localizado em %USERPROFILE%\.aws\ 

O script também considera que as 3 primeiras linhas do arquivo credencials são destinadas para o perfil default.
'''
path = "~/.aws/credentials"
full_path = os.path.expanduser(path)

aws_account = []

with open(full_path, 'r') as f:  # abre o arquivo de credenciais
    next(f) # ignora a credencial "default" (3 primeiras linhas)
    next(f)
    next(f)
    lines = f.readlines()  # lê o arquivo e joga como array em linhas
    f.close()

for line in lines: # faz um loop em linhas para verificar se é o nome do profile, o access_key ou o secret_access_key
    if line.startswith('['):  # se a linha começar com colchetes então é o nome do perfil AWS
        perfil = line[1:-2]

        regions_array = []  # array que irá conter todas as regiões

        ##########################
        # Nesta seção são recuperadas as regiões para um perfil (conta AWS)
        session_region = boto3.Session(profile_name=perfil)  # abre uma sessão com o perfil definido na variável perfil
        client_region = session_region.client('ec2')  # abre um cliente do tipo ec2 que irá ser utilizado para \
        # verificar as regiões habilitadas para o usuário atrelado as credenciais

        response_regions = client_region.describe_regions()  # response é um dicionário com KEY Regions que por sua\
        # vez tem VALUE com sendo um array de dicionários que contém a KEY RegionName

        regions = response_regions["Regions"]  # regions é do tipo array composto por elementos que são dicionários,\
        # que por sua vez têm a chave RegionName

        for region in regions:  # cria um array com as regiões para o usuário IAM que conectou através das credenciais\
            # do arquivo credencials
            regions_array.append(region["RegionName"])

        ###########################
        # para cada região o script irá recuperar o account_id, depois irá buscar todas as instâncias que tenham um \
        # IAM Instance Profile e por fim irá buscar as instâncias da região.
        for x in range(0, len(regions_array)):  # faz um loop por todas as regiões contidas no array regions_array e \
            # mais adiante irá procurar pelas instâncias EC2
            session_ec2 = boto3.Session(profile_name=perfil)
            client_ec2 = session_ec2.client('ec2', # abre um cliente do tipo ec2
                                   region_name=regions_array[x]
                                   )
            nome_regiao = regions_array[x]  # armazena a região sendo analisada.
            response_ec2 = client_ec2.describe_instances()  # recupera as instâncias.

            session_sts = boto3.Session(profile_name=perfil) # abre uma sessão para buscar o account_id.
            client_sts = session_sts.client('sts', # abre um cliente do tipo sts para recuperar o account_id.
                                   region_name=regions_array[x]
                                   )
            ################
            # código abaixo pega os iam instance profiles de cada instância. Se uma instância não tiver uma IAM Role, \
            # então, não irá aparecer na lista.
            response_instance_profiles = client_ec2.describe_iam_instance_profile_associations()  # cria a descrição\
            # dos iam instance profiles das instâncias do client_ec2.

            instance_profiles = response_instance_profiles["IamInstanceProfileAssociations"]  # instance_profiles será\
            # do tipo array contendo dicionários somente com as instâncias com iam instance profile associado.

            id_arn = {}  # cria o dicionário que irá conter os InstanceIDs e os IAM instance profiles Arn.

            for instance_profile in instance_profiles:  # itera para criar um dicionário que irá conter itens de\
                # dicionário com as keys sendo o InstanceId e value o InstanceProfileArn.
                # cria um dicionário que tem o Id da instância e o ARN do Instance Profile.
                id_arn[instance_profile['InstanceId']] = instance_profile['IamInstanceProfile']['Arn'].split('/')[1].strip()

            ###################
            # a seção a seguir faz uma busca pelas instâncias EC2 em uma região e imprime as instâncias que forem encontradas.
            instanceprofilearn = 'N/A'
            for reservation in response_ec2['Reservations']:  # faz loop procurando dentro do dicionário response_ec2.
                for instance in reservation['Instances']:  # faz loop procurando por instâncias.
                    instanceprofilearn = 'N/A'  # configura o IAM Instance Profile como N/A.
                    for key in id_arn: # itera dentro do dicionário que tem as instâncias e seus respectivos IAM instance profile.
                        if key == instance['InstanceId']: # se a instância buscada tiver um IAM instance profile, \
                            # então, seta a variável instanceprofilearn com o nome do IAM Instance Profile.
                            instanceprofilearn = id_arn[key]

                print("Profile:{};AccountID:{};Region:{};InstanceID:{};Type:{};Status:{};Plataform:{};IAMInstanceProfileARN:{}"
                      .format(perfil, client_sts.get_caller_identity().get('Account'), regions_array[x], instance['InstanceId'], \
                              instance['InstanceType'], instance['State']['Name'], instance['PlatformDetails'], instanceprofilearn))
				
			

It’s done!

Bruno Veiga

Bruno Veiga

Arquiteto Cloud e Arquiteto de Soluções. Me dedicando em compartilhar conhecimento e ajudar empresas a encontrar as melhores soluções tecnológicas para os problemas do negócio com agilidade, segurança, equipes alinhadas e dentro do orçamento.