Python

AWS TrustedAdvisorのBacklog課題投稿を自動化してみた

1.はじめに

今回は主にTrustedAdvisorを中心とした、AWSの最適化の取り組みをご紹介したいと思います。

ということで簡単にTrustedAdvisorを説明しますと、
「AWSのベストプラクティスとマッチしていない設定/利用法をチェックし、改善を促すサービス」
になるかと思います。

これをこれまではAWSのコンソールから目検で確認していたのですが、アカウントの増加に対応できないため、
確認と問題がある項目のBacklog投稿作業を自動化することにしました。

2.全体の構成

普段はインフラを中心に見ているため勉強も兼ねて、サーバレスな感じの構成とすることにしました。
なのでLambdaを中心にS3,SQS,IAM,CLoudWatchなどAWSのサービスを組み合わせています。

スクリーンショット 2017-12-18 21.46.30.png

3.大まかな流れ

CloudWatchによる実行

全体のキックはCloudWatch EventのRuleを利用し定期的に実行しています。

アカウント情報の取得

アカウント情報はS3内のファイルに記載しておき、Lambdaがそれを読み込みSQSに登録しています。
登録後、次のTrustedAdvisorのステータス情報を取得するLambdaを呼び出します。

Get_AwsAccount.py
def lambda_handler(event, context):
    s3 = boto3.resource('s3')
    #読み込むS3のファイルを指定
    s3_object = s3.Object('%s' %Bucket_Name,'%s/%s' %(Target_Dir,FileName))

    #ファイルを読み込み
    account_file = s3_object.get()
    #本文抽出
    account_info = account_file['Body'].read()
    #アカウント毎に別ける
    accounts = account_info.split()

    for account in accounts:
        #SQSに登録する本文を作成
        queue_body = 'arn:aws:iam::アカウント番号:role/ロール名'

        #SQSに情報を送信する
        responce = boto3.client('sqs').send_message(
            QueueUrl = 'キューURL',
            MessageBody = queue_body
        )

    lambda_client = boto3.client('lambda')
    response2 = lambda_client.invoke(
        FunctionName = 'Get_TrustedAdvisor_Detail',
        InvocationType = 'RequestResponse',
        LogType = 'Tail',
    )

SQSに登録する情報はAssumeRoleに利用する各アカウントのIAMRole ARNです。
なお、AssumeRoleするためには、事前に各アカウントでIAMRoleを作成しておく必要があります。

今回はSQSの利用テストも兼ねて組み込みんだので、S3に置いてあるファイルに直接ARN情報を書けば、
SQSは無くても大丈夫ですw

TrustedAdvisorのステータス情報取得

SQSに登録されたIAMRoleのARNを利用して、各アカウントのTrustedAdvisorの情報を収集、
その内容をS3に吐き出します。

Get_TrustedAdvisor_Detail.py
def lambda_handler(event, context):
    s3 = boto3.client('s3')
    lambda_function = boto3.client('lambda')
    sqs = boto3.client('sqs')

    #キューを取得
    get_queue = sqs.receive_message(
        QueueUrl = Sqs_URL,
        WaitTimeSeconds = 3
    )

    Messages = get_queue['Messages']
    ReceiptHandle = Messages[0]['ReceiptHandle']

    #取得済みのキューを削除
    delete_queue = sqs.delete_message(
        QueueUrl = Sqs_URL,
        ReceiptHandle = ReceiptHandle
    )

    target_role_arn = Messages[0]['Body']
    sts_region = "ap-northeast-1"

    #他のAWSAccountに接続するための認証情報を取得する
    credentials = get_sts_credentials(target_role_arn, sts_region)

    #取得した認証情報を使ってそのアカウントのTrustedAdvisorへの接続設定を行う
    support = boto3.client(
        'support',
        region_name = 'us-east-1',
        aws_access_key_id=credentials['AccessKeyId'],
        aws_secret_access_key=credentials['SecretAccessKey'],
        aws_session_token=credentials['SessionToken']
    )

    #TrustedAdvisorの詳細情報を取得する
    TACheck = support.describe_trusted_advisor_checks(language='en')

    #######################################
    ###必要な情報を整理し、S3に吐き出す処理を書く###
    #######################################

    #キューがなくなるまでこの処理を繰り返す
    list_queue = sqs.list_queues()

    if len(list_queue['QueueUrls']) != 0:
        lambda_client = boto3.client('lambda')
        response2 = lambda_client.invoke(
            FunctionName = 'Get_TrustedAdvisor_Detail',
            InvocationType = 'RequestResponse',
            LogType = 'Tail',
        )

#AssumeRoleして他アカウントの認証情報を取得
def get_sts_credentials(role_arn, sts_region):
    sts_endpoint_url = "https://sts." + sts_region + ".amazonaws.com"
    sts_client = boto3.client('sts',endpoint_url=sts_endpoint_url,use_ssl=True)
    assume_role = sts_client.assume_role(
        RoleArn=role_arn,
        RoleSessionName="セッション名"
    )
    return assume_role['Credentials']

Backlogへの投稿

S3にファイルがPutされることをトリガーに、Backlogを投稿するLambdaが投稿用に情報を編集し、
Backlog APIを利用して投稿します。

Post_Backlog.py
def lambda_handler(event, context):

    ##################################
    ###S3に書き出した情報を取得し、整形する###
    ##################################

    project_id = '1234567890'
    issue_type_id = '1234567890'
    priority_id = '3'
    summary = '件名'
    description = '本文'

    #Backlog投稿メソッド呼び出し
    r = add_issue(project_id, issue_type_id, priority_id, summary, description)

#Backlogチケット投稿
def add_issue(_project_key, _issue_type_id, _priority_id, _summary, _description):
    api = 'issues'
    url = BASE_URL.format(space_key=space_key, api=api, api_key=api_key)
    #投稿の詳細指定
    payload={
        'projectId': _project_key,
        'issueTypeId': _issue_type_id,
        'priorityId': _priority_id,
        'categoryId[]':'1234567890',
        'summary': _summary,
        'description': _description
    }

    #投稿実行
    r = requests.post(url, data=payload)
    r.raise_for_status()
    return r

あんまりコーディングしないので、こうすると良いよとかあったらご指摘下さい。

4.こんなんなりました

手動で対応していたときと比べ、確認しているAWSアカウント数と項目数が6倍になりました。

起票は楽になりましたが、改善はあまりペースが変わっていないので、
今後は問題がある項目を自動的に改善するようなLambdaを作成していきたいと考えています。