Chapter 12 - 강사용 답안

CloudTrail 감사 로깅

"누가, 언제, 무엇을 했는지 모든 기록을 남기자"

강사 전용 문서

이 문서는 강사용 답안입니다. 학생에게 공유하지 마세요. 각 단계의 정확한 답과 해설, 트러블슈팅 가이드가 포함되어 있습니다.

Step 1: CloudTrail 이벤트 기록 확인

답안

웹 콘솔 방법

  1. AWS 콘솔에서 CloudTrail 서비스로 이동
  2. 좌측 메뉴에서 이벤트 기록(Event history) 클릭
  3. 기본적으로 최근 이벤트가 시간 역순으로 표시됨
  4. 필터 드롭다운을 "이벤트 이름"으로 변경
  5. RunInstances 입력 후 Enter - EC2 인스턴스 생성 기록 확인
  6. 검색된 이벤트 행을 클릭하면 상세 JSON 이벤트 레코드를 확인 가능
  7. JSON에서 다음 항목을 확인:
    • userIdentity.userName - 작업을 수행한 IAM 사용자
    • eventTime - 작업 수행 시간 (UTC)
    • sourceIPAddress - 요청을 보낸 IP 주소
    • requestParameters - 요청에 사용된 파라미터

같은 방법으로 다른 이벤트도 검색해 봅니다:

  • CreateBucket - S3 버킷 생성 이벤트
  • CreateRole - IAM 역할 생성 이벤트
  • CreateDBInstance - RDS 인스턴스 생성 이벤트

AWS CLI 방법

bash
# EC2 인스턴스 생성(RunInstances) 이벤트 조회
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=RunInstances \
  --max-results 5 \
  --region ap-northeast-2

# S3 버킷 생성(CreateBucket) 이벤트 조회
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateBucket \
  --max-results 5 \
  --region ap-northeast-2

# IAM 역할 생성(CreateRole) 이벤트 조회
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateRole \
  --max-results 5 \
  --region ap-northeast-2

# 결과를 보기 좋게 포맷팅
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=RunInstances \
  --max-results 3 \
  --region ap-northeast-2 \
  --query "Events[].{Time:EventTime, Name:EventName, User:Username, Source:EventSource}" \
  --output table
해설: 이벤트 기록(Event history)의 특징
  • 무료: 추가 비용 없이 최근 90일간의 관리 이벤트를 조회할 수 있습니다
  • 자동 활성화: AWS 계정을 만들면 이벤트 기록이 자동으로 활성화됩니다. Trail을 생성하지 않아도 사용 가능합니다
  • 관리 이벤트만: 리소스 생성/변경/삭제 등 관리 작업만 기록됩니다. 데이터 이벤트(S3 GetObject 등)는 포함되지 않습니다
  • 90일 제한: 90일이 지난 이벤트는 자동 삭제됩니다. 장기 보관이 필요하면 Trail을 생성해야 합니다

Step 2: CloudTrail 추적(Trail) 생성

답안

웹 콘솔 방법

  1. AWS 콘솔에서 CloudTrail 서비스로 이동
  2. 좌측 메뉴에서 추적(Trails) 클릭
  3. 추적 생성(Create trail) 클릭
  4. 일반 세부 정보:
    • 추적 이름: ShopEasy-Trail
    • 스토리지 위치: 새 S3 버킷 생성 선택
    • 추적 로그 버킷 이름: shopeasy-cloudtrail-{ACCOUNT_ID}
    • 로그 파일 SSE-KMS 암호화: 활성화됨 (체크)
      • AWS KMS 고객 관리형 키: 새로 만들기 또는 기존 (기본 aws/s3 키 사용)
    • 로그 파일 검증: 활성화됨 (기본값 유지)
  5. 다음 클릭
  6. 이벤트 선택:
    • 이벤트 유형: 관리 이벤트 체크 (기본값)
    • 관리 이벤트 → API 활동: 읽기쓰기 모두 체크
  7. 다음 클릭
  8. 검토 화면에서 설정 확인 후 추적 생성 클릭
  9. 추적 상태가 로깅 중(Logging)인지 확인

AWS CLI 방법

bash
# 계정 ID 확인
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "Account ID: $ACCOUNT_ID"

# 1. CloudTrail 로그용 S3 버킷 생성
aws s3api create-bucket \
  --bucket shopeasy-cloudtrail-${ACCOUNT_ID} \
  --region ap-northeast-2 \
  --create-bucket-configuration LocationConstraint=ap-northeast-2

