1. 프로젝트 개요
클라우드 보안 운영에서 가장 기본이자 중요한 작업 중 하나는 보안 관련 이벤트를 실시간으로 감지하는 것이다.
특히 IAM 계정 생성, 보안 그룹 변경, CloudTrail 비활성화, Config Rule 위반 같은 이벤트는 즉시 대응하지 못하면 차후 보안 사고로 이어질 가능성이 높기 때문에 자동화된 보안 알림 파이프라인이 필수적이다.
이번 글에서는 CloudFormation으로 완전 자동화된 AWS 보안 이벤트 실시간 알림 스택을 구성한 과정을 정리했다.
구조는 단순하면서도 실무에서 바로 활용 가능하도록, 그리고 아래의 문제를 해결하는 데 초점을 두었다.
- CloudWatch Logs 남용으로 인한 구성 복잡도 증가
- Amazon SNS 알림 메시지 가독성 부족
- EventBridge Rule 난립 문제
- AWS Config 결과 수집의 부재
- 향후 보안 서비스(Security Hub, GuardDuty) 확장을 고려한 구조 필요
2. 개선 목표 및 설계 방향
2-1. 개선된 아키텍처 구성도

프로젝트 아키텍처는 다음과 같이 실행된다.
CloudTrail (멀티 리전 Trail) ┐
├─ EventBridge (4개 Rule로 분류)
AWS Config (Compliance Events) ┘
↓
Lambda (FormatMessageFunction)
↓
SNS Topic
↓
Email Alert
이 구조의 핵심은 중간 구성요소 최소화와 단일 Lambda를 통한 메시지 정규화다. 모든 이벤트는 EventBridge에서 필터링된 뒤 Lambda에 전달되며, Lambda는 한국어 메시지로 변환 후 SNS로 발행한다.
3. CloudFormation 템플릿 구성 및 실행 방법
3-1. 주요 리소스 요약
| 리소스 유형 | 이름 또는 설명 |
| S3 bucket | CloudTrail 로그 저장용, AES256 암호화 |
| CloudTrail | 모든 AWS API 활동 기록 |
| Config | 규정 위반(Compliance) 지속 감시 |
| EventBridge Rule 4종 | 보안 관점별 이벤트 필터링 |
| Lambda Function | 이벤트 메시지 형식 지정 및 SNS 발행 |
| CloudWatch Logs | Lambda 로그 저장 |
| SNS Topic | 이메일을 통한 최종 알림 전달 |
| Rule 이름 | 포함된 서비스 | 목적 |
| HighRiskSecurityEvents | IAM | 계정/권한 관련 고위험 이벤트 실시간 감지 |
| InfraProvisioningEvents | EC2, S3, RDS, VPC | 인프라 변경/프로비저닝 추적 |
| CloudTrailChanges | CloudTrail | 감사 로그 비활성화/변조 시도 탐지 |
| ConfigComplianceChanges | Config | 정책 위반(조직 규정 / Config Rule) 감지 |
3-2. 템플릿 다운로드
CloudFormation 배포 방법 (콘솔 기준)
1. AWS CloudFormation 콘솔 접속

2. "Create stack" > "With new resources (standard)" 선택
3. 위 템플릿 파일 업로드
- 파라미터 입력:
- DeploymentTimeStamp : AWS 계정 ID를 대신할 고유한 stack 이름 키
- EmailAddress : 알림 받을 이메일 주소 입력 (예: security@example.com)

4. "Next" → "Next" → 권한 경고 수락 후 "Create stack"
SNS 구독 이메일이 도착하면, 반드시 확인(Confirm subscription) 해야 이메일 수신 가능하다.
5. 결과 확인

5. EventBridge Rule 점검 시나리오
5-1. HighRiskSecurityEvents 시나리오
IAM 고위험 이벤트 탐지 테스트
Resources:
HighRiskSecurityEventsRule:
Type: AWS::Events::Rule
DependsOn: FormatMessageFunction
Properties:
Name: !Sub "HighRiskSecurityEvents-${DeploymentTimestamp}"
EventPattern:
source:
- aws.iam
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- iam.amazonaws.com
eventName:
- CreateUser
- DeleteUser
- AttachUserPolicy
- DetachUserPolicy
- CreateAccessKey
- DeleteAccessKey
- UpdateLoginProfile
- CreateLoginProfile
- DeleteLoginProfile
- PutUserPolicy
- DeleteUserPolicy
Targets:
- Arn: !GetAtt FormatMessageFunction.Arn
Id: "HighRiskTarget"
목적
IAM 사용자 생성/삭제, 정책 부착 등 고위험 이벤트가 EventBridge → Lambda → SNS로 정상 전달되는지 확인한다.
사전 준비
- IAM 작업 수행 권한 (IAMFullAccess 또는 필요한 개별 권한)
- SNS 구독 이메일 "확인 완료(Confirmed)" 상태
점검 시나리오
가장 영향이 적은 임시 사용자 생성 후 즉시 삭제 시나리오를 사용한다.
5-1-1. IAM 사용자 생성
aws iam create-user --user-name TestEventUser
5-1-2. 이벤트 발생 대기 (1~3초)
5-1-3. IAM 사용자 삭제
aws iam delete-user --user-name TestEventUser
결과

