[S3 4/7] S3 보안 다층 방어 — 7계층 패턴과 실전 구현

2026/05/18 AWS Security 8094자 · 약 24분

Hook

S3 버킷 하나를 공개하면 하루 만에 수천 건의 무단 접근 시도가 시작됩니다. 보안은 단일 계층이 아니라 다층 방어로 설계해야 합니다.

한 계층이 뚫려도 다음 계층이 막아주는 구조가 되어야 합니다. 이 글에서는 S3 데이터 보안을 위한 7계층 방어 모델과 함께, 최소 권한 원칙, 버킷 정책 6가지 패턴, Block Public Access, SSE-KMS 암호화, CloudTrail 감사까지 실전 코드로 정리합니다.


TL;DR

  • 7계층 방어 모델 — 네트워크 → 액세스 → 권한 → 암호화 → 모니터링
  • 최소 권한이 핵심 — 읽기 전용이면 읽기 전용만, 필요한 경로만
  • Block Public Access는 기본 — 실수로 공개되는 것을 원천 차단
  • 암호화는 SSE-KMS 기본 — 키 제어권을 갖는 암호화
  • CloudTrail + Macie로 감사 — 누가 언제 무엇을 했는지 추적

S3 보안 7계층 모델

S3 보안은 여러 레이어로 구성된 방어 심도(Defense in Depth) 모델로 설계합니다. 하나의 계층에 의존하면 단일 장애점이 됩니다.

S3 보안 7계층 Defense in Depth 모델

7개 계층은 각각 독립적으로 작동하면서 상호 보완합니다.

계층역할핵심 서비스
Layer 1: IAM 인증사용자/역할 기반 인증 기반IAM, STS, MFA
Layer 2: Block Public Access공개 접근 원천 차단S3 BPA
Layer 3: 네트워크 보안VPC/TLS/IP 제한VPC Endpoint, TLS
Layer 4: 버킷 정책 & ACL세밀한 접근 제어Bucket Policy, IAM 정책
Layer 5: 공유 메커니즘 보안Pre-signed URL, Access Point만료 시간, AP 정책
Layer 6: 데이터 보호암호화, 버전관리, WORMSSE-S3/KMS, Versioning
Layer 7: 모니터링 & 감사추적 및 탐지CloudTrail, Macie, Config

보안 결정 흐름

S3에 들어온 모든 요청은 정해진 순서로 평가됩니다. 이 흐름을 이해하면 정책이 왜 허용/거부되는지 알 수 있습니다.

S3 보안 결정 흐름 — 요청부터 허용/거부까지

핵심 원칙은 명시적 Deny > Block Public Access > 명시적 Allow > 기본 거부입니다. 기본적으로 모든 S3 접근은 암시적으로 거부되며, 명시적 Allow가 있어야만 허용됩니다.


최소 권한 원칙

데이터 공유 시 필요한 최소한의 권한만 부여하는 것이 핵심입니다. “읽기만 주면 되는데 s3:*를 주는” 실수가 가장 흔한 보안 사고의 원인입니다.

최소 권한 원칙 — 공유 시나리오별 권한 매트릭스

공유 시나리오별 권한 매트릭스