# 2. S3 버킷 정책 설정 (CloudTrail이 버킷에 로그를 쓸 수 있도록 허용)
cat > /tmp/cloudtrail-bucket-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AWSCloudTrailAclCheck",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::shopeasy-cloudtrail-${ACCOUNT_ID}"
    },
    {
      "Sid": "AWSCloudTrailWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::shopeasy-cloudtrail-${ACCOUNT_ID}/AWSLogs/${ACCOUNT_ID}/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}
EOF

aws s3api put-bucket-policy \
  --bucket shopeasy-cloudtrail-${ACCOUNT_ID} \
  --policy file:///tmp/cloudtrail-bucket-policy.json

# 3. CloudTrail 추적 생성
aws cloudtrail create-trail \
  --name ShopEasy-Trail \
  --s3-bucket-name shopeasy-cloudtrail-${ACCOUNT_ID} \
  --is-multi-region-trail \
  --region ap-northeast-2

# 4. 로깅 시작
aws cloudtrail start-logging \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 5. 추적 상태 확인
aws cloudtrail get-trail-status \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 6. 추적 설정 확인
aws cloudtrail describe-trails \
  --trail-name-list ShopEasy-Trail \
  --region ap-northeast-2
해설: CLI로 Trail을 생성할 때 버킷 정책이 필요한 이유

웹 콘솔에서 Trail을 생성하면 S3 버킷과 버킷 정책이 자동으로 설정됩니다. 하지만 CLI로 생성할 때는 다음 작업을 수동으로 해야 합니다:

  1. S3 버킷 생성: CloudTrail 로그를 저장할 버킷을 먼저 만들어야 합니다
  2. 버킷 정책 설정: CloudTrail 서비스가 버킷에 로그를 쓸 수 있도록 권한을 부여해야 합니다
  3. Trail 생성: 버킷 준비가 완료된 후에야 Trail을 생성할 수 있습니다
  4. 로깅 시작: Trail을 생성한 후 start-logging을 호출해야 실제로 로깅이 시작됩니다
해설: 버킷 정책 분석
Statement Action 설명
AWSCloudTrailAclCheck s3:GetBucketAcl CloudTrail이 버킷의 ACL을 확인하여 쓰기 권한이 있는지 검증
AWSCloudTrailWrite s3:PutObject CloudTrail이 로그 파일을 버킷에 저장. AWSLogs/{ACCOUNT_ID}/* 경로만 허용

보안 포인트: Conditions3:x-amz-acl: bucket-owner-full-control은 CloudTrail이 저장하는 로그 파일의 소유권이 버킷 소유자에게 있음을 보장합니다.

해설: 주요 Trail 옵션
옵션 설명 권장 설정
--is-multi-region-trail 모든 리전의 이벤트를 기록 활성화 (단일 리전만 사용해도 권장)
SSE-KMS 암호화 S3에 저장되는 로그를 암호화 활성화 (보안 Best Practice)
로그 파일 검증 로그가 변조되지 않았음을 확인하는 무결성 검증 활성화 (컴플라이언스 필수)
관리 이벤트 읽기/쓰기 읽기(Describe, List 등)와 쓰기(Create, Delete 등) 이벤트 모두 활성화

Step 3: 추적 로그 S3 버킷 확인

답안

웹 콘솔 방법

  1. AWS 콘솔 → S3 서비스로 이동
  2. shopeasy-cloudtrail-{ACCOUNT_ID} 버킷 클릭
  3. 폴더 구조를 순서대로 탐색:
    • AWSLogs/ 클릭
    • {ACCOUNT_ID}/ 클릭
    • CloudTrail/ 클릭
    • ap-northeast-2/ 클릭
    • 오늘 날짜 폴더 (YYYY/MM/DD/) 클릭
  4. .json.gz 확장자의 로그 파일이 있으면 성공
  5. 로그 파일을 다운로드하여 압축을 풀면 JSON 형태의 이벤트 기록을 확인할 수 있음
참고

Trail 생성 후 첫 번째 로그 파일이 S3에 도착하기까지 5~15분 소요됩니다. 파일이 보이지 않으면 잠시 기다린 후 새로고침하세요.

AWS CLI 방법

bash
# 계정 ID 확인
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# S3 버킷 내용 확인 (재귀적으로 첫 10개 파일)
aws s3 ls s3://shopeasy-cloudtrail-${ACCOUNT_ID}/ --recursive | head -10

# 특정 날짜의 로그 파일 확인 (오늘 날짜로 변경)
TODAY=$(date +%Y/%m/%d)
aws s3 ls s3://shopeasy-cloudtrail-${ACCOUNT_ID}/AWSLogs/${ACCOUNT_ID}/CloudTrail/ap-northeast-2/${TODAY}/

# 로그 파일 다운로드 및 내용 확인 (첫 번째 파일)
FIRST_LOG=$(aws s3 ls s3://shopeasy-cloudtrail-${ACCOUNT_ID}/ --recursive | head -1 | awk '{print $4}')
if [ -n "$FIRST_LOG" ]; then
  aws s3 cp s3://shopeasy-cloudtrail-${ACCOUNT_ID}/${FIRST_LOG} /tmp/cloudtrail-log.json.gz
  gunzip -f /tmp/cloudtrail-log.json.gz
  python3 -m json.tool /tmp/cloudtrail-log.json | head -50
fi
해설: CloudTrail 로그 파일 구조
text
shopeasy-cloudtrail-{ACCOUNT_ID}/
  AWSLogs/
    {ACCOUNT_ID}/
      CloudTrail/
        ap-northeast-2/          <-- 리전별 폴더
          2024/
            12/
              15/                 <-- 날짜별 폴더
                {ACCOUNT_ID}_CloudTrail_ap-northeast-2_20241215T0930Z_xxxxx.json.gz
                {ACCOUNT_ID}_CloudTrail_ap-northeast-2_20241215T0935Z_xxxxx.json.gz
                ...
  • 로그 파일은 리전별 → 연도별 → 월별 → 일별로 정리됩니다
  • 각 파일은 약 5분 단위로 생성되며, .json.gz (gzip 압축 JSON) 형식입니다
  • 파일 이름에 타임스탬프가 포함되어 있어 시간대별로 식별이 가능합니다
  • Multi-region Trail을 활성화하면 다른 리전의 로그도 함께 저장됩니다

Step 4: 특정 이벤트 검색

답안

웹 콘솔 방법

  1. AWS 콘솔 → CloudTrail이벤트 기록
  2. 필터 드롭다운에서 검색 기준 선택:
    • 이벤트 이름으로 검색: CreateBucket 입력 - S3 버킷 생성 이벤트 확인
    • 이벤트 이름으로 검색: CreateTrail 입력 - 방금 만든 Trail 생성 이벤트 확인
  3. 검색된 이벤트를 클릭하여 상세 JSON 확인
  4. JSON에서 다음 핵심 필드를 확인:
    • userIdentity → 누가 이 작업을 수행했는지
    • eventTime → 언제 수행했는지
    • sourceIPAddress → 어디서(어떤 IP에서) 수행했는지
    • eventName → 어떤 API를 호출했는지
    • requestParameters → 어떤 파라미터를 사용했는지
    • responseElements → 결과는 무엇인지

다른 필터도 시도해 봅니다:

  • 사용자 이름으로 검색: 본인의 IAM 사용자 이름 입력 → 해당 사용자의 모든 활동 조회
  • 리소스 유형으로 검색: AWS::S3::Bucket 입력 → S3 관련 모든 이벤트 조회

AWS CLI 방법

bash
# CreateBucket 이벤트 검색
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateBucket \
  --region ap-northeast-2

# CreateTrail 이벤트 검색 (방금 만든 Trail 생성 기록)
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateTrail \
  --region ap-northeast-2

# 특정 사용자의 활동 검색
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=admin \
  --max-results 10 \
  --region ap-northeast-2

# 결과를 보기 좋게 요약
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=admin \
  --max-results 10 \
  --region ap-northeast-2 \
  --query "Events[].{Time:EventTime, Event:EventName, Source:EventSource}" \
  --output table

# 시간 범위 지정 검색 (예: 오늘 하루)
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateTrail \
  --start-time $(date -u -d "today 00:00:00" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v0H -v0M -v0S +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --region ap-northeast-2
해설: lookup-events에서 사용 가능한 검색 기준
AttributeKey 설명 예시 값
EventName API 호출 이름으로 검색 RunInstances, CreateBucket
Username IAM 사용자 이름으로 검색 admin, developer
ResourceType 리소스 유형으로 검색 AWS::S3::Bucket, AWS::EC2::Instance
ResourceName 리소스 이름/ID로 검색 i-0abcdef1234567890
EventSource AWS 서비스로 검색 s3.amazonaws.com, ec2.amazonaws.com
ReadOnly 읽기 전용 여부로 검색 true (읽기), false (쓰기)
해설: 이벤트 JSON 주요 필드 상세
json
{
  "eventVersion": "1.08",
  "userIdentity": {
    "type": "IAMUser",
    "principalId": "AIDAEXAMPLE",
    "arn": "arn:aws:iam::123456789012:user/admin",
    "accountId": "123456789012",
    "userName": "admin"
  },
  "eventTime": "2024-12-15T09:30:00Z",
  "eventSource": "cloudtrail.amazonaws.com",
  "eventName": "CreateTrail",
  "awsRegion": "ap-northeast-2",
  "sourceIPAddress": "203.0.113.50",
  "userAgent": "aws-cli/2.x Python/3.x",
  "requestParameters": {
    "name": "ShopEasy-Trail",
    "s3BucketName": "shopeasy-cloudtrail-123456789012",
    "isMultiRegionTrail": true
  },
  "responseElements": {
    "name": "ShopEasy-Trail",
    "s3BucketName": "shopeasy-cloudtrail-123456789012",
    "trailARN": "arn:aws:cloudtrail:ap-northeast-2:123456789012:trail/ShopEasy-Trail"
  }
}

읽는 법: IAM 사용자 admin이 2024-12-15 09:30(UTC)에 IP 주소 203.0.113.50에서 AWS CLI를 사용하여 ShopEasy-Trail이라는 CloudTrail 추적을 생성했다.

트러블슈팅 가이드

자주 발생하는 문제와 해결 방법

Trail 생성 실패: "S3 bucket does not exist" 또는 "Insufficient S3 bucket policy"

원인: CLI로 Trail을 생성할 때 S3 버킷이 없거나 버킷 정책이 설정되지 않음

해결 방법:

  1. S3 버킷이 존재하는지 확인
  2. 버킷 정책에 CloudTrail 서비스의 s3:GetBucketAcls3:PutObject 권한이 있는지 확인
  3. 웹 콘솔에서 Trail을 생성하면 S3 버킷과 정책이 자동으로 설정되므로, CLI로 어려우면 콘솔 사용을 권장
bash
# 버킷 존재 확인
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws s3api head-bucket --bucket shopeasy-cloudtrail-${ACCOUNT_ID}

# 버킷 정책 확인
aws s3api get-bucket-policy \
  --bucket shopeasy-cloudtrail-${ACCOUNT_ID} \
  --output text | python3 -m json.tool

# 버킷이 없으면 생성
aws s3api create-bucket \
  --bucket shopeasy-cloudtrail-${ACCOUNT_ID} \
  --region ap-northeast-2 \
  --create-bucket-configuration LocationConstraint=ap-northeast-2
Trail이 로깅하지 않음: 상태가 "Logging: false"

원인: CLI로 Trail을 생성한 후 start-logging을 실행하지 않음

해결 방법:

bash
# 로깅 상태 확인
aws cloudtrail get-trail-status \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# IsLogging이 false이면 로깅 시작
aws cloudtrail start-logging \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 다시 상태 확인
aws cloudtrail get-trail-status \
  --name ShopEasy-Trail \
  --region ap-northeast-2 \
  --query "{IsLogging:IsLogging, LatestDeliveryTime:LatestDeliveryTime}"
참고

웹 콘솔에서 Trail을 생성하면 로깅이 자동으로 시작됩니다. CLI에서는 create-trail 후 반드시 start-logging을 실행해야 합니다.

S3 버킷에 로그 파일이 보이지 않음

원인: Trail 생성 직후이거나, 로깅이 시작되지 않았음

해결 방법:

  1. Trail 생성 후 첫 번째 로그 파일이 S3에 도착하기까지 5~15분 소요됩니다. 잠시 기다린 후 확인하세요
  2. Trail의 로깅 상태가 활성(Logging: true)인지 확인
  3. S3 버킷 이름이 Trail 설정과 일치하는지 확인
  4. 어떤 API 호출이라도 발생해야 로그가 생성됩니다 (콘솔에서 아무 서비스를 조회하면 이벤트가 발생합니다)
bash
# Trail 로깅 상태 확인
aws cloudtrail get-trail-status \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 마지막 로그 전달 시간 확인 (LatestDeliveryTime이 있으면 정상)
aws cloudtrail get-trail-status \
  --name ShopEasy-Trail \
  --region ap-northeast-2 \
  --query "{IsLogging:IsLogging, LatestDeliveryTime:LatestDeliveryTime, LatestDeliveryError:LatestDeliveryError}"

# API 호출을 발생시켜 로그 생성 유도
aws sts get-caller-identity
aws s3 ls

# 5분 후 S3 버킷 다시 확인
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws s3 ls s3://shopeasy-cloudtrail-${ACCOUNT_ID}/ --recursive | head -5
이벤트 기록에서 특정 이벤트를 찾을 수 없음

원인: 이벤트가 아직 반영되지 않았거나, 데이터 이벤트를 검색하고 있음

해결 방법:

  1. 이벤트가 이벤트 기록에 반영되기까지 최대 15분 소요될 수 있습니다
  2. 이벤트 기록은 관리 이벤트만 표시합니다. S3 GetObject(파일 다운로드), PutObject(파일 업로드) 같은 데이터 이벤트는 표시되지 않습니다
  3. 필터 값의 대소문자가 정확한지 확인하세요 (예: RunInstances (O), runinstances (X))
  4. 이벤트 이름이 정확한지 확인하세요 (예: EC2 생성은 RunInstances이지, CreateInstance가 아닙니다)
bash
# 최근 이벤트 목록 확인 (최근 10개)
aws cloudtrail lookup-events \
  --max-results 10 \
  --region ap-northeast-2 \
  --query "Events[].{Time:EventTime, Event:EventName, User:Username}" \
  --output table

# 주요 관리 이벤트 이름 참고:
# EC2 인스턴스 생성: RunInstances
# EC2 인스턴스 종료: TerminateInstances
# S3 버킷 생성: CreateBucket
# S3 버킷 삭제: DeleteBucket
# IAM 역할 생성: CreateRole
# IAM 정책 연결: AttachRolePolicy
# RDS 인스턴스 생성: CreateDBInstance
# CloudTrail 추적 생성: CreateTrail
Trail을 삭제하고 다시 만들고 싶음

원인: 설정이 잘못되었거나, 다시 처음부터 하고 싶음

해결 방법:

bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# 1. 로깅 중지
aws cloudtrail stop-logging \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 2. Trail 삭제
aws cloudtrail delete-trail \
  --name ShopEasy-Trail \
  --region ap-northeast-2

# 3. (선택) S3 버킷의 기존 로그 삭제 후 버킷 삭제
aws s3 rm s3://shopeasy-cloudtrail-${ACCOUNT_ID} --recursive
aws s3api delete-bucket \
  --bucket shopeasy-cloudtrail-${ACCOUNT_ID} \
  --region ap-northeast-2

# 4. 다시 처음부터 Step 2를 수행
S3 버킷 이름 충돌: "BucketAlreadyExists"

원인: S3 버킷 이름은 전 세계에서 유일해야 하는데, 이미 같은 이름이 존재

해결 방법:

  1. 버킷 이름에 계정 ID를 포함했는지 확인 (shopeasy-cloudtrail-{ACCOUNT_ID})
  2. 이미 본인이 만든 버킷이 있을 수 있으므로 aws s3 ls | grep cloudtrail로 확인
  3. 필요시 다른 이름을 사용 (예: shopeasy-trail-logs-{ACCOUNT_ID})
bash
# 기존 버킷 확인
aws s3 ls | grep cloudtrail

# 이미 있으면 해당 버킷을 사용하여 Trail 생성
# 또는 다른 이름으로 버킷 생성
강사 참고: 학생들이 자주 실수하는 포인트
  1. CLI에서 start-logging을 빼먹음 - create-trail 만으로는 로깅이 시작되지 않습니다. 반드시 start-logging을 실행해야 합니다
  2. 로그가 바로 안 보인다고 당황 - CloudTrail은 약 5분 간격으로 로그를 배치 전달합니다. Trail 생성 직후에는 5~15분 기다려야 합니다
  3. 데이터 이벤트와 관리 이벤트를 혼동 - 이벤트 기록에서 S3 PutObject(파일 업로드)를 찾으려 하는 경우가 있습니다. 이벤트 기록은 관리 이벤트만 표시합니다
  4. 이벤트 이름의 대소문자 오류 - API 이름은 대소문자를 구분합니다. RunInstances가 맞고 runinstances는 검색되지 않습니다
  5. CLI에서 버킷 정책 설정을 건너뜀 - 콘솔에서는 자동이지만, CLI에서는 버킷 정책을 직접 설정해야 Trail이 로그를 쓸 수 있습니다
  6. 리전 설정 누락 - CLI 명령에 --region ap-northeast-2를 빼먹으면 기본 리전에서 실행됩니다