📝

CloudFormation での EC2 インスタンス作成時に ENI に自動でタグを付与してみた

に公開

AWS::EC2::Instance NetworkInterface - AWS CloudFormation
AWS::EC2::Instance NetworkInterface にはタグに関するプロパティが存在しないため、同定義内でタグ付けすることはできません。
そのため、今回はカスタムリソースでタグ付けしてみました。

1. Lambda 関数の作成

以下の設定で作成しました。

  • ランタイム: Python 3.13
  • 実行ロール: AdministratorAccess を付与した IAM ロール
  • コード: 以下の通り
import boto3
import json
import urllib3

http = urllib3.PoolManager()

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    
    response_status = 'SUCCESS'
    response_data = {}
    
    try:
        if event['RequestType'] in ['Create', 'Update']:
            instance_id = event['ResourceProperties']['InstanceId']
            
            response = ec2.describe_instances(InstanceIds=[instance_id])
            eni_id = response['Reservations'][0]['Instances'][0]['NetworkInterfaces'][0]['NetworkInterfaceId']
            
            ec2.create_tags(
                Resources=[eni_id],
                Tags=[
                    {'Key': 'Name', 'Value': 'MyENI'}
                ]
            )
    except Exception as e:
        response_status = 'FAILED'
        response_data = {'Error': str(e)}
    
    send_response(event, context, response_status, response_data)

def send_response(event, context, status, data):
    body = json.dumps({
        'Status': status,
        'Reason': f'See CloudWatch Log Stream: {context.log_stream_name}',
        'PhysicalResourceId': context.log_stream_name,
        'StackId': event['StackId'],
        'RequestId': event['RequestId'],
        'LogicalResourceId': event['LogicalResourceId'],
        'Data': data
    })
    
    http.request('PUT', event['ResponseURL'], body=body)

カスタムリソースでのレスポンスでは cfn-response モジュールを使用する方法もありますが、cfn-response モジュールは CloudFormation テンプレート内で Lambda 関数を定義する場合かつ、ZipFile プロパティを使用する場合にのみ使用可能です。
cfn-response module - AWS CloudFormation

The module has a send method that sends a response object to a custom resource by way of an Amazon S3 presigned URL (the ResponseURL).

そのため、既存の関数をカスタムリソースとして使用する場合には独自にレスポンスを返す処理を定義する必要があります。

2. CloudFormation テンプレートの作成

今回は以下のテンプレートを使用しました。
サブネットなどはハードコーディングです。

AWSTemplateFormatVersion: "2010-09-09"

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Sub "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}"
      InstanceType: t2.micro
      SubnetId: subnet-xxx
      Tags:
        - Key: Name
          Value: MyEC2Instance

  ENITagger:
    Type: Custom::ENITagger
    Properties:
      ServiceToken: arn:aws:lambda:ap-northeast-1:012345678901:function:test
      InstanceId: !Ref EC2Instance

03. 動作確認

手順 02 の CloudFormation テンプレートをデプロイします。
スタックが CREATE_COMPLETE になった後に ENI にタグが付与されていれば成功です。

まとめ

今回は CloudFormation での EC2 インスタンス作成時に ENI に自動でタグを付与してみました。
どなたかの参考になれば幸いです。

参考資料

Discussion