CloudTrail + Lambda를 활용하여 EC2 공인 IP 할당을 감지하고 통지해 봤습니다.

CloudTrail + Lambda를 활용하여 EC2 공인 IP 할당을 감지하고 통지해 봤습니다.

CloudTrail + Lambda를 활용하여 EC2 공인 IP 할당을 감지하고 통지해 봤습니다.
Clock Icon2025.06.17

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 CloudTrail + Lambda를 활용하여 EC2 공인 IP 할당을 감지하고 통지해 봤습니다.

IAM 정책 및 역할 생성

먼저 Lambda 함수에 EC2, SNS, CloudWatch에 대한 권한과 EC2 인스턴스, 네트워크 인터페이스를 검사하기 위해 [ec2:DescribeInstances]. [ec2:DescribeNetworkInterfaces]에 대한 권한을 할당합니다.

[arn:aws:sns:ap-northeast-2:xxxxxxxxxx]에는 SNS 토픽 Arn을 입력합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeNetworkInterfaces"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": "arn:aws:sns:ap-northeast-2:xxxxxxxxxx"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}

Lambda 함수 코드 작성

Lambda 함수의 런타임은 [Python 3.13]을 지정합니다.

[arn:aws:sns:ap-northeast-2:xxxxxxxxxx]에는 SNS 토픽 Arn을 입력합니다.

Lambda 함수는 AssociateAddress 또는 ModifyNetworkInterfaceAttribute 이벤트 발생 시 EC2 인스턴스에 퍼블릭 IP가 할당된 것을 감지하고 SNS로 경고를 전송합니다. 처음 EC2 인스턴스를 생성할 때 Public IP를 할당하거나 EIP 생성만으로 이메일을 전송하는 것은 아닙니다. EIP를 생성하고 EC2 인스턴스에 EIP를 할당하면 이메일이 전송됩니다.
※ 이번 블로그의 주 목적은 Private한 EC2 인스턴스에 공인 IP가 악의적으로 할당되었을 가능성을 고려한 구성입니다.

import json
import boto3

ec2 = boto3.client('ec2')
sns = boto3.client('sns')

SNS_TOPIC_ARN = 'arn:aws:sns:ap-northeast-2:xxxxxxxxxx'

def lambda_handler(event, context):
    print("Received event:", json.dumps(event))

    # 이벤트 정보 추출
    detail = event.get('detail', {})
    instance_id = detail.get('requestParameters', {}).get('instanceId')
    eni_id = detail.get('requestParameters', {}).get('networkInterfaceId')
    public_ip = detail.get('requestParameters', {}).get('publicIp')

    if not instance_id and not eni_id:
        print("No instanceId or networkInterfaceId in event")
        return {'statusCode': 400, 'body': 'Missing required parameters'}

    message_lines = []

    if instance_id:
        response = ec2.describe_instances(InstanceIds=[instance_id])
        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                for iface in instance['NetworkInterfaces']:
                    if iface.get('Association', {}).get('PublicIp'):
                        message_lines.append(
                            f"Instance {instance_id} has public IP: {iface['Association']['PublicIp']}"
                        )

    if eni_id:
        response = ec2.describe_network_interfaces(NetworkInterfaceIds=[eni_id])
        for iface in response['NetworkInterfaces']:
            if iface.get('Association', {}).get('PublicIp'):
                message_lines.append(
                    f"ENI {eni_id} has public IP: {iface['Association']['PublicIp']}"
                )

    if message_lines:
        message = "\n".join(message_lines)
        print("ALERT:", message)
        sns.publish(
            TopicArn=SNS_TOPIC_ARN,
            Subject="⚠️ Public IP Attached to EC2/ENI",
            Message=message
        )
    else:
        print("No public IP associated")

    return {
        'statusCode': 200,
        'body': 'Inspection complete'
    }

EventBridge 규칙 생성

Lambda 함수를 생성했다면, 이제 EventBridge 규칙을 생성합시다.

이벤트 트리거 조건으로는 [AssociateAddress]와 [ModifyNetworkInterfaceAttribute]입니다.

{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventName": ["AssociateAddress", "ModifyNetworkInterfaceAttribute"]
  }
}

결과 확인

테스트를 위해 먼저 EIP를 생성합니다. 먼저 두 개의 EIP를 생성하는데, 하나의 EIP는 EC2 인스턴스에 직접 할당합니다.

jw-eiptestec2-1

[test-ec2-1]은 EC2 인스턴스 생성 시 Public IP 자동 할당을 했고, [test-ec2-2]는 조금 전에 생성한 EIP 중 하나를 할당했습니다.

jw-eiptestec2-2

이메일을 확인해 보면, [test-ec2-2]에 Public IP가 할당되었다고 이메일이 온 것을 확인할 수 있습니다.

jw-eiptestec2-3

문의 사항은 클래스메소드 코리아로!

클래스메소드 코리아에서는 다양한 세미나 및 이벤트를 진행하고 있습니다.
진행중인 이벤트는 아래 페이지를 참고해주세요.

https://classmethod.kr/board/library

AWS에 대한 상담 및 클래스 메소드 멤버스에 관한 문의사항은 아래 메일로 연락주시면 감사드립니다!
Info@classmethod.kr

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.