아키텍처 개요

이벤트 흐름 (단일 리전 기준)

발신 계정(B~E) EC2 생성
  → CloudTrail (RunInstances 감지)
    → 발신 계정 EventBridge Rule
      → A 계정 default Event Bus (Cross-account PutEvents)
        → A 계정 EventBridge Rule (이벤트 매칭)
          → SNS Topic
            → SMS 알림

StackSet 배포 구조 (다중 리전)

각 발신 계정은 자기 계정 내 모든 리전에 EventBridge Rule을 배포하기 위해 StackSet을 사용합니다.
이 StackSet은 크로스 계정 배포가 아닌, 같은 계정 내 다중 리전 배포(Self-managed) 방식입니다.

발신 계정(B) StackSet
  → us-east-1      : EventBridge Rule + IAM Role 배포
  → ap-northeast-2 : EventBridge Rule + IAM Role 배포
  → eu-west-1      : EventBridge Rule + IAM Role 배포
  → (모든 대상 리전...)

발신 계정(C) StackSet → (동일 구조)
발신 계정(D) StackSet → (동일 구조)
...

계정 정보

역할계정 ID설명
A (중앙/수신)<A_ACCOUNT_ID>모든 이벤트를 수신하는 계정
B (발신)<B_ACCOUNT_ID>EC2 생성을 감지하는 하위 계정
C (발신)<C_ACCOUNT_ID>하위 계정
D (발신)<D_ACCOUNT_ID>하위 계정
E (발신)<E_ACCOUNT_ID>하위 계정

계정별 구성 요약

구성 요소A 계정 (수신)B~E 계정 (발신)
Event Bus 리소스 정책
EventBridge Rule (수신)
SNS Topic + 구독
입력 변환기
StackSet용 IAM Role 2개✅ (각 계정마다)
StackSet 배포✅ (각 계정마다)
CloudTrail Trail✅ (각 계정마다)

1단계: A 계정 (수신) — Event Bus 리소스 정책 설정

경로: A 계정 → Amazon EventBridge → 이벤트 버스 → default → 편집 → 리소스 기반 정책

발신 계정들이 A 계정의 Event Bus에 이벤트를 보낼 수 있도록 허용합니다.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowCrossAccountEvents",
    "Effect": "Allow",
    "Principal": {
      "AWS": [
        "arn:aws:iam::<B_ACCOUNT_ID>:root",
        "arn:aws:iam::<C_ACCOUNT_ID>:root",
        "arn:aws:iam::<D_ACCOUNT_ID>:root",
        "arn:aws:iam::<E_ACCOUNT_ID>:root"
      ]
    },
    "Action": "events:PutEvents",
    "Resource": "arn:aws:events:us-east-1:<A_ACCOUNT_ID>:event-bus/default"
  }]
}

새 발신 계정을 추가할 때는 Principal.AWS 배열에 해당 계정의 ARN을 추가합니다.


2단계: 각 발신 계정(B~E) — StackSet용 IAM Role 및 정책 생성

이 단계는 모든 발신 계정(B, C, D, E)에서 각각 수행해야 합니다.
각 발신 계정이 자기 계정 내 모든 리전에 EventBridge Rule을 StackSet으로 배포하기 위한 IAM 구성입니다.

2-1. 필요한 IAM Role

Role 이름신뢰 엔터티연결 정책용도설명
AWSCloudFormationStackSetAdministrationRoleAWS 서비스 (cloudformation.amazonaws.com)StackSetAdminPolicyStackSet 관리용CloudFormation 서비스가 Assume하여 StackSet 작업을 시작
AWSCloudFormationStackSetExecutionRoleAWS 계정 (자기 자신의 계정 ID)StackSetExecutionPolicyStackSet 실행용AdministrationRole이 Assume하여 각 리전에 스택을 배포

StackSet 내부 동작 흐름

CloudFormation 서비스
  → AdministrationRole Assume (신뢰: cloudformation.amazonaws.com)
    → ExecutionRole Assume (신뢰: 자기 계정 ID)
      → 각 리전에 EventBridge Rule + IAM Role 생성

