CoderCastrov logo
CoderCastrov
AWS

Как работать с пользовательским рекордером AWS Config?

Как работать с пользовательским рекордером AWS Config?
просмотров
2 мин чтение
#AWS

Отказ от ответственности: Я не являюсь экспертом по REGEX 😄

В последнее время я работал для одного из своих клиентов над настройкой пользовательского рекордера AWS Config.

Мой клиент хотел записывать все ресурсы, кроме нескольких:

  • 'AWS::EC2::Subnet'
  • 'AWS::EC2::VPC'
  • 'AWS::EC2::SecurityGroup'

К сожалению, API и консоль AWS не позволяют это сделать, вам нужно вручную выбирать ресурсы, которые вы хотите записать.

Недостатком этого метода является то, что если появится новый тип ресурса AWS Config, он не будет записан, пока вы не выберете его в настройках рекордера AWS Config.

Чтобы справиться с этим, я создал очень простой скрипт на Python, который использует веб-скрапинг документации AWS для извлечения поддерживаемых типов ресурсов, а затем применяет все ресурсы, кроме тех, которые находятся в черном списке моего клиента.

Идея заключается в том, чтобы запускать этот скрипт раз в неделю, чтобы быть в курсе последних обновлений.

import boto3
import re
from urllib.request import urlopen
import logging

# [https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/config.html#ConfigService.Client.put_configuration_recorder](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/config.html#ConfigService.Client.put_configuration_recorder)
# Цель:
# Активировать пользовательский рекордер AWS для AWS Config
# Поддерживаемые типы ресурсов: [https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources](https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources)
# Скрапинг документации AWS с использованием: [https://realpython.com/python-web-scraping-practical-introduction/](https://realpython.com/python-web-scraping-practical-introduction/)

# Получить информацию о текущем региональном рекордере конфигурации: aws configservice describe-configuration-recorders --region eu-west-1

# Логирование
root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',level=logging.INFO)

# Конфигурация
recorder_name = "<название вашего рекордера AWS Config>"
role_arn = "<ARN роли рекордера AWS Config>"

# Укажите здесь типы ресурсов AWS Config, которые нужно исключить из записи
blacklisted_types = [
    'AWS::EC2::Subnet',
    'AWS::EC2::VPC',
    'AWS::EC2::SecurityGroup'
]

def get_config_resources():
    url = "[https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources](https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources)"
    page = urlopen(url)
    html = page.read().decode("utf-8")

    # Целевой формат: AWS::ApiGateway::Stage
    pattern = "AWS::.*"
    match_results = re.findall(pattern, html)
    cleaned_list = []
    count = 0

    for result in match_results:
        # удалить HTML-теги
        results = re.sub("<.*?>", "", result) 
        # удалить завершающую *
        results = results.replace("*", "")
        # удалить пробелы
        results = results.replace(" ", "")
        # удалить длинные элементы (предложения)
        if len(results) >= 60:
            continue
        # удалить дубликаты из списка, сохраняя порядок
        list(dict.fromkeys(results))
        # Подсчитать элементы
        count += 1
        # Создать целевой очищенный список
        cleaned_list.append(results)

    logging.info("Получено поддерживаемых ресурсов Config: %s", count)

    return cleaned_list

def apply_custom_recorder(config_resources):
    # Удалить ресурсы из черного списка из общего списка
    result_list = list(set(config_resources) - set(blacklisted_types))

    # Счетчик
    count_result = 0

    # Подсчитать количество типов ресурсов (за исключением ресурсов из черного списка)
    for type in result_list:
        count_result += 1

    logging.info("result_types: %s", count_result)

    client = boto3.client('config')

    try:
        r = client.put_configuration_recorder(
                ConfigurationRecorder={
                    'name': recorder_name,
                    'roleARN': role_arn,
                    'recordingGroup': {
                        'allSupported': False,
                        'includeGlobalResourceTypes': False,
                        'resourceTypes': result_list
                    }
                }
            )
    except Exception as e:
        logging.error(e)

    logging.info("Response: %s", r)

if __name__ == "__main__":
    config_resources = get_config_resources()
    apply_custom_recorder(config_resources)

Gist версия, если вы хотите внести свой вклад.

Я думаю, что этот подход может помочь кому-то еще, поэтому я делюсь им с вами. Не стесняйтесь комментировать и улучшать его по своему усмотрению.

Вот и все, друзья!

zoph.

Этот пост был опубликован на zoph.me. Подпишитесь на меня в Twitter.