目的
リソースの起動停止を「Auto:on/off」というタグの値で制御している環境があります。
この環境では以下の要件がありました。
- ① タグの付け忘れを防ぐために、デフォルトで「Auto:on」を自動的に付与したい
- ② 必要に応じて手動で「off」に変更できるようにしておきたい
これを実現するにはどうすれば良いでしょうか?
考えたこと
真っ先に思いついたのは以下の方法でした。AWS Config のマネージドルール「required-tags」でタグの有無をチェックし、非準拠のリソースに対して修復アクションの「SetRequiredTags」を適用することでタグの付与ができるのではないか?
たしかに、非準拠となったリソースに修復アクションで「Auto:on」を付与することで、要件 ① は満たすことができます。
しかし、このアプローチでは「off」に設定しているリソースも非準拠と見なされ、強制的に「on」に変更されてしまうため、要件 ② に抵触してしまいます。
そこで、required-tags ルールではタグキー「Auto」の有無のみをチェックするように設定し、修復アクションとして SNS に通知を送る仕組みを採用しました。
この SNS 通知をトリガーに Lambda を実行し、デフォルトのタグ「Auto:on」を付与する構成を考えました。
これにより、タグの値はチェックされないまま、デフォルトのタグを自動付与することができます。
構成図
事前準備
設定で必要となるリソースを先に作成しておきます。
対象リソース | 概要 |
---|---|
SNS トピック | 修復アクションで利用するためのもの |
自動修復アクション用 IAM ロール | SNS のオートメーションを利用するためのもの 信頼関係に Systems Manager を許可、AmazonSNSFullAccess ポリシーをアタッチ |
Lambda 実行用 IAM ロール | Lambda が他サービスへタグを付けるためのもの 信頼関係に Lambda を許可、タグを付与するサービスへの権限と、AWSLambdaBasicExecutionRole ポリシーをアタッチ |
AWS Config の設定
まずは AWS Config の設定を行います。
今回の仕組みのためであればデータの保持期間は最短の30日で十分です。
ルールの追加
required-tags ルールを追加します。
評価モードの箇所でチェックを行うタイミングと、対象とするリソースカテゴリを選択します。
今回は、EC2 および RDS インスタンスを対象としました。
なお、required-tags に対応しているリソースカテゴリは以下の通りです。
AWS::ACM::Certificate
AWS::AutoScaling::AutoScalingGroup
AWS::CloudFormation::Stack
AWS::CodeBuild::Project
AWS::DynamoDB::Table
AWS::EC2::CustomerGateway
AWS::EC2::Instance
AWS::EC2::InternetGateway
AWS::EC2::NetworkInterface
AWS::EC2::NetworkAcl
AWS::EC2::RouteTable
AWS::EC2::SecurityGroup
AWS::EC2::Subnet
AWS::EC2::Volume
AWS::EC2::VPC
AWS::EC2::VPNConnection
AWS::EC2::VPNGateway
AWS::ElasticLoadBalancing::LoadBalancer AWS::ElasticLoadBalancingV2::LoadBalancer
AWS::RDS::DBInstance
AWS::RDS::DBSecurityGroup
AWS::RDS::DBSnapshot
AWS::RDS::DBSubnetGroup
AWS::RDS::EventSubscription
AWS::Redshift::Cluster
AWS::Redshift::ClusterParameterGroup
AWS::Redshift::ClusterSecurityGroup
AWS::Redshift::ClusterSnapshot
AWS::Redshift::ClusterSubnetGroup
AWS::S3::Bucket
例えば、RDS ならインスタンスは対応していてもクラスターは対応していません。
画面上では対応していないサービスも選択できてしまうので要注意ですね。
次に、パラメータにて評価するタグを入力します。
上述した通り、タグキー「Auto」のみを評価するようにしています。
修復アクションの設定
修復アクションは以下のように設定しています。
再試行回数や時間、レート制限は必要に応じて設定いただければと思います。
また、SNS に渡すことのできるパラメータはリソース ID のみです。
これをメッセージに含めるように設定し、事前に作成しておいた SNS トピック、および IAM ロールの ARN を入力します。
これで AWS Config の設定は完了です。
Lambda の設定
Lambda では、事前に作成しておいた SNS トピックをトリガーに、IAM ロールを実行ロールとして設定します。
肝心のコードは Python 3.13 で書いてみました。
import json import boto3 # EC2、RDSインスタンスのクライアントを作成 ec2_client = boto3.client('ec2') rds_client = boto3.client('rds') def lambda_handler(event, context): # SNSイベントを取得 for record in event['Records']: resource_id = record['Sns']['Message'] # タグを追加するための共通タグ tags = [{'Key': 'Auto', 'Value': 'on'}] try: # EC2インスタンスの場合 if resource_id.startswith('i-'): ec2_client.create_tags( Resources=[resource_id], Tags=tags ) print(f"Added 'Auto:on' tag to EC2 instance {resource_id}") # RDSインスタンスの場合 elif resource_id.startswith('db-'): arn = get_rds_instance_arn(resource_id) rds_client.add_tags_to_resource( ResourceName=arn, Tags=tags ) print(f"Added 'Auto:on' tag to RDS instance {resource_id}") else: print(f"Unsupported resource ID format: {resource_id}") except Exception as e: print(f"Error adding tag to resource {resource_id}: {str(e)}") raise e return { 'statusCode': 200, 'body': 'Tagging process completed.' } #RDSインスタンスのARNを取得 def get_rds_instance_arn(resource_id): try: response = rds_client.describe_db_instances( Filters=[{"Name": "dbi-resource-id", "Values": [resource_id]}] ) arn = response['DBInstances'][0]['DBInstanceArn'] return arn except Exception as e: print(f"Error retrieving ARN for RDS instance {resource_id}: {e}") return None
ポイントとしては以下が挙げられます。
- SNS メッセージにはリソース ID しか含まれていないため、接頭辞を利用してリソースの判別を行った
- AWS SDK で RDS にタグを付与する際は ARN が必要なので、リソース ID しか情報がないことを考慮し、describe コマンドを使用して ARN を取得するようにした
これで設定は完了です。
終わりに
私が関わった案件で実際に求められた内容を基に、タグ付けを自動化する一例としてご紹介しました。
今回の方法は、本来想定されている AWS Config の使い方とは少し異なるかもしれませんが、工夫次第でこのような仕組みを実現することができました。
そのまま適用できるケースは限られるかもしれませんが、似たようなケースに取り組む際の参考になれば幸いです。