IAM 사용자 생성을 감지하고, MFA 설정 여부를 통지하는 구성을 만들어 봤습니다.

IAM 사용자 생성을 감지하고, MFA 설정 여부를 통지하는 구성을 만들어 봤습니다.

IAM 사용자 생성을 감지하고, MFA 설정 여부를 통지하는 구성을 만들어 봤습니다.
Clock Icon2025.06.18

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 IAM 사용자 생성을 감지하고, MFA 설정 여부를 통지하는 구성을 만들어 봤습니다.

이번 블로그에서는 IAM 정책&역할, Lambda, EventBridge를 활용합니다. 또 한, IAM 사용자 생성을 감지하기 위해 EventBridge 규칙에서 [CreateUser]를 설정하여 이벤트를 감지하고 트리거를 하는데, [CreateUser]는 버지니아 리전(us-east-1)에서 발생하기 때문에 Lambda와 EventBridge 규칙은 버지니아 리전(us-east-1)에 생성해야 합니다.

IAM 정책 & 역할 생성

먼저 Lambda 함수에 사용할 IAM 정책과 역할을 생성합시다.

Lambda 함수에서 사용자 MFA 설정을 확인하기 위해 [iam:ListMFADevices] 권한을 할당합니다. 나머지는 이메일 통지를 위한 권한과 CloudWatch에 로그를 남기기 위한 권한입니다.

[arn:aws:sns:us-east-1:xxxxxxxxxx]에는 SNS 토픽 Arn을 입력합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": "arn:aws:sns:us-east-1:xxxxxxxxxx"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}

Lambda 함수 코드 작성

IAM 정책과 역할을 생성했다면 Lambda 함수 코드를 작성합시다.

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

이벤트가 트리거 되면, 생성한 Lambda 함수가 실행되며, MFA 설정 여부를 확인하고 이메일을 전송합니다. MFA 설정은 IAM 사용자 생성 이후에 설정할 수 있는 부분이기 때문에 기본적으로 IAM 사용자가 생성된다면 이메일이 전송된다고 보면 됩니다.

[arn:aws:sns:us-east-1:xxxxxxxxxx]에는 SNS 토픽 Arn을 입력합니다.

import json
import boto3

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

SNS_TOPIC_ARN = 'arn:aws:sns:us-east-1:xxxxxxxxxx'  # 실제 ARN으로 교체

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

    try:
        user_name = event['detail']['requestParameters']['userName']
    except KeyError:
        print("userName not found in event")
        return {
            'statusCode': 400,
            'body': 'No userName found in event'
        }

    # MFA 장치 확인
    response = iam.list_mfa_devices(UserName=user_name)
    mfa_devices = response['MFADevices']
    has_mfa = len(mfa_devices) > 0

    # 알림 메시지 포맷
    if not has_mfa:
        subject = f"[ALERT] IAM 사용자 '{user_name}' MFA 미설정!"
        message = (
            f"🔐 보안 경고: IAM 사용자 '{user_name}'이(가) 생성되었으나 MFA가 설정되지 않았습니다.\n\n"
            "⚠️ 즉시 MFA 설정을 확인하고 적용해 주세요.\n"
            f"- 사용자명: {user_name}\n"
            f"- 이벤트 출처: {event['detail']['eventSource']}\n"
            f"- 생성자: {event['detail'].get('userIdentity', {}).get('arn', 'N/A')}\n"
            f"- 이벤트 시간: {event['detail'].get('eventTime', 'N/A')}\n"
        )

        sns.publish(
            TopicArn=SNS_TOPIC_ARN,
            Subject=subject,
            Message=message
        )
        print(f"SNS 알림 전송 완료: {subject}")
    else:
        print(f"사용자 {user_name} 은(는) MFA가 설정되어 있음.")

    return {
        'statusCode': 200,
        'body': f'User {user_name} processed. MFA set: {has_mfa}'
    }

EventBridge 규칙 생성

EventBridge 규칙은 CloudTrail에서 [CreateUser] 이벤트가 발생했을 때 트리거합니다. 대상은 조금 전 생성한 Lambda 함수입니다.

{
  "source": ["aws.iam"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["iam.amazonaws.com"],
    "eventName": ["CreateUser"]
  }
}

결과 확인

테스트용으로 [test-iam-user] 사용자를 생성합니다.

jw-iamlambt-1

조금 기다려보면, 이메일로 생성한 IAM 사용자에 대한 정보(생성한 사용자와 생성 시간 등)이 전송됩니다.

생성 시간은 UTC로 설정되어 있는 것 같은데 상황에 맞게 적절하게 시간대를 변경해 주면 될 것 같습니다.

jw-iamlambt-2

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

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

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

https://classmethod.kr/board/library

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

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.