Chapter 09

S3 버킷 보안

"S3 버킷의 문은 필요한 만큼만 열어두자"

학습 목표

  • S3 버킷의 보안 계층(퍼블릭 액세스 차단, 버킷 정책, CORS, 버전 관리)을 이해할 수 있다
  • S3 버킷 정책을 확인하고 최소 권한 원칙이 적용되어 있는지 점검할 수 있다
  • S3 버전 관리를 활성화하여 데이터를 보호할 수 있다
  • S3 액세스 로깅의 개념과 필요성을 이해할 수 있다
Chapter 09 - S3 버킷 보안 아키텍처
사용자 (브라우저)
이미지 조회 / 프론트엔드 접속
↓ HTTPS 요청
S3: shopeasy-images
uploads/* 만 퍼블릭 읽기
퍼블릭 액세스 차단: 해제
버킷 정책으로 제어
S3: shopeasy-frontend
정적 웹 호스팅
모든 객체 읽기 허용
(GetObject only)
↓ 보안 강화
보안 계층
퍼블릭 액세스 차단 | 버킷 정책 | CORS | 버전 관리 | 액세스 로깅

S3 버킷 보안 계층

비유로 이해하기: S3 버킷 = 창고

S3 버킷을 창고라고 생각해 보세요.

  • 퍼블릭 액세스 차단 = 창고 외벽의 출입문 잠금장치. 이것이 잠겨 있으면 안쪽에서 아무리 문을 열어도 외부인이 들어올 수 없습니다.
  • 버킷 정책 = 창고 안의 각 방에 대한 출입 규칙. "1번 방(uploads/)은 누구나 열람 가능, 2번 방은 직원만 가능"처럼 세밀하게 제어합니다.
  • CORS = 외부 건물(다른 도메인)에서 온 사람이 이 창고의 물건을 볼 수 있는지에 대한 규칙
  • 버전 관리 = 창고에 보관된 서류가 수정될 때마다 이전 버전을 자동으로 보관하는 시스템. 실수로 덮어쓰거나 삭제해도 복구 가능
  • 액세스 로깅 = 창고 출입 기록부. 누가, 언제, 어떤 물건에 접근했는지 기록

현재 ShopEasy의 이미지 버킷은 외벽 출입문이 열려 있고(퍼블릭 액세스 차단 해제), 버킷 정책으로 uploads/* 경로만 공개하고 있습니다. 이번 챕터에서는 추가 보안 계층을 적용하여 더 안전하게 만들겠습니다.

S3 보안의 4가지 계층

보안 계층 역할 ShopEasy 현재 상태
퍼블릭 액세스 차단 버킷 전체의 퍼블릭 접근을 일괄 차단/허용하는 최상위 스위치 이미지 버킷: 4개 모두 해제 (버킷 정책이 작동하려면 필요)
버킷 정책 JSON으로 정의하는 세밀한 접근 규칙 (누가, 무엇을, 어디에) 이미지 버킷: uploads/*만 GetObject 허용
CORS 브라우저에서 다른 도메인의 리소스에 접근할 때의 허용 규칙 이미지 버킷: GET/PUT/POST 허용 (Chapter 05에서 설정)
버전 관리 객체의 모든 버전을 보관하여 실수로 인한 삭제/덮어쓰기 방지 미설정 (이번 챕터에서 활성화)
퍼블릭 액세스 차단과 버킷 정책의 관계

S3의 퍼블릭 액세스 차단은 일종의 "마스터 스위치"입니다. 이것이 켜져 있으면 버킷 정책에서 아무리 공개 설정을 해도 차단됩니다.

  • 퍼블릭 액세스 차단 ON + 버킷 정책 공개 = 차단됨 (마스터 스위치가 우선)
  • 퍼블릭 액세스 차단 OFF + 버킷 정책 공개 = 공개됨 (버킷 정책 적용)
  • 퍼블릭 액세스 차단 OFF + 버킷 정책 없음 = 비공개 (기본 비공개)

이미지 버킷은 uploads/* 경로를 브라우저에서 직접 접근해야 하므로 퍼블릭 액세스 차단을 해제하고, 버킷 정책으로 세밀하게 제어하는 방식을 사용합니다.

ShopEasy S3 현재 상태

Chapter 05에서 생성한 두 개의 S3 버킷이 현재 다음 상태로 운영 중입니다.

1. 이미지 버킷: shopeasy-images-{ACCOUNT_ID}

설정 항목 현재 값 상태
퍼블릭 액세스 차단 4개 항목 모두 해제 (OFF) 의도적 - 버킷 정책이 작동하려면 필요
버킷 정책 uploads/* 경로만 s3:GetObject 허용 양호 - 최소 경로만 공개
CORS GET/PUT/POST 허용 양호 - 브라우저 업로드 지원
버전 관리 비활성화 개선 필요 - 실수로 삭제 시 복구 불가

2. 프론트엔드 버킷: shopeasy-frontend-{ACCOUNT_ID}

설정 항목 현재 값 상태
퍼블릭 액세스 차단 4개 항목 모두 해제 (OFF) 의도적 - 정적 웹 호스팅에 필요
버킷 정책 모든 객체 s3:GetObject 허용 점검 필요 - 쓰기 권한이 없는지 확인
정적 웹 호스팅 활성화 양호
이번 챕터에서 할 일

현재 구성은 기본적으로 잘 되어 있지만, 보안을 더 강화할 수 있습니다. 이번 실습에서는 다음을 수행합니다:

  1. 이미지 버킷의 버킷 정책이 uploads/*만 공개하는지 재확인
  2. 이미지 버킷에 버전 관리를 활성화하여 실수 방지
  3. 프론트엔드 버킷이 읽기 전용인지 점검 (쓰기 권한 없는지)
  4. S3 액세스 로깅 개념 이해

버전 관리(Versioning)란?

비유로 이해하기: 버전 관리 = 자동 백업 시스템

문서 작업을 할 때 "보고서_v1.docx", "보고서_v2.docx"처럼 버전을 따로 저장하는 것을 떠올려 보세요. S3 버전 관리는 이것을 자동으로 해줍니다. 같은 이름의 파일을 덮어쓰면 이전 버전이 자동으로 보관되고, 파일을 삭제해도 "삭제 마커"만 추가될 뿐 실제 데이터는 남아있어 복구할 수 있습니다.

버전 관리의 장점

상황 버전 관리 OFF 버전 관리 ON
같은 이름으로 파일 업로드 (덮어쓰기) 이전 파일 영구 삭제 이전 버전 보관, 복구 가능
파일 실수로 삭제 영구 삭제, 복구 불가 삭제 마커만 추가, 이전 버전 복구 가능
악의적인 삭제/변조 데이터 유실 이전 버전에서 복구 가능
버전 관리 비용

버전 관리를 활성화하면 모든 버전이 저장되므로 스토리지 비용이 증가할 수 있습니다. 수명 주기 정책(Lifecycle Policy)을 설정하여 오래된 버전을 자동 삭제하면 비용을 관리할 수 있습니다. 하지만 리뷰 이미지처럼 중요한 사용자 데이터는 버전 관리를 활성화하는 것이 좋습니다.

S3 액세스 로깅이란?

서버 액세스 로깅 (Server Access Logging)

S3 서버 액세스 로깅은 버킷에 대한 모든 접근 요청을 기록하는 기능입니다. 누가, 언제, 어떤 객체에, 어떤 작업(GET/PUT/DELETE)을 했는지 로그로 남깁니다.

  • 보안 감사: 비정상적인 접근 패턴을 탐지할 수 있습니다
  • 비용 분석: 어떤 객체가 많이 요청되는지 파악할 수 있습니다
  • 문제 해결: 403/404 에러의 원인을 추적할 수 있습니다

로그는 별도의 로깅 전용 버킷에 저장됩니다. 소스 버킷과 로깅 버킷은 같은 리전에 있어야 하며, 로깅 버킷에 적절한 권한이 설정되어야 합니다.

이번 실습에서는

액세스 로깅을 활성화하려면 별도의 로깅 버킷을 생성해야 합니다. 이번 실습에서는 액세스 로깅의 개념과 설정 방법을 이해하는 것을 목표로 합니다. 실제 활성화는 선택 사항입니다.

실습: S3 버킷 보안 강화

사전 준비
  • Chapter 05에서 생성한 S3 이미지 버킷(shopeasy-images-{ACCOUNT_ID})이 존재해야 합니다
  • Chapter 06에서 생성한 S3 프론트엔드 버킷(shopeasy-frontend-{ACCOUNT_ID})이 존재해야 합니다
  • AWS 계정 ID를 확인해 두세요 (콘솔 우측 상단 클릭 또는 aws sts get-caller-identity)
Hands-on Lab
  1. S3 이미지 버킷 정책 확인

    이미지 버킷의 버킷 정책이 올바르게 설정되어 있는지 확인합니다.

    • 현재 버킷 정책을 조회합니다
    • Resourcearn:aws:s3:::shopeasy-images-{ACCOUNT_ID}/uploads/*인지 확인합니다
    • Actions3:GetObject(읽기 전용)인지 확인합니다
    • Resource/*(전체 공개)가 아닌 /uploads/*(제한적 공개)인지 반드시 확인합니다
    왜 이 확인이 중요한가?

    버킷 정책에서 Resourcearn:aws:s3:::shopeasy-images-{ACCOUNT_ID}/*로 되어 있으면 버킷의 모든 파일이 공개됩니다. 반드시 /uploads/*로 제한되어 있어야 다른 경로의 파일(설정 파일, 로그 등)이 노출되지 않습니다.

    AWS 콘솔: S3 → shopeasy-images-{ACCOUNT_ID} 버킷 → 권한 탭 → 버킷 정책 섹션에서 JSON을 확인합니다.

    또는 AWS CLI를 사용하여 버킷 정책을 조회할 수 있습니다.

  2. S3 이미지 버킷 버전 관리 활성화

    이미지 버킷에 버전 관리를 활성화하여 실수로 인한 데이터 손실을 방지합니다.

    • 현재 버전 관리 상태를 확인합니다 (비활성화 상태일 것입니다)
    • 버전 관리를 활성화(Enabled)합니다
    • 활성화 후 상태가 Enabled로 변경되었는지 확인합니다
    버전 관리 주의사항

    버전 관리를 한 번 활성화하면 비활성화(Disabled)로 되돌릴 수 없습니다. "중지(Suspended)" 상태로만 변경할 수 있으며, 이 경우 새 버전 생성은 중단되지만 기존 버전은 그대로 유지됩니다.

    AWS 콘솔: S3 → shopeasy-images-{ACCOUNT_ID} 버킷 → 속성 탭 → 버킷 버전 관리 섹션 → 편집 → 활성화 선택 → 저장

    또는 AWS CLI의 put-bucket-versioning 명령을 사용할 수 있습니다.

  3. S3 프론트엔드 버킷 보안 점검

    프론트엔드 버킷의 버킷 정책을 확인하여 보안 상태를 점검합니다.

    • 프론트엔드 버킷의 버킷 정책을 조회합니다
    • Actions3:GetObject(읽기)만 허용하는지 확인합니다
    • s3:PutObject, s3:DeleteObject 등 쓰기/삭제 권한이 없는지 확인합니다
    • 만약 쓰기 권한이 포함되어 있다면, 이는 보안 위험입니다 - 외부 사용자가 웹사이트 파일을 변조할 수 있습니다
    프론트엔드 버킷이 읽기 전용이어야 하는 이유

    프론트엔드 버킷은 정적 웹사이트 호스팅용입니다. 사용자의 브라우저에서는 HTML, CSS, JS 파일을 다운로드(읽기)만 하면 됩니다. 만약 PutObject(쓰기) 권한이 공개되어 있으면, 누구나 웹사이트 파일을 바꿔치기할 수 있어 웹사이트 변조 공격의 대상이 됩니다.

    AWS 콘솔: S3 → shopeasy-frontend-{ACCOUNT_ID} 버킷 → 권한 탭 → 버킷 정책 섹션에서 JSON을 확인합니다.

    또는 AWS CLI를 사용하여 버킷 정책을 조회할 수 있습니다. Action 필드에 s3:GetObject만 있어야 합니다.

  4. S3 액세스 로깅 확인

    S3 서버 액세스 로깅의 개념을 이해하고, 설정 방법을 확인합니다.

    • S3 서버 액세스 로깅이 어떤 정보를 기록하는지 이해합니다
    • 이미지 버킷의 현재 로깅 설정 상태를 확인합니다
    • (선택) 로깅을 활성화하려면 별도의 로깅 버킷이 필요합니다
    S3 액세스 로그 예시

    S3 서버 액세스 로그에는 다음과 같은 정보가 기록됩니다:

    text
    # S3 액세스 로그 형식 (한 줄 요약)
    79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be \
      shopeasy-images-123456789012 [06/Feb/2025:00:00:38 +0000] \
      192.0.2.3 - ... REST.GET.OBJECT uploads/review-001.jpg \
      "GET /uploads/review-001.jpg HTTP/1.1" 200 - 12345 ...
    로그에서 확인할 수 있는 정보
    • 요청자 IP: 누가 접근했는지
    • 시간: 언제 접근했는지
    • 작업: GET(읽기), PUT(쓰기), DELETE(삭제) 등
    • 대상 객체: 어떤 파일에 접근했는지
    • HTTP 상태 코드: 성공(200), 거부(403), 없음(404) 등

    AWS 콘솔: S3 → shopeasy-images-{ACCOUNT_ID} 버킷 → 속성 탭 → 서버 액세스 로깅 섹션에서 현재 상태를 확인합니다.

    액세스 로깅을 활성화하려면 로그를 저장할 별도 버킷(예: shopeasy-logs-{ACCOUNT_ID})을 먼저 생성해야 합니다. 이번 실습에서는 개념 이해가 목표이므로 활성화는 선택 사항입니다.

확인 사항

아래 항목을 모두 완료했는지 체크하세요:

  • 이미지 버킷의 버킷 정책에서 Resource/uploads/*로 제한되어 있음을 확인했다
  • 이미지 버킷의 버킷 정책에서 Actions3:GetObject(읽기 전용)임을 확인했다
  • 이미지 버킷의 버전 관리가 Enabled 상태로 활성화되었다
  • 프론트엔드 버킷의 버킷 정책에서 Actions3:GetObject(읽기 전용)임을 확인했다
  • 프론트엔드 버킷에 쓰기/삭제 권한이 공개되어 있지 않음을 확인했다
  • S3 서버 액세스 로깅의 개념과 기록되는 정보를 이해했다