RDS 퍼블릭 액세스 설정을 감지하고 이메일로 통지

RDS 퍼블릭 액세스 설정을 감지하고 이메일로 통지

RDS 퍼블릭 액세스 설정을 감지하고 이메일로 통지하는 구성을 만들어 봤습니다.
Clock Icon2025.06.19

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 RDS 퍼블릭 액세스 설정을 감지하고 이메일로 통지하는 구성을 만들어 봤습니다.

IAM 정책 및 역할 생성

IAM에는 Lambda 함수의 로그를 기록하기 위한 CloudWatch 권한과 이메일 전송을 위한 SNS 권한 그리고 생성한 DB 인스턴스에 대한 정보를 받아오기 위한 DescribeDBInstances 권한을 할당합니다.

https://docs.aws.amazon.com/ko_kr/documentdb/latest/developerguide/API_DescribeDBInstances.html

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

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances"
            ],
            "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 함수 생성 및 코드 작성

EventBridge에서 이벤트가 발생하면, Lambda 함수가 트리거 됩니다. 해당 Lambda 함수에서는 DB 인스턴스 ID와 퍼블릭 액세스 여부, 이벤트 이름 등을 추출하여 이메일로 전송합니다.

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

import json
import boto3

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

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', {})
    request_params = detail.get('requestParameters', {})

    db_instance_id = request_params.get('dBInstanceIdentifier', 'unknown')
    public_access = request_params.get('publiclyAccessible', False)

    print(f"DBInstanceIdentifier: {db_instance_id}, PubliclyAccessible: {public_access}")

    if public_access:
        subject = "⚠️ RDS 퍼블릭 액세스 설정 감지"
        message = f"""
🔒 보안 경고: RDS 인스턴스가 퍼블릭하게 설정되었습니다.

- DB 인스턴스 ID: {db_instance_id}
- 퍼블릭 액세스: {public_access}
- 이벤트 이름: {detail.get('eventName')}
- 호출자: {detail.get('userIdentity', {}).get('arn')}
- 리전: {event.get('region')}
- 시간: {event.get('time')}

보안을 위해 즉시 설정을 확인하세요.
"""

        sns.publish(
            TopicArn=SNS_TOPIC_ARN,
            Subject=subject,
            Message=message
        )

    return {
        'statusCode': 200,
        'body': f"Checked RDS instance {db_instance_id}, public access: {public_access}"
    }

EventBridge 규칙 생성

EventBridge 규칙에서는 [CreateDBInstance]와 [ModifyDBInstance] 이벤트 발생 시 Lambda 함수가 실행되도록 설정합니다.

즉, RDS가 생성되거나 수정될 때 해당 이벤트가 감지되며, Lambda 함수가 이를 처리합니다.
이 Lambda 함수는 퍼블릭 액세스 설정(PubliclyAccessible)이 활성화되어 있는지 확인하고, 활성화된 경우 SNS를 통해 이메일 알림을 전송하는 구조입니다.

{
  "source": ["aws.rds"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventName": ["CreateDBInstance", "ModifyDBInstance"]
  }
}

결과 확인

먼저 테스트로 RDS를 생성할 때 퍼블릭 액세스를 활성화한 상태로 생성해 봅시다.

jw-rdstestblg-1

RDS 생성하자 이메일로 퍼블릭 액세스 설정 감지 통지가 날아온 것을 확인할 수 있습니다. RDS를 생성했을 때 발생하는 [CreateDBInstance]를 이메일에서 확인할 수 있습니다.

jw-rdstestblg-2

이번에는 퍼블릭 액세스 거부한 RDS를 수정하여 퍼블릭 액세스를 허용해 봅시다.

jw-rdstestblg-3

기존 RDS를 수정하자 [ModifyDBInstance] 이벤트가 발생하고, 퍼블릭 액세스가 허용되었다는 이메일이 날아옵니다.

jw-rdstestblg-4

마지막으로 CloudTrail을 통해 흐름을 확인해 보면, RDS가 생성되고서 로그 그룹과 로그가 생성된 것을 확인할 수 있습니다. 여기서 로그 그룹이 생성된 것은 Lambda 함수가 실행되었다는 것을 의미합니다. 이어서 RDS에 수정이 일어나자 또 로그가 생성된 것을 확인할 수 있습니다.

jw-rdstestblg-5

본 블로그 게시글을 읽고 궁금한 사항이 있으신 분들은 jaewookkim533@yahoo.com로 보내주시면 감사하겠습니다.

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

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

https://classmethod.kr/board/library

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

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.