문제 발생 시 점검 항목
- CloudTrail → EventBridge 관리형 이벤트 활성화 여부
- Rule의 eventPattern에 IAM 이벤트가 포함되어 있는지
- Lambda Invoke Permission 누락 여부
- Lambda CloudWatch Logs에서 오류 확인
- SNS Topic ARN 환경변수 오타 여부
5-2. InfraProvisioningEventsRule 시나리오
EC2, SG, S3, RDS, VPC provisioning 이벤트 테스트
Resources:
InfraProvisioningEventsRule:
Type: AWS::Events::Rule
DependsOn: FormatMessageFunction
Properties:
Name: !Sub "InfraProvisioningEvents-${DeploymentTimestamp}"
EventPattern:
source:
- aws.ec2
- aws.s3
- aws.rds
- aws.vpc
detail-type:
- AWS API Call via CloudTrail
detail:
eventName:
- RunInstances
- TerminateInstances
- AuthorizeSecurityGroupIngress
- AuthorizeSecurityGroupEgress
- CreateSecurityGroup
- DeleteSecurityGroup
- CreateBucket
- DeleteBucket
- PutBucketPolicy
- DeleteBucketPolicy
- PutBucketAcl
- PutObjectAcl
- CreateDBInstance
- DeleteDBInstance
- CreateVpc
- DeleteVpc
Targets:
- Arn: !GetAtt FormatMessageFunction.Arn
Id: "InfraProvisioningTarget"
목적
주요 인프라 변경 이벤트가 정상적으로 Rule에 의해 필터링되는지 확인한다.
사전 준비
- EC2:SecurityGroup 수정 권한
- 테스트용 VPC (기본 VPC 사용 가능)
점검 시나리오
가장 영향이 적고 빠르게 테스트 가능한 API는 Security Group Ingress Rule 추가 후 즉시 삭제이다.
5-2-1. SG 식별
aws ec2 describe-security-groups \
--group-names default \
--query "SecurityGroups[0].GroupId" \
--output text
- GroupedId를 변수로 저장:
SG_ID=sg-xxxxxxx
5-2-2. Ingress Rule 추가
aws ec2 authorize-security-group-ingress \
--group-id $SG_ID \
--protocol tcp \
--port 9999 \
--cidr 1.1.1.1/32
5-2-3. 즉시 Ingress 삭제
aws iam delete-user --user-name TestEventUser
결과

문제 발생 시 점검 항목
- EventBridge Rule의 eventPattern에 EC2/SG 이벤트가 포함되어 있는지
- CloudTrail 로그 지연 여부
- Lambda 오류 여부
- SNS Publish 권한 체크
5-3. CloudTrailChangesRule 시나리오
감사 로그 비활성화/수정 탐지 테스트
Resources:
CloudTrailChangesRule:
Type: AWS::Events::Rule
DependsOn: FormatMessageFunction
Properties:
Name: !Sub "CloudTrailChanges-${DeploymentTimestamp}"
EventPattern:
source:
- aws.cloudtrail
detail-type:
- AWS API Call via CloudTrail
detail:
eventName:
- StopLogging
- DeleteTrail
- UpdateTrail
Targets:
- Arn: !GetAtt FormatMessageFunction.Arn
Id: "CloudTrailChangesTarget"
목적
CloudTrail 설정 변경 시도가 알림으로 정확히 전달되는지 검증한다.
사전 주의
- 이 규칙은 "StopLogging", "UpdateTrail", "DeleteTrail" 이벤트를 감지한다.
- 실제 Trail을 중단시키면 위험하므로, Trail 설정만 읽기/쓰기 가능한 무해한 속성 변경(UpdateTrail)만 테스트한다.
점검 시나리오
5-3-1. Trail 이름 확인 :
aws cloudtrail list-trails
- TrailName 변수 설정 :
TRAIL_NAME=SecurityTrail-20250101-120000 # 실제 배포된 이름 사용
5-3-2. UpdateTrail 실행 (무해한 속성 업데이트)
aws cloudtrail update-trail \
--name $TRAIL_NAME \
--is-multi-region-trail
CloudTrail은 동일 값이어도 UpdateTrail 이벤트가 발생한다.
결과