시나리오필요 권한권장 방식
읽기 전용 공유s3:GetObject, s3:ListBucket (특정 Prefix)IAM 정책 + Prefix 제한
특정 파일 공유 (Pre-signed)s3:GetObject (지정된 Key만)Pre-signed URL + 시간 제한
분석용 공유 (Access Point)s3:GetObject, s3:ListBucket, s3:GetObjectAclAccess Point 정책
쓰기 포함 공유 (양방향)s3:GetObject, s3:PutObject, s3:DeleteObject지정된 Prefix만
구독 데이터 (Data Exchange)s3:GetObject, athena:StartQueryExecution, glue:Get*구독한 데이터셋만
최소 권한 IAM 정책 예시 (읽기 전용 공유) — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "ListSpecificPrefix", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::shared-data-bucket", "Condition": { "StringLike": { "s3:prefix": ["analytics/public/*"] } } }, { "Sid": "ReadSpecificPrefix", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::shared-data-bucket/analytics/public/*" } ] } ```

이 정책은 analytics/public/ 경로 아래만 조회할 수 있으며, 다른 경로는 존재 자체를 알 수 없습니다.


버킷 정책 6가지 패턴

버킷 정책은 조건(Condition) 키를 조합해 세밀한 접근 제어를 구현합니다. 6가지 패턴을 상황에 맞게 선택하거나 조합합니다.

버킷 정책 6가지 패턴 분류

패턴 1: 계정 기반 허용

특정 AWS 계정에만 읽기 권한을 부여합니다. aws:PrincipalAccount 조건 키로 계정을 식별합니다.

  • 언제 쓰나 — 파트너사 계정, 자회사 계정과 데이터를 공유할 때
  • 주의점 — 상대 계정의 IAM 정책도 별도로 허용해야 실제 접근 가능
패턴 1: 계정 기반 읽기 허용 정책 — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSpecificAccountRead", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:root" }, "Action": ["s3:GetObject", "s3:GetObjectVersion"], "Resource": "arn:aws:s3:::shared-data-bucket/*", "Condition": { "StringEquals": { "aws:PrincipalAccount": "999999999999" } } }, { "Sid": "AllowSpecificAccountList", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:root" }, "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::shared-data-bucket", "Condition": { "StringLike": { "s3:prefix": "shared/*" } } } ] } ```

패턴 2: VPC 엔드포인트만 허용

특정 VPC에서만 접근을 허용합니다. aws:SourceVpce 조건 키로 특정 VPC 엔드포인트를 통한 요청만 허용합니다.

VPC 엔드포인트 기반 접근 제어 구조

  • 언제 쓰나 — 사내 네트워크나 특정 VPC 내 EC2/ECS만 접근해야 할 때
  • 주의점 — Deny 문에 aws:ViaAWSService: false를 추가해 AWS 서비스(복제, Lambda 등)는 예외 처리해야 합니다
패턴 2: VPC 엔드포인트만 허용 + 외부 Deny — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowVPCAccessOnly", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:GetObjectVersion"], "Resource": "arn:aws:s3:::shared-data-bucket/*", "Condition": { "StringEquals": { "aws:SourceVpce": "vpce-1a2b3c4d5e6f7g8h9" } } }, { "Sid": "DenyNonVPCAccess", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::shared-data-bucket", "arn:aws:s3:::shared-data-bucket/*" ], "Condition": { "StringNotEquals": { "aws:SourceVpce": "vpce-1a2b3c4d5e6f7g8h9" }, "Bool": { "aws:ViaAWSService": "false" } } } ] } ```

패턴 3: IP 기반 허용

특정 IP 범위에서만 접근을 허용합니다. aws:SourceIpNotIpAddress를 조합해 허용 IP 외 요청을 명시적으로 차단합니다.

  • 언제 쓰나 — 사무실 고정 IP, VPN 대역만 허용할 때
  • 주의점 — VPC 엔드포인트를 통한 내부 트래픽은 공인 IP가 없으므로 패턴 2와 병행 필요
패턴 3: IP 기반 접근 제한 정책 — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowOfficeIPOnly", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::shared-data-bucket", "arn:aws:s3:::shared-data-bucket/*" ], "Condition": { "IpAddress": { "aws:SourceIp": ["203.0.113.0/24", "198.51.100.0/24"] } } }, { "Sid": "DenyAllOtherIPs", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::shared-data-bucket", "arn:aws:s3:::shared-data-bucket/*" ], "Condition": { "NotIpAddress": { "aws:SourceIp": ["203.0.113.0/24", "198.51.100.0/24"] }, "Bool": { "aws:ViaAWSService": "false" } } } ] } ```

패턴 4: 시간 기반 허용

업무 시간에만 접근을 허용합니다. aws:CurrentTimeDateGreaterThan/DateLessThan으로 시간 범위를 지정합니다.

  • 언제 쓰나 — 야간/주말 자동화 작업을 차단하거나, 임시 접근 기간을 설정할 때
  • 주의점 — KST가 아닌 UTC 기준이므로 변환 필요 (KST 09:00-18:00 = UTC 00:00-09:00)
패턴 4: 시간 기반 접근 제한 정책 — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowBusinessHoursOnly", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:root" }, "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::shared-data-bucket", "arn:aws:s3:::shared-data-bucket/*" ], "Condition": { "DateGreaterThan": { "aws:CurrentTime": "2026-01-01T00:00:00Z" }, "DateLessThan": { "aws:CurrentTime": "2026-12-31T23:59:59Z" } } } ] } ```

패턴 5: 태그 기반 허용

리소스 태그나 보안 주체 태그로 접근을 제어합니다. ABAC(Attribute-Based Access Control) 방식으로, 환경(env=prod)이나 부서(team=data) 태그로 분류합니다.

  • 언제 쓰나 — 개발/운영 환경 분리, 부서별 데이터 접근 제어
  • 장점 — 새 리소스 추가 시 정책 변경 없이 태그만 부여하면 됨

패턴 6: 복합 조건

위 패턴들을 AND로 조합합니다. 예를 들어 “특정 역할 + 특정 VPC + TLS 전송”을 모두 만족해야 허용합니다.

패턴 6: 복합 조건 (역할 + VPC + TLS + Prefix) — 전체 보기 ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "CompoundConditionAccess", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:role/DataAnalystRole" }, "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::shared-data-bucket", "arn:aws:s3:::shared-data-bucket/analytics/*" ], "Condition": { "Bool": { "aws:SecureTransport": "true" }, "StringEquals": { "aws:SourceVpce": "vpce-1a2b3c4d5e6f7g8h9" }, "StringLike": { "s3:prefix": "analytics/*" }, "NumericLessThan": { "s3:max-keys": "1000" } } } ] } ```

Block Public Access

S3 Block Public Access는 의도치 않은 공개 접근을 방지하는 계정/버킷 수준의 안전망입니다. 실수로 공개 ACL이나 정책을 설정해도 접근을 원천 차단합니다.

Block Public Access 설정 계층

4가지 설정 항목

설정역할
BlockPublicAclsACL을 통한 공개 접근 차단
IgnorePublicAcls기존 공개 ACL 무시
BlockPublicPolicy공개 버킷 정책 적용 차단
RestrictPublicBuckets공개 정책이 있는 버킷 제한

적용 계층

Block Public Access는 4개 수준에서 적용할 수 있으며, 상위 수준이 하위 수준보다 우선합니다.

수준범위권장
Account계정 내 모든 버킷무조건 켜기
Bucket개별 버킷기본값 유지
Organization조직 전체 (SCP)조직 규칙으로 강제
Region리전별리전 격리 시 활용
# 계정 수준 Block Public Access 활성화
aws s3control put-public-access-block \
    --account-id 123456789012 \
    --public-access-block-configuration \
    BlockPublicAcls=true,IgnorePublicAcls=true,\
BlockPublicPolicy=true,RestrictPublicBuckets=true

원칙: 계정 수준에서 4가지 설정 모두 활성화 → 공개 데이터셋이 필요한 경우에만 버킷 수준에서 선택적 해제. 공개 버킷은 전용 계정에서 격리 운영하는 것이 안전합니다.


암호화와 공유

S3 암호화 방식에 따라 데이터 공유 방법이 달라집니다. 어떤 암호화를 썼느냐에 따라 소비자가 추가 권한이 필요할 수 있습니다.

S3 암호화 방식 비교와 공유 영향

암호화 방식 비교

방식키 관리공유 영향권장 용도
SSE-S3AWS 완전 관리없음 (소비자 추가 권한 불필요)공유 데이터 기본 암호화
SSE-KMS고객 관리 CMK소비자 KMS 권한 필요 ⚠️민감 데이터 공유
SSE-C고객 제공 키키를 소비자에게 별도 전달최고 수준 제어 필요 시
CSE클라이언트복호화 키 별도 채널 공유엄격한 규제 요건

SSE-KMS 공유 흐름

SSE-KMS로 암호화된 데이터를 타 계정과 공유하려면, KMS 키 정책에 소비자 계정을 명시적으로 허용해야 합니다. 소비자 측 IAM 정책에도 KMS 사용 권한이 필요합니다.

SSE-KMS 공유 흐름 — 5단계

공유 흐름은 5단계로 진행됩니다.

  1. 제공자 → KMS: 키 정책에 소비자 계정 추가
  2. 소비자 IAM: kms:Decrypt 권한 추가
  3. 소비자 → S3: GetObject 요청
  4. S3 → KMS: 데이터 키 복호화
  5. S3 → 소비자: 복호화된 데이터 반환
KMS 키 정책: 소비자 계정 복호화 허용 — 전체 보기 ```json { "Sid": "AllowConsumerAccountToDecrypt", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::999999999999:root" }, "Action": [ "kms:Decrypt", "kms:DescribeKey", "kms:GenerateDataKey" ], "Resource": "*" } ``` 소비자 IAM 정책에는 `kms:Decrypt`와 `s3:GetObject`를 함께 부여해야 합니다. KMS 권한이 없으면 객체를 받아도 복호화하지 못해 AccessDenied가 발생합니다.

감사 및 모니터링

데이터 공유 환경에서 접근 감사와 모니터링은 필수입니다. 누가 언제 무엇에 접근했는지 추적할 수 있어야 사고 발생 시 대응할 수 있습니다.

S3 감사 및 모니터링 아키텍처

3종 감사 도구

도구추적 대상특징
CloudTrail모든 S3 API 이벤트데이터 이벤트(GetObject 등) + 관리 이벤트(CreateBucket 등)
S3 Access Logs모든 요청 상세 로그요청자 IP, 시간, 응답 코드, 바이트 수
Amazon Macie민감 데이터 자동 탐지PII, PHI 식별, 공유 전/후 노출 방지

추가로 AWS Config로 버킷 설정 변경 추적과 암호화/공개 설정 규칙 준수 여부를 모니터링합니다.

Athena로 access log 쿼리하기

CloudTrail 로그는 Athena로 직접 쿼리해 의심스러운 접근을 탐지할 수 있습니다. 아래 쿼리는 외부 계정의 GetObject/ListBucket 접근을 시간순으로 조회합니다.

Athena로 CloudTrail 로그 쿼리 (외부 계정 접근 탐지) — 전체 보기 ```sql SELECT eventtime, useridentity.arn AS requester, eventname, requestparameters, sourceipaddress, awsregion FROM cloudtrail_logs WHERE eventsource = 's3.amazonaws.com' AND ( eventname = 'GetObject' OR eventname = 'ListBucket' ) AND useridentity.accountid != '123456789012' AND eventtime >= '2026-06-01T00:00:00Z' ORDER BY eventtime DESC; ```

이 쿼리를 정기 실행하도록 예약하고, 결과를 알림(SNS/Slack)으로 연동하면 비인가 접근을 실시간으로 감지할 수 있습니다.


보안 체크리스트

S3 보안 모범 사례 체크리스트 10가지

#항목확인 방법위험도
1Block Public Accesss3-bucket-level-public-access-prohibited Config 규칙🔴 High
2최소 권한 원칙IAM Access Analyzer 검토🔴 High
3암호화 적용aws s3api get-bucket-encryption🟠 Medium
4버전 관리 활성화aws s3api get-bucket-versioning🟡 Low
5MFA Delete버킷 버전 관리 설정 확인🟠 Medium
6Access Point 활용Access Point 정책 검토🟡 Low
7Pre-signed URL 만료 시간URL 생성 코드 리뷰 (1시간 이내)🟠 Medium
8CloudTrail 데이터 이벤트CloudTrail 이벤트 기록 확인🔴 High
9정기 보안 평가Macie 발견 결과 + Config Rules🟠 Medium
10IAM 역할 분리관리/소비/감사 역할 분리🔴 High

Takeaway

  1. 보안은 하나의 계층으로 충분하지 않다 — 7계층 다층 방어가 기본입니다. 한 계층이 뚫려도 다음 계층이 막아주도록 설계해야 합니다
  2. Block Public Access는 무조건 켜세요 — 계정 수준에서 4가지 설정 모두 활성화하면 실수로 인한 유출을 원천 차단합니다
  3. SSE-KMS + CloudTrail + Macie 3종 세트 — 암호화, 감사, 민감 정보 탐지를 한 번에 갖추면 사고 예방과 추적이 모두 가능합니다

S3 시리즈 4/7

  
S3 Access Grants와 복제로 대규모 데이터 공유하기 
 S3 데이터 공유 아키텍처 — 6가지 패턴과 선택 가이드
HeonJe Lee | 선임연구원
게이트웨이 On-promise 제품 팀에서 시스템 모니터링 및 관리를 쉽게 다가갈 수 있도록 하기 위한 업무를 하고 있습니다.

Contact: lhjnano@gmail.com

Search

    Table of Contents