2-2. AdministrationRole 생성

경로: IAM 콘솔 → 역할 → 역할 생성 → AWS 서비스 선택 → CloudFormation

신뢰 정책 (Trust Policy)

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Service": "cloudformation.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}

연결할 정책 — StackSetAdminPolicy

경로: IAM 콘솔 → 정책 → 정책 생성 → JSON 탭

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AssumeExecutionRole",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"
    }
  ]
}

이 정책은 동일 계정 내 ExecutionRole을 Assume하기 위한 것입니다. Resource*는 계정 ID 부분이며, 같은 계정 내에서 동작합니다.

2-3. ExecutionRole 생성

경로: IAM 콘솔 → 역할 → 역할 생성 → AWS 계정 선택 → 이 계정 (자기 자신의 계정 ID)

신뢰 정책 (Trust Policy)

⚠️ 아래의 <자기_계정_ID>를 현재 작업 중인 발신 계정의 실제 계정 ID로 교체하세요.
예: B 계정에서 작업 중이라면 <B_ACCOUNT_ID>, C 계정이라면 <C_ACCOUNT_ID>

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::<자기_계정_ID>:root"
    },
    "Action": "sts:AssumeRole"
  }]
}

연결할 정책 — StackSetExecutionPolicy

⚠️ 아래 정책의 모든 <자기_계정_ID>를 현재 작업 중인 발신 계정의 실제 계정 ID로 교체하세요.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CloudFormationManagement",
      "Effect": "Allow",
      "Action": [
        "cloudformation:CreateStack",
        "cloudformation:UpdateStack",
        "cloudformation:DeleteStack",
        "cloudformation:DescribeStacks",
        "cloudformation:DescribeStackEvents",
        "cloudformation:GetTemplate",
        "cloudformation:ListStackResources"
      ],
      "Resource": "arn:aws:cloudformation:*:<자기_계정_ID>:stack/StackSet-*"
    },
    {
      "Sid": "EventBridgeRuleManagement",
      "Effect": "Allow",
      "Action": [
        "events:PutRule",
        "events:DeleteRule",
        "events:DescribeRule",
        "events:PutTargets",
        "events:RemoveTargets",
        "events:EnableRule",
        "events:DisableRule",
        "events:ListTargetsByRule"
      ],
      "Resource": "arn:aws:events:*:<자기_계정_ID>:rule/ec2-creation-alert-rule"
    },
    {
      "Sid": "IAMRoleManagement",
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:GetRole",
        "iam:PutRolePolicy",
        "iam:DeleteRolePolicy",
        "iam:GetRolePolicy",
        "iam:PassRole",
        "iam:TagRole",
        "iam:UntagRole"
      ],
      "Resource": "arn:aws:iam::<자기_계정_ID>:role/EventBridge-CrossAccount-*"
    },
    {
      "Sid": "SNSNotification",
      "Effect": "Allow",
      "Action": [
        "sns:Publish"
      ],
      "Resource": "arn:aws:sns:*:<자기_계정_ID>:StackSet-*"
    }
  ]
}
Sid용도
CloudFormationManagementStackSet이 배포하는 개별 스택의 생성/수정/삭제/조회
EventBridgeRuleManagementEC2 생성 알림용 EventBridge 규칙 관리
IAMRoleManagementEventBridge 크로스 계정 역할 생성/삭제 및 PassRole
SNSNotificationStackSet 관련 SNS 토픽에 알림 발행

3단계: 각 발신 계정(B~E) — CloudFormation StackSet 배포

이 단계는 모든 발신 계정(B, C, D, E)에서 각각 수행해야 합니다.
StackSet은 같은 계정 내 여러 리전에 동일한 리소스를 한 번에 배포하기 위해 사용합니다.

StackSet 이름 추천 : ec2-creation-alert-stackset

아래 CloudFormation 템플릿을 StackSet으로 배포합니다.

파일명: ec2-alert-rule.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: >-
  EC2 instance creation alert - forward to central account