문제 발생 시 점검 항목
- Rule eventPattern에 "aws.cloudtrail" / UpdateTrail 포함 여부
- CloudTrail이 EventBridge로 관리형 이벤트를 전송 중인지
- Lambda 로그에서 eventType 파싱 오류 여부
5-4. ConfigComplianceChangesRule 시나리오
Config Rule NON_COMPLIANT 이벤트 테스트
Resources:
ConfigComplianceChangesRule:
Type: AWS::Events::Rule
DependsOn: FormatMessageFunction
Properties:
Name: !Sub "ConfigComplianceChanges-${DeploymentTimestamp}"
EventPattern:
source:
- aws.config
detail-type:
- Config Rules Compliance Change
detail:
newEvaluationResult:
complianceType:
- NON_COMPLIANT
Targets:
- Arn: !GetAtt FormatMessageFunction.Arn
Id: "ConfigComplianceTarget"
목적
AWS Config Rule의 평가 결과가 "NON_COMPLIANT"일 때 EventBridge → Lambda → SNS까지 정상 흐름을 검증한다.
사전 주의
- 이미 활성화된 AWS Config Recorder 필수
- AWS Config recorder 생성 또한 CloudFormation template을 통한 생성 대상이었다.
- 하지만 AWS Config recorder는 AWS 계정 당 한 개만 활성화 가능하고 이전 프로젝트에서 한번 생성한 후로는 삭제 및 재생성을 시도해도 문제가 발생하여 부득이하게 이번 CloudFormation을 통한 생성 로직에서 배제되었다.
- 해당 EventBridge rule 결과 확인을 원한다면 사용자가 직접 Config 생성 필요.
- 최소 1개의 AWS Managed Rule이 활성화되어야 한다.
- ex. REQUIRED_TAGS, IAM_PASSWORD_POLICY 등
- 아래 시나리오는 `s3-bucket-versioning-enabled` AWS managed rule을 활성화했다.
점검 시나리오
5-4-1. AWS Config rule에 's3-bucket-versioning-enabled' 규칙 활성화

5-4-2. S3 버킷 생성 (버전 관리 미활성 상태로 생성 - 규칙 위반)
BUCKET_NAME="test-versioning-bucket-$(date +%s)"
aws s3api create-bucket \
--bucket $BUCKET_NAME
이 동작은 Config Rule에 따라 NON_COMPLIANT가 발생한다.
5-4-3. AWS Config에서 리소스 평가 강제 실행
aws configservice start-config-rules-evaluation \
--config-rule-names s3-bucket-versioning-enabled
결과


