🛠️

【AWS】そのリソース誰が作ったの?がわかる仕組みを考えてみた

2023/09/24に公開

概要

コストを最適化するために、定期的なリソースの棚卸はかかせません。
例えば検証用やPoCで一時的に作成したEC2を目的が達成したとしても何故かしばらく残しておくことが多々あると思います。そして、消し忘れると後に誰が作ったのかわからず消したいけど消せないと悶々とした気持ちになるのです。

誰が作ったのかが一目瞭然となれば、すぐ連絡をすることができスムーズにアクションができますよね。例えばCloudTrailとLambdaを使って作成者(Author)のタグ情報を自動的につける設定できないか考えてみました。

大まかな流れ

CloudTrailでは誰が・いつ・何をしたかが記録されるので、記録されたイベントをキャッチして、LambdaでEC2やRDSを作成した人(またはロール)のIAM ARN値をAuthorとしてタグをつけようか考えてみます。
CloudTrailからいい感じにLambdaをイベントを渡すには、CloudWatch Logsにログを配信する必要があります。フィルタに引っかかったイベントをトリガーにLambdaを実行する感じで構成を考えてみました。

構成図

CloudTrailのイベント

抜粋したものになりますが、「userIdentity」の中の「arn」を使います。
アカウントIDなどは適当に置き換えています。

{
    "eventVersion": "1.05",
    "userIdentity": {
      "type": "IAMUser",
      "principalId": "AIDATVKPPIUCE123DQ2N3",
      "arn": "**arn:aws:iam::123456789123:user/testuser**",
      "accountId": "123456789123",
      "accessKeyId": "ABCDEFGGGPWLOWPSPWDW",
      "userName": "testuser",
      "sessionContext": {
        "attributes": {
          "mfaAuthenticated": "false",
          "creationDate": "2019-07-29T04:54:48Z"
        }
      },
      "invokedBy": "signin.amazonaws.com"
    },
    "eventTime": "2019-07-29T06:22:42Z",
    "eventSource": "ec2.amazonaws.com",
    "eventName": "RunInstances",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "111.111.111.111",
    "userAgent": "signin.amazonaws.com",
    "requestParameters": {
      "instancesSet": {
        "items": [
          {
            "imageId": "ami-xxxabcd5123456789",
            "minCount": 1,
            "maxCount": 1,
            "keyName": "testkey"
          }
        ]
      },

CloudWatch Logsのイベントの例

以下はCloudWatch Logsに配信されたデータの例ですが、ログはエンコードされているのでLambdaで処理するためには一度デコードをしてあげる必要があります。

{ 
   "awslogs": { 
      "data": "XXXXXXX ..(省略).. XXX=="
   } 
}

Lambdaのソースコード

Lambda関数自体はこちらを参照。以下は補足です。

データのデコード

CloudWatch Logsから受け取ったデータをデコードしてイベントデータを取り出します。

# decode messages from cloudwatch logs

b64data = events["awslogs"]["data"]
compressed_payload = base64.b64decode(b64data)
uncompressed_payload = gzip.decompress(compressed_payload)
payload = json.loads(uncompressed_payload)
event = json.loads(payload['logEvents'][0]['message'])
jsn_str = json.dumps(event, ensure_ascii=False, default=json_serial)
logger.info(jsn_str)

タグの付与

EC2やRDSの作成はそれぞれイベント名が違うので、すこし面倒ですがif文で条件分岐してデコードしたデータの中からIAM ARN値を取得します。

elif event["eventName"] == "RunInstances":

   # var
   resource_list = []

   # extract the author's arn
   useridentify=event["userIdentity"]["arn"]
   instanceid=event["responseElements"]["instancesSet"]["items"][0]["instanceId"]
   resource_list.append(instanceid)

取得した値をタグにつけます。

response = ec2.create_tags(
   Resources=resource_list, 
   Tags=[ 
      { 
         'Key': 'Author', 
         'Value': useridentify
      }, 
   ] 
)

フィルターの設定

CloudTrailからCloudWatchにログを出力するように設定を変更します。

Lambda関数をデプロイできたら、出力されたCloudWatch Logsのロググループを選択した状態で、Lambdaサブスクリプションフィルターを作成します。

「RunInstances」はEC2が起動した際に発行されるイベント名、「CreateDBInstance」はRDSが起動した際に発行されるイベント名です。

設定結果

試しにEC2を1台作成してみて、EC2にタグが付いていることを確認してみました。
これで誰が作成したリソースなのか、ユーザ名から判断でき、必要に応じて作成したユーザへ問合せをすることができそうです!

感想

リソースごとにフィルタリングをかけるイベントが違うので、リソース別に処理分岐をしないといけなさそうなのが難点かなと思いました。
また、スイッチロールなどで運用をしている場合もどうなるか要検討で利用は限定的かもですが、一旦いい感じにリソースの作成者情報がタグに自動的に付与されましたので良かったです。
これ、わざわざ作らずともAWSさんが機能として提供してくれたりするといいなとふと思いました。

Discussion