기준: SCS-C03 시험 가이드오류 제보
거버넌스 천장(SCP), 베이스라인 자동화(Control Tower), 증거 수집(Audit Manager)을 갖췄다면, 남은 것은 일상 운영이다. 수백 개 계정에 방화벽 정책을 일관되게 깔고, 태그·비용을 통제하고, 새 계정이 태어날 때마다 보안 도구가 자동으로 켜지게 하는 운영 평면이다. 이 날의 핵심은 AWS Firewall Manager(중앙 방화벽 정책 배포), 태그·비용 거버넌스, 그리고 보안 베이스라인 자동화다.
세 주제를 관통하는 한 문장이 있다. "정책은 한 번 선언하고, 시스템이 계속 수렴시킨다." Day 1의 SCP가 할 수 없는 것을 정의했다면, 오늘의 도구들은 반드시 있어야 하는 것을 계속 유지시킨다. 전자는 경계, 후자는 수렴이다. 시험 보기에서 "차단해야 하는가, 아니면 자동으로 붙여 줘야 하는가"를 먼저 가르는 것이 정답으로 가는 첫 갈림길이다.
WAF·Shield·Security Group·Network Firewall·Route 53 Resolver DNS Firewall를 계정마다 손으로 설정하면 누락과 드리프트가 불가피하다. Firewall Manager(FMS)는 조직 전역에 방화벽 정책을 한 번 정의해 자동 배포·강제하는 서비스다.
전제 조건이 중요하다:
리전 제약도 하나 있다. Shield Advanced 정책과 CloudFront 범위의 WAF 정책은 us-east-1에서 생성해야 한다. "서울 리전에서 FMS 정책을 만들었는데 CloudFront 배포에 적용되지 않는다"는 상황의 정체가 대부분 이것이다.
[ 관리 계정 (Management) ]
· Organizations / 결제 / OU 구조
· FMS 관리자 계정 "지정"만 수행
│ associate-admin-account
▼
┌────────────────────────────────────────────┐
│ Security(Audit) 계정 = FMS 관리자 │
│ · WAF 정책 / SG 감사 정책 / DNS 정책 각 1개 │
│ · 범위: OU · 계정 · 리소스 태그로 선언 │
│ · 조직 단일 준수 대시보드 + 자동 교정 │
└──────────────────┬─────────────────────────┘
│ 배포 · 지속 평가 · 교정
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
OU: Prod OU: NonProd OU: Sandbox
├ 계정 A (ALB×12) ├ 계정 D └ (범위에서 제외)
├ 계정 B (CF×3) └ 계정 E
└ 계정 C (API GW×5)
│
└─▶ 새 ALB 생성 → FMS 감지 → 공통 Web ACL 자동 연결 (사람 개입 0회)
전제: 각 멤버 계정·리전에서 Config가 켜져 있어야 평가·교정이 성립
FMS가 배포·강제할 수 있는 정책 유형:
FMS의 강점은 신규 리소스 자동 보호다. 정책 범위(계정·리소스 태그)에 맞는 새 리소스가 생기면 FMS가 자동으로 정책을 적용한다. "WAF를 안 붙인 ALB"가 새로 생겨도 FMS가 자동 연결한다.
이것은 정책의 선언적 강제(declarative enforcement)와 지속적 교정(continuous remediation)이다. 정책을 한 번 선언하면 시스템이 현재 상태를 선언 상태로 수렴시킨다(Kubernetes의 reconcile loop와 동일한 사고). 사람이 매번 적용하는 명령형 운영의 누락 확률은 리소스 수 n에 대해 대략 1-(1-p)^n으로 커지지만, 선언적 수렴의 실패 확률은 n이 커져도 정책 정의 1개의 정확성에 수렴한다. 계정 수가 세 자리로 갈 때 FMS가 선택이 아닌 이유가 이 수식에 있다.
"WAF를 각 계정에서 붙이면 되지 않나"는 계정이 5개일 때는 맞고 200개일 때는 틀리다.
| 축 | 계정별 개별 WAF/SG 관리 | Firewall Manager |
|---|---|---|
| 정책 정의 지점 | 계정×리전마다 각각 | FMS 관리자 계정에서 1회 |
| 신규 리소스 | 사람이 기억해야 붙음 | 범위 매칭 시 자동 연결 |
| 드리프트(누가 떼어냄) | 발견 자체가 어려움 | 비준수 보고 + RemediationEnabled면 자동 복원 |
| 준수 가시성 | 계정별 콘솔 순회 | 조직 단일 준수 대시보드 |
| 신규 계정 | 온보딩 체크리스트에 의존 | OU에 들어오는 순간 정책 상속 |
| 범위 지정 | 불가(수동 판단) | OU·계정·리소스 태그로 선언적 지정 |
| 실패 모드 | 조용한 누락 | 가시적 비준수 |
마지막 행이 본질이다. 개별 관리의 실패는 아무 신호도 남기지 않고, FMS의 실패는 대시보드에 뜬다. 보안 운영에서 "조용한 실패"를 "시끄러운 실패"로 바꾸는 것 자체가 통제다.
| 서비스 | 본질 | 관계 |
|---|---|---|
| WAF | 단일 Web ACL을 한 리소스에 적용 | FMS가 배포하는 대상 |
| Network Firewall | VPC 트래픽 검사(stateful/IPS) | FMS가 배포하는 대상 |
| Firewall Manager | 위 정책들을 조직 전역 배포·강제·교정 | 오케스트레이터 |
시험에서 "여러 계정에 WAF를 일관 적용하고 신규 리소스도 자동 보호" → 답은 거의 항상 Firewall Manager다. 단일 리소스 보호면 WAF 직접이다.
// FMS WAF 정책 — 범위 축소·생애주기 옵션까지 붙인 실물 형태
{
"PolicyName": "Org-Common-WAF-Prod",
"ResourceType": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"IncludeMap": { "ORG_UNIT": ["ou-xxxx-prod", "ou-xxxx-shared"] },
"ExcludeMap": { "ACCOUNT": ["999988887777"] },
"ExcludeResourceTags": true,
"ResourceTags": [ { "Key": "fms-exempt", "Value": "true" } ],
"RemediationEnabled": true,
"DeleteUnusedFMManagedResources": true,
"SecurityServicePolicyData": {
"Type": "WAFV2",
"ManagedServiceData": "{\"type\":\"WAFV2\",\"preProcessRuleGroups\":[{\"managedRuleGroupIdentifier\":{\"vendorName\":\"AWS\",\"managedRuleGroupName\":\"AWSManagedRulesCommonRuleSet\"},\"overrideAction\":{\"type\":\"NONE\"},\"ruleGroupType\":\"ManagedRuleGroup\"}],\"postProcessRuleGroups\":[],\"defaultAction\":{\"type\":\"ALLOW\"}}"
}
}세 옵션의 의미가 실무·시험 모두에서 갈린다.
ExcludeResourceTags: true + ResourceTags: 이 태그가 붙은 리소스를 범위에서 뺀다. false면 반대로 그 태그가 붙은 리소스만 포함한다. 예외 승인 프로세스를 태그로 구현하는 표준 패턴이다.DeleteUnusedFMManagedResources: true: 정책 삭제·범위 이탈 시 FMS가 만든 Web ACL 같은 관리형 리소스를 함께 정리한다. false면 고아 Web ACL이 계정마다 남아 요금이 계속 나간다.preProcessRuleGroups / postProcessRuleGroups: 각 멤버 계정 Web ACL의 앞단·뒷단에 고정되는 규칙 그룹이고, 그 사이는 계정 소유자가 자기 규칙을 넣도록 남겨 둔다. "조직 필수 규칙은 못 건드리되 앱별 규칙은 각자 추가"라는 절충이 구조로 표현된 것이다.# 1) 관리 계정에서 FMS 관리자(위임 관리자) 지정 — 통상 Security/Audit 계정
aws fms associate-admin-account --admin-account 222233334444
# 2) FMS 관리자 계정에서 정책 생성
aws fms put-policy --policy file://org-common-waf.json
# 3) 조직 전역 준수 상태 / 계정별 비준수 원인 확인
aws fms list-compliance-status --policy-id <policy-id>
aws fms get-compliance-detail --policy-id <policy-id> --member-account 111122223333
# Network Firewall / DNS Firewall 정책 전제: 조직 리소스 공유 활성화
aws ram enable-sharing-with-aws-organizationsSecurity Group 정책은 세 종류이며, 시험은 "어느 쪽인가"를 묻는다.
| SG 정책 유형 | 하는 일 | 답이 되는 상황 |
|---|---|---|
| 공통 보안 그룹(Common) | 조직 표준 SG를 범위 내 리소스에 붙인다 | "모든 EC2/ENI에 공통 기본 SG를 강제 부착" |
| 콘텐츠 감사(Content audit) | 기존 SG의 규칙 내용을 템플릿과 대조해 판정 | "0.0.0.0/0 인바운드나 22/3389 개방을 조직 전역 금지" |
| 사용 현황 감사(Usage audit) | 미사용·중복 SG를 찾아 정리 | "쓰지 않는 보안 그룹이 쌓여 관리 불가" |
⚠️ 함정: FMS 정책을 만들어도 아무 일도 일어나지 않는 세 가지 흔한 원인이 있다. ① 대상 계정·리전에서 Config가 꺼져 있다 — FMS는 Config 인벤토리 위에서 평가하므로 "비준수 0건"이 아니라 "평가 자체가 없음"이 되고, 대시보드가 깨끗해 보여서 더 위험하다. ②
RemediationEnabled가false다 — 이때 FMS는 보고만 하고 아무것도 붙이지 않는다. "정책은 있는데 Web ACL이 안 붙는다"의 1순위 원인. ③ CloudFront/Shield Advanced 정책을us-east-1이 아닌 리전에서 만들었다 — 정책은 생성되지만 대상이 잡히지 않는다. 셋 다 에러 없이 조용히 실패하는 형태라 진단이 늦어진다.
FMS가 WAF 정책을 배포할 때 하는 일은 중앙 Web ACL을 공유하는 것이 아니다. 각 멤버 계정·리전에 그 계정 소유의 FMS 관리형 Web ACL을 새로 만들고 정책 규칙 그룹을 앞뒤로 고정한 뒤 대상 리소스에 연결한다. 그래서 ① WAF 요금·용량 단위(WCU)는 각 멤버 계정에 청구되고, ② 멤버 계정 관리자가 FMS 관리 영역을 수정해도 다음 평가 주기에 되돌려진다. 이 되돌림이 곧 지속적 교정이며 Control Tower 드리프트와 같은 원리다. 다만 계정 관리자가 Web ACL을 삭제하면 FMS가 재생성하기까지 짧은 무방비 구간이 생긴다. 이 구간을 없애려면 SCP로 wafv2:DeleteWebACL·wafv2:DisassociateWebACL을 Deny해 두는 것이 정석이다 — FMS(수렴)와 SCP(경계)를 겹쳐 쓰는 전형적 조합이다.
태그는 비용 배분·접근 통제(ABAC)·자동화의 기반이다. 태그가 일관되지 않으면 비용 추적도, 태그 기반 권한도 무너진다. 조직 규모의 태그 거버넌스는 세 축으로 강제한다.
역할이 겹쳐 보이지만 차단 시점과 강제력이 전혀 다르다. 이 표가 판단 축이다.
| Tag Policy (Organizations) | SCP 태그 조건 | Config required-tags | |
|---|---|---|---|
| 통제 유형 | 표준화 + (선택적) 강제 | 예방(차단) | 탐지 + 교정 |
| 작동 시점 | 태그 지정·변경 시 | API 호출 평가 시 | 리소스 생성·변경 후 |
| 무엇을 막나 | 비준수 값·표기의 태그 부착 | 필수 태그 없는 생성 자체 | 아무것도 막지 못함(사후) |
| 무태그 생성 | 막지 못함 | 막음 | 사후 탐지 |
| 산출물 | 준수 리포트 | AccessDenied | NON_COMPLIANT + 교정 실행 |
핵심 함정이 4행에 있다. Tag Policy는 "태그를 아예 안 달고 리소스를 만드는 것"을 막지 못한다. Tag Policy가 강제하는 것은 태그가 붙을 때 그 키·값이 표준을 따르는가이지 태그가 반드시 있어야 하는가가 아니다. "필수 태그 없이는 생성 불가"를 원하면 답은 언제나 SCP다. 보기에 둘이 함께 나오면 요구사항의 동사가 "표준화/보고"인지 "차단/강제"인지부터 확인한다.
// SCP: 태그를 "붙이게" 만들고, 붙은 뒤 "떼지 못하게" 만든다 — 두 개가 한 쌍
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyCreateWithoutRequiredTags",
"Effect": "Deny",
"Action": ["ec2:RunInstances", "rds:CreateDBInstance", "s3:CreateBucket"],
"Resource": "*",
"Condition": {
"Null": {
"aws:RequestTag/CostCenter": "true",
"aws:RequestTag/DataClassification": "true"
},
"Bool": { "aws:PrincipalIsAWSService": "false" }
}
},
{
"Sid": "DenyInvalidDataClassificationValue",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestTag/DataClassification": ["public","internal","confidential","restricted"]
},
"Null": { "aws:RequestTag/DataClassification": "false" }
}
},
{
"Sid": "DenyRemovingGovernanceTags",
"Effect": "Deny",
"Action": ["ec2:DeleteTags", "rds:RemoveTagsFromResource", "s3:DeleteBucketTagging"],
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:TagKeys": ["CostCenter", "DataClassification"]
},
"ArnNotLike": { "aws:PrincipalARN": "arn:aws:iam::*:role/OrgTagGovernanceRole" }
}
}
]
}세 Statement가 각각 다른 구멍을 막는다. 첫째는 무태그 생성, 둘째는 비표준 값, 셋째는 사후 태그 제거다. 둘째에서 Null을 "false"로 둔 것이 포인트다 — "태그가 있을 때만 값 검사"를 뜻하며, 이 조건이 없으면 태그를 지정하지 않은 모든 호출까지 걸려 다른 서비스가 통째로 깨진다. 셋째가 없으면 "만들 때만 태그를 달고 곧바로 지우는" 우회가 성립하는데, 태그로 접근 통제(ABAC)를 하는 조직에서 이 우회는 곧 권한 상승 경로다.
# Organizations Tag Policy: 키 표기·허용값 표준화, 지정 리소스 타입에 한해 강제
aws organizations enable-policy-type --root-id r-exam --policy-type TAG_POLICY
aws organizations create-policy \
--name "Org-Standard-Tags" --type TAG_POLICY \
--content '{ "tags": { "CostCenter": {
"tag_key": { "@@assign": "CostCenter" },
"tag_value": { "@@assign": ["CC-1001","CC-1002","CC-2001"] },
"enforced_for": { "@@assign": ["ec2:instance","rds:db","s3:bucket"] } } } }'
aws organizations attach-policy --policy-id p-tagpolicy --target-id ou-xxxx-prod
# 조직 전역 태그 실태 조사와 일괄 보정
aws resourcegroupstaggingapi get-tag-keys
aws resourcegroupstaggingapi get-resources \
--tag-filters Key=DataClassification,Values=restricted \
--resource-type-filters ec2:instance rds:db s3
aws resourcegroupstaggingapi tag-resources \
--resource-arn-list arn:aws:ec2:ap-northeast-2:111122223333:instance/i-0abc123 \
--tags CostCenter=CC-1001,Owner=platform-team태그는 ABAC(Attribute-Based Access Control)의 핵심이기도 하다. aws:ResourceTag/aws:PrincipalTag로 "같은 팀 태그를 가진 리소스만 접근" 같은 동적 권한을 줄 수 있어, 계정·리소스가 늘어도 정책 수가 폭발하지 않는다. 아래 정책 하나가 팀이 3개든 300개든 그대로 동작한다.
{
"Effect": "Allow",
"Action": ["ec2:StartInstances","ec2:StopInstances"],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": { "aws:ResourceTag/Team": "${aws:PrincipalTag/Team}" }
}
}다만 ABAC의 안전성은 전적으로 태그의 무결성에 의존한다. 위 SCP의 셋째 Statement(태그 제거 차단)와 "자기 프린시펄 태그를 스스로 바꾸지 못하게" 하는 통제가 없으면, 사용자가 자기 Team 태그를 바꿔 남의 리소스를 만지는 권한 상승이 성립한다. ABAC를 도입할 때 iam:TagRole·iam:TagUser·sts:TagSession을 함께 잠그는 이유다.
태그 거버넌스는 신뢰할 수 있는 식별자(trusted identifier) 문제다. 태그는 사용자가 자유롭게 쓰는 문자열이므로 본질적으로 신뢰할 수 없는 필드인데, ABAC와 비용 배분은 그것을 신뢰한다고 가정한다. 그 간극을 메우는 것이 "누가 태그를 쓰고 지울 수 있는가"에 대한 통제다. 즉 태그 거버넌스의 절반은 태그 값이 아니라 태그 변경 권한의 거버넌스다. 예방(SCP)·표준화(Tag Policy)·교정(Config)을 함께 써야 "garbage in, garbage out"을 끊을 수 있다.
⚠️ 함정:
aws:RequestTag/*조건은 해당 API가 생성 시 태그 지정(tag-on-create)을 지원할 때만 의미가 있다. 지원하지 않는 API에 이Null조건을 걸면 태그를 요청에 실을 방법이 없으므로 그 액션은 항상 거부된다. 그래서 실무 SCP는 액션 목록을 넓게 잡지 말고 tag-on-create 지원 액션만 골라 명시한다. 하나 더 —ec2:RunInstances에서 태그를 강제하려면 사용자의 IAM 정책이 인스턴스 리소스에 대해ec2:CreateTags를 허용하고 있어야 한다. SCP는 통과했는데 IAM에CreateTags가 없어 생성이 실패하는, 원인을 찾기 어려운 조합이 있다.
"SCP로 막았는데 왜 리소스가 태그 없이 생겼나"의 답은 언제나 평가 규칙에 있다. Day 1의 판정 규칙을 태그 맥락에서 압축하면 이렇다.
유효 권한 = (SCP ∩ RCP ∩ 권한경계 ∩ 세션정책) ∩ (IAM Allow ∪ 리소스정책 Allow) − (모든 Deny)
① 명시적 Deny 하나면 종료 → 태그 SCP의 Deny는 AdministratorAccess도 이긴다
⑦ 어디에도 Allow가 없으면 암묵적 Deny
| 정책 유형 | 태그 거버넌스에서의 역할 | 힘의 크기 |
|---|---|---|
| SCP | 계정·OU 전체의 무태그 생성 차단 | Deny면 무조건 이김(단 관리 계정 프린시펄엔 미적용) |
| IAM 아이덴티티 정책 | 실제 권한 부여 + 태그 조건 부가 | SCP Deny를 못 이김 |
| 권한 경계 | 특정 역할 하나의 상한 | 좁히기만 가능, Allow를 넓히지 못함 |
| 리소스 기반 정책 | 교차 계정 접근 시 태그 조건 부과 | 동일 계정에서만 단독 Allow 성립 |
여기서 두 개의 실전 결론이 나온다. 첫째, SCP는 관리 계정 프린시펄에 적용되지 않으므로 관리 계정에서 워크로드를 돌리면 태그·리전 강제가 통째로 샌다(관리 계정에 워크로드를 두지 말라는 규칙의 또 다른 근거). 둘째, AWS 서비스가 자기 이름으로 만드는 리소스는 요청에 태그를 싣지 않는 경우가 있어 SCP Deny에 걸린다 — 그래서 위 JSON 첫째 Statement에 aws:PrincipalIsAWSService 조건이 붙어 있다.
🎯 시나리오: 태그 강제 SCP를 Prod OU에 붙인 다음 날, Auto Scaling 스케일아웃이 전부 실패하고 CloudFormation 스택 업데이트가 롤백된다. 원인과 해법은? → ASG가 인스턴스를 만드는
ec2:RunInstances호출에CostCenter태그가 실리지 않았기 때문이다. 해법은 세 갈래다. ① ASG의 태그 전파(PropagateAtLaunch) 를 켜서 그룹 태그가 인스턴스 요청에 실리게 한다. ② CloudFormation 스택 레벨 태그를 표준화해 하위 리소스에 상속시킨다. ③ 그래도 남는 서비스 프린시펄 경로만aws:PrincipalIsAWSService조건으로 예외한다. 중요한 판단은 ③을 먼저 하면 안 된다는 것이다 — 예외를 먼저 열면 아무도 ①을 하지 않고, 태그 누락이 서비스 경로로 영구히 새어 나간다. 강제 정책을 도입할 때는 항상 예외를 열기 전에 정상 경로를 먼저 고친다.
비용은 보안과 무관해 보이지만, 비정상 비용 급증은 침해의 신호일 수 있다(암호화폐 채굴 인스턴스, 데이터 유출 송신, 탈취된 키로 대량 리소스 생성). 보안 운영은 비용 신호를 위협 탐지에 활용한다.
{
"Sid": "DenyExpensiveGPUInstances",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"ForAnyValue:StringLike": { "ec2:InstanceType": ["p4d.*","p5.*","x2*"] }
}
}GuardDuty의 일부 발견 유형(예: 암호화폐 채굴 관련 EC2/Kubernetes 발견)도 이 맥락과 직접 연결된다.
여기에 리전 제한을 겹치면 피해 한계가 한 번 더 줄어든다. 채굴 공격의 전형적 행태는 조직이 쓰지 않는 리전에 인스턴스를 띄우는 것이다 — 기본 리전만 보는 운영자에게 오래 발각되지 않기 때문이다.
{
"Sid": "DenyAllOutsideApprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*", "organizations:*", "sts:*", "cloudfront:*", "route53:*",
"support:*", "budgets:*", "ce:*", "waf:*", "wafv2:*", "shield:*", "fms:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": { "aws:RequestedRegion": ["ap-northeast-2", "us-east-1"] }
}
}NotAction에 글로벌 서비스를 예외로 두어야 한다는 점, 그리고 CloudFront·WAF(글로벌 범위)·Shield·FMS의 제어 평면이 us-east-1이라 그 리전을 허용 목록에 남겨야 한다는 점이 이 패턴의 두 함정이다. SCP 하나가 "우리는 서울만 쓴다"는 정책을 미사용 리전에서의 채굴·데이터 유출까지 차단하는 보안 통제로 바꾼다.
# 조직 전체를 하나의 비용 이상 모니터로 두고, 알림을 보안 채널로 흘린다
aws ce create-anomaly-monitor --anomaly-monitor \
'{"MonitorName":"OrgWideCostMonitor","MonitorType":"DIMENSIONAL","MonitorDimension":"SERVICE"}'
aws ce create-anomaly-subscription --anomaly-subscription '{
"SubscriptionName": "SecOps-Cost-Spike",
"MonitorArnList": ["arn:aws:ce::111122223333:anomalymonitor/<id>"],
"Subscribers": [{"Type":"SNS","Address":"arn:aws:sns:us-east-1:222233334444:secops-alerts"}],
"Frequency": "IMMEDIATE" }'
aws ce get-anomalies --date-interval StartDate=2026-07-01,EndDate=2026-07-312018년 2월, 클라우드 보안 업체 RedLock(현 Palo Alto Networks) 연구팀은 테슬라의 AWS 환경에서 암호화폐 채굴이 진행 중이던 것을 발견해 보고했다. 침투 경로는 정교한 취약점이 아니라 인증이 걸려 있지 않은 Kubernetes 관리 콘솔이었고, 그 콘솔 안에 AWS 자격증명이 노출돼 있었다. 이 사건이 거버넌스 교재에 계속 인용되는 이유는 채굴 자체가 아니라 은닉 기법 때문이다 — 공격자는 ① 공개 채굴 풀 대신 자체 마이닝 풀 서버를 쓰고, ② 그 서버를 CDN 뒤에 숨겨 목적지 IP 평판 기반 탐지를 회피했으며, ③ 비표준 포트를 사용하고, ④ CPU 사용률을 의도적으로 낮게 유지해 "사용률 급등" 기반 탐지에 걸리지 않게 했다. 전통적 임계값 탐지를 전부 우회한 것이다. 남는 신호는 결국 비용과 권한 경계 위반이었다. 실무 결론은 명확하다 — 채굴 탐지를 CPU 사용률 하나에 걸지 말고 비용 이상 탐지 + GuardDuty 발견 유형 + 미사용 리전·대형 인스턴스 SCP 차단을 겹쳐야 한다. 그리고 근본 원인은 언제나 "자격증명이 놓여 있던 자리"였다는 점도 잊으면 안 된다.
🎯 시나리오: 새벽 3시에 Cost Anomaly Detection이 특정 계정에서 평소 대비 40배 지출을 알렸다. 조직이 쓰지 않는 3개 리전에서 대형 인스턴스 수십 대가 떠 있고, 생성 주체는 6개월 전 발급된 IAM 사용자 액세스 키였다. 순서대로 무엇을 하는가. → ① 자격증명 무력화 먼저: 액세스 키를
Inactive로 바꾼다(삭제보다 비활성화가 포렌식에 유리하다). ② 격리: 인스턴스를 종료하지 말고 격리 SG로 교체 + 스냅샷 확보 — 종료하면 메모리·디스크 증거가 사라진다. ③ 범위 확정: CloudTrail에서 그 키의 전체 호출 이력을 뒤져CreateUser·AttachUserPolicy·PutBucketPolicy같은 지속성·확산 행위를 찾는다. ④ 재발 차단: 리전 제한·인스턴스 타입 제한 SCP를 적용하고, 장기 액세스 키를 IAM Identity Center 기반 임시 자격증명으로 대체한다. 순서는 멈춤 → 보존 → 조사 → 예방이며, 흔한 실수는 ②에서 인스턴스를 곧바로 삭제해 조사를 불가능하게 만드는 것이다.
새 계정이 태어날 때마다 보안 도구가 자동으로 켜지고, 비준수가 자동 교정되게 만드는 것이 다계정 보안 운영의 종착점이다. 구성 요소:
자동 등록은 서비스마다 별도로 켜야 한다는 점이 실무에서 자주 빠진다. 하나라도 놓치면 그 서비스만 신규 계정에서 조용히 꺼진 채 남는다.
# GuardDuty: 위임 관리자에서 조직 신규 계정 자동 등록
aws guardduty update-organization-configuration \
--detector-id <detector-id> --auto-enable-organization-members ALL
# Security Hub: 신규 계정 자동 등록 + 기본 표준 자동 활성화
aws securityhub update-organization-configuration \
--auto-enable --auto-enable-standards DEFAULT
# Config 자동 교정: 비준수 감지 시 SSM Automation 실행
aws configservice put-remediation-configuration --remediation-configurations '[{
"ConfigRuleName": "s3-bucket-public-read-prohibited",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-DisableS3BucketPublicReadWrite",
"Automatic": true, "MaximumAutomaticAttempts": 5, "RetryAttemptSeconds": 60,
"Parameters": {
"AutomationAssumeRole": {"StaticValue":{"Values":["arn:aws:iam::111122223333:role/ConfigRemediationRole"]}},
"S3BucketName": {"ResourceValue":{"Value":"RESOURCE_ID"}} } }]'EventBridge 규칙은 "무엇을 잡을 것인가"를 이벤트 패턴으로 선언한다. 심각도로 걸러 노이즈를 줄이는 것이 표준이다.
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [ { "numeric": [">=", 7] } ],
"type": [ { "prefix": "CryptoCurrency:" }, { "prefix": "UnauthorizedAccess:" } ]
}
}닫힌 루프 전체를 그리면 이렇게 된다.
[ 계정 발급 경로 ] [ 상시 운영 루프 ]
Account Factory / AFT 워크로드 계정에서 이벤트 발생
│ 계정 생성 │
▼ ▼
OU 배치 + 표준 태그 GuardDuty / Security Hub / Config
│ │ finding · NON_COMPLIANT
▼ ▼
auto-enable 상속 EventBridge 규칙(심각도 필터)
├ GuardDuty │
├ Security Hub ┌───────────┼───────────┐
├ Config + 조직 규칙 ▼ ▼ ▼
└ FMS 정책(OU 상속) Lambda 격리 SSM 교정 SNS/Slack
│ (키 비활성화) (설정 복원) (사람 판단분)
▼ │ │
베이스라인 IaC 후처리 └─────┬─────┘
(역할·로그 구독·네트워크) ▼
│ Security Hub에 결과 반영
└─────────────────────────────▶ (준수 상태 재평가)
자동 교정은 켜는 순간 운영 사고의 새로운 원인이 된다. ① 교정 루프: 교정이 리소스를 바꾸면 그것이 다시 구성 변경 이벤트를 만들고 다른 규칙이 또 교정하는 진동이 생긴다(MaximumAutomaticAttempts와 규칙 간 충돌 검토가 필요한 이유). ② 의도된 예외를 부수는 교정: 승인받은 퍼블릭 배포용 버킷이 자동 교정으로 닫혀 서비스가 중단된다 — 예외를 태그로 선언하고 교정 대상에서 빼는 설계가 먼저 있어야 한다. ③ 권한 부족으로 조용히 실패: AutomationAssumeRole에 권한이 없으면 교정이 실패하는데 대시보드에는 여전히 "교정 구성됨"으로 보인다. 자동 교정은 반드시 교정 실패 자체를 알림 대상으로 삼아야 한다.
자동 대응을 설계할 때 판단 기준은 "이 조치가 되돌릴 수 있는가"다. 가역적 조치(액세스 키 비활성화, 격리 SG 교체, 스냅샷 생성, 세션 무효화)는 자동화해도 안전하다 — 오탐이어도 몇 분 안에 복구된다. 비가역적 조치(인스턴스 종료, 사용자 삭제, 리소스 삭제)는 자동화하면 오탐 한 번이 곧 장애다. 그래서 성숙한 조직은 가역적 조치는 자동, 비가역적 조치는 승인 게이트(Step Functions 대기 상태 + 승인 콜백)로 나눈다. 하나 더 — 자동 대응 Lambda가 멤버 계정에서 조치하려면 각 계정에 교차 계정 대응 역할이 미리 배포돼 있어야 하고, 그 역할은 매우 강력하다. 신뢰 정책을 보안 계정의 특정 Lambda 실행 역할로 좁히고 SCP로 그 역할의 삭제·수정을 막는 것이 정석이다. 대응 역할이 곧 최고 권한 통로이므로, 대응 자동화의 보안이 조직 전체 보안의 상한이 된다.
RemediationEnabled: false면 FMS는 보고만 한다 — "정책은 있는데 안 붙는다"의 1순위 원인.DeleteUnusedFMManagedResources를 끄면 정책 삭제 후 고아 Web ACL이 계정마다 남아 요금이 계속 나간다.aws:RequestTag는 tag-on-create 지원 API에서만 유효하다 — 미지원 액션에 걸면 항상 거부된다.iam:TagRole·sts:TagSession도 함께 잠가야 한다.RemediationEnabled와 DeleteUnusedFMManagedResources를 의도대로 설정했는가us-east-1에서 만들었는가ExcludeResourceTags)로 선언해 승인 프로세스와 연결했는가aws:TagKeys + ec2:DeleteTags)까지 한 쌍으로 걸었는가us-east-1 예외를 정확히 넣었는가AutomationAssumeRole 권한이 있고, 교정 실패가 알림 대상인가선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
200개 계정의 모든 ALB에 공통 WAF 관리형 규칙을 적용하고, 앞으로 새로 생기는 ALB도 자동으로 보호되게 하려 한다. 가장 적절한 서비스는?
문제 2
Firewall Manager 정책을 만들었는데 일부 계정에서 준수 평가·자동 교정이 동작하지 않는다. 가장 가능성 높은 전제 조건 누락은?
문제 3
모든 EC2/RDS 생성 시 CostCenter 태그를 반드시 갖도록 *강제(차단)*하려 한다. 가장 직접적인 방법은?
문제 4
한 계정에서 평소의 10배에 달하는 GPU 인스턴스 비용이 갑자기 발생했다. 보안 운영 관점의 가장 적절한 해석과 통제 조합은?
문제 5
신규로 조직에 합류하는 모든 계정에서 GuardDuty·Security Hub·Config가 자동으로 켜지고, 발견된 비준수가 자동 교정되게 하려 한다. 가장 적절한 설계는?