- 기존의 `AWS API Call via CloudTrail` 로그 형식과 다른 이벤트 출력 결과(`Config Rules Compliance Change`) 확인
- 해당 이벤트를 위한 별도의 Lambda Formatting Function 생성 필요
문제 발생 시 점검 항목
- AWS Config의 Recorder / Delivery Channel 정상 동작 여부 확인
- 테스트한 Config Rule이 실제로 NON_COMPLIANT를 발생시키는지
- EventBridge Rule의 eventPattern JSONPath 불일치 여부
- Lambda의 event.detail.newEvaluationResult 파싱 오류
6. 스택 구현 주안점
6-1. Lambda Formatting Logic
단순한 이벤트 전달을 넘어서, 보안 이벤트를 사람이 이해 가능한 형식으로 재가공하는 것은 실무 자동화의 필수 요소다. Lambda 함수는 event["detail"] 내 다양한 키를 안전하게 파싱하고, 누락되거나 오류가 발생할 수 있는 값을 default 처리하며, 메시지를 통일된 형식으로 구성한다. 이 구조적 formatting을 통해 다음과 같은 효과를 얻었다.
- 이메일 제목, 본문, Slack 전송 메시지 등 사람 중심 알림 구조 확립
- Unknown 값 방지를 위한 이벤트 구조 디버깅 로그 삽입
- "Root 계정 사용 감지", "S3 정책 변경", "Config 비준수" 등 이벤트 성격을 구분하는 가독성 높은 메시지 형식 제공
6-2. CloudTrail + S3 설정 - 보안 기본기 강화
보안 이벤트 감지의 출발점은 결국 CloudTrail이 얼마나 신뢰할 수 있게 구성되어 있는가에 달려있다. 이 프로젝트에서는 CloudTrail이 S3 버킷에 로그를 저장하고, 동시에 EventBridge로 직접 이벤트를 전송하도록 구성했다.
CloudTrail + S3에서 중요한 보안 구성은 아래와 같다.
6-2-1. CloudTrail 구성 보안
isMultiRegionTrail: true
includeGlobalServiceEvents: true
enableLogFileValidation: true
- 멀티 리전 CloudTrail 활성화 (isMultiRegionTrail)
- 공격자가 다른 리전(us-west-2 등)에서 API 호출을 시도하더라도, 해당 리전에 Trail이 존재하지 않으면 로그가 저장되지 않는다.
- 따라서 이 설정은 단일 Trail이 모든 리전의 활동을 추적할 수 있도록 보장하며, Shadow Trail(보이지 않는 Trail 회피) 우회 공격 방지를 수행한다.
- 글로벌 서비스 이벤트 로깅 활성화 (includeGlobalServiceEvents)
- IAM, STS 같은 글로벌 서비스는 리전과 무관하게 동작한다.
- 이 설정은 이러한 글로벌 API 호출도 CloudTrail에 기록하도록 동작한다.
- 로그 파일 무결성 검증 (enableLogFileValidation)
- S3에 저장된 로그 파일이 변조되지 않았는지 확인 가능한 해시 체계를 자동 생성한다.
- Compliance / Forensic 목적에서 법적 증거 신뢰성 확보에도 기여할 수 있다.
6-2-2. S3 버킷 보안
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
- SSE-S3 (Server-Side Encryption - S3 Managed Keys)
- CloudTrail 로그가 S3에 저장될 때, 자동으로 서버 측 암호화가 적용된다.
- 해당 설정은 저장 중 데이터 보호를 위한 기본 방어선이며, 별도의 KMS 키 관리 없이도 Compliance 요건 충족이 가능하다.
7. 마무리 및 향후 확장
이번 프로젝트는 단순한 보안 이벤트 알림을 넘어서, 결과를 의미 있는 형태로 전달하는 보안망을 구축하는 것을 목표로 삼았다. 아래는 이 스택이 제공하는 기능과 개선사항들이다.
실현된 구성 요소 및 효과 요약
- CloudTrail 용 CloudWatch Logs 제거 → 구성 복잡도 감소
- EventBridge Rule 통합 → 운영 지점(Single Point of Failure) 축소
- Lambda로 메시지 formatting → 알림 가독성 극적 향상
- Config Rule 위반까지 통합 → 조직 정책 준수 모니터링 강화
- 멀티 리전 CloudTrail 활성화 → 리전 우회 공격 대응
결과적으로, 단순 "알림 기반 대응"을 뛰어넘어, 보안 거버넌스 자동화, 정책 위반 탐지, 알림의 정규화, 리전 단위 커버리지 확대까지 포함하며, 선제적(proactive) 보안 운영 체계로 확장 가능한 기반이 되는 구조였다.
8. 향후 확장 방향
- Security Hub 통합
- CIS, PCI, AWS 보안 모범 사례 등 평가 결과를 SNS 알림에 포함
- 컴플라이언트 관점에서의 자동화된 모니터링 구현
- GuardDuty 이벤트 연계
- Credential exfiltration, 포트 스캐닝, 내부 lateral movement 등 이상 행위 탐지
- 탐지 결과를 별도 SNS로 라우팅하거나 SIEM 연계 가능
- Lambda 실패 추적을 위한 DeadLetter Queue 설정
- 메시지 전송 실패나 formatting 오류 발생 시 DLQ로 전송
- 실패 이벤트 기반 디버깅 및 재처리 자동화 기반 확보
- 부서별 정책 준수 검사 자동화 (Custom Config Rule + Tag 기반 필터링)
- 태그 기반 예외 처리 로직을 도입하여 일반 규칙과 부서별 특수 규칙 구분
- 관리 부서별 책임 영역 분리 및 정책 유연성 확보
Powered By. ChatGPT & Claude
'Cloud Security' 카테고리의 다른 글
| [Cloud Security] 1주차. Terraform으로 AWS 인프라 구성하기 (0) | 2026.01.22 |
|---|---|
| [CloudSecurity] SecurityHub와 GuardDuty 기반 AWS 보안 알림 스택 확장 (0) | 2025.12.05 |
| [Cloud Security] 쿠버네티스 보안 및 CI/CD 환경 분석 - CD 구현 (0) | 2025.06.12 |
| [Cloud Security] 쿠버네티스 보안 및 CI/CD 환경 분석 - CI 구현 (0) | 2025.06.10 |
| [Cloud Security] 9주차. 쿠버네티스 보안 및 CI/CD 환경 분석 (0) | 2025.06.08 |