Resources:
  EC2CreationAlertRule:
    Type: AWS::Events::Rule
    Properties:
      Name: ec2-creation-alert-rule
      Description: >-
        Detect EC2 RunInstances and forward to central account
      State: ENABLED
      EventPattern:
        source:
          - aws.ec2
        detail-type:
          - AWS API Call via CloudTrail
        detail:
          eventSource:
            - ec2.amazonaws.com
          eventName:
            - RunInstances
      Targets:
        - Id: CentralAccountEventBus
          Arn: arn:aws:events:us-east-1:<A_ACCOUNT_ID>:event-bus/default
          RoleArn: !GetAtt EventBridgeRole.Arn

  EventBridgeRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub 'EventBridge-CrossAccount-${AWS::Region}'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: PutEventsPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: events:PutEvents
                Resource: arn:aws:events:us-east-1:<A_ACCOUNT_ID>:event-bus/default

이 템플릿은 두 가지 리소스를 생성합니다:
1. EventBridge Rule — EC2 RunInstances API 호출을 감지하여 A 계정으로 전달
2. IAM Role — EventBridge가 A 계정의 Event Bus에 PutEvents를 실행할 수 있는 권한


4단계: 각 발신 계정(B~E) — CloudTrail 추적 생성 (필수!)

이 단계를 빠뜨리면 EventBridge Rule이 트리거되지 않습니다.
이 단계는 모든 발신 계정(B, C, D, E)에서 각각 수행해야 합니다. (이미 Trail이 있는 계정은 생략)

AWS API Call via CloudTrail 이벤트가 EventBridge로 전달되려면 활성화된 CloudTrail Trail이 반드시 필요합니다.

경로: 각 발신 계정 → CloudTrail → 추적 → 추적 생성

항목설정 값
추적 이름management-events-trail
다중 리전예 (콘솔 생성 시 자동)
S3 버킷새 버킷 생성 (기본값)
SSE-KMS 암호화비활성화 (비용 절감, S3 기본 SSE-S3 암호화 적용됨)
로그 파일 검증활성화
CloudWatch Logs비활성화 (불필요)
이벤트 유형관리 이벤트
API 활동읽기 + 쓰기

비용 참고

  • 첫 번째 관리 이벤트 Trail은 무료
  • SSE-KMS 비활성화로 KMS 비용($1/월) 절감
  • SSE-KMS를 끄더라도 S3 기본 암호화(SSE-S3)가 적용되므로 보안상 문제 없음

5단계: A 계정 (수신) — EventBridge Rule 생성

경로: A 계정 → Amazon EventBridge → 규칙 → 규칙 생성

항목
규칙 이름ec2-creation-alert-rule
이벤트 버스default
상태활성화

이벤트 패턴

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

대상 설정

항목
대상 유형SNS 주제
대상ec2-instance-creation-alert

6단계: A 계정 (수신) — 입력 변환기 설정 (SMS 분할 방지)

이 설정이 없으면 CloudTrail 원본 JSON(수천 자)이 그대로 SMS로 전송되어 10건 이상 분할됩니다.

경로: A 계정 → EventBridge → ec2-creation-alert-rule → 대상 편집 → 입력 변환 → 입력 변환기

입력 경로

{"account":"$.account","region":"$.region","instanceId":"$.detail.responseElements.instancesSet.items[0].instanceId","time":"$.time"}

입력 템플릿

"EC2 Created: account=<account>, region=<region>, instance=<instanceId>, time=<time>"

SMS는 영문 160자 / 한글 70자 제한이 있으므로, 메시지를 짧게 유지해야 1건으로 수신됩니다. 영문 템플릿을 권장합니다.


7단계: A 계정 (수신) — SNS Topic 및 구독 설정

경로: A 계정 → SNS → 주제 → ec2-instance-creation-alert

SNS 구독 추가

프로토콜엔드포인트비고
SMS전화번호 (예: +8201012345678)확인 불필요
Email이메일 주소확인 메일 클릭 필요
profile
멋지게 기록하자

0개의 댓글