- Published on
AWS S3 보안
- Authors
- Name
- Chan Sol OH
목차
- 객체 암호화
- SSE-KMS 주의점
- 전송 중 암호화
- 강제로 전송 중 암호화
- S3의 CORS
- MFA Delete
- S3 Access Logs
- 사전 서명된 URL (Pre-Signed URLs)
- S3 Access Points
- 프라이빗 액세스를 가능하도록 만들기
- S3 Object Lambda
이번 포스팅은 AWS S3 (1)과 AWS S3(2)에 이어서 S3의 보안에 관련된 내용을 다룬다.
객체 암호화
AWS S3는 4가지 방법으로 객체를 암호화할 수 있다.
- Server-Side Encryption(SSE) : 서버 측에서 암호화한 다음 S3에 업로드
- SSE-S3 방식은 S3 Managed Keys로 암호화한다. (버킷 기본 설정) AWS에서 암호화 키를 소유하고 관리하기 때문에 사용자는 키에 접근할 수 없다. 또한 헤더에
"X-amz-server-side-encryption":"AES256"
을 설정해야한다. - SSE with KMS는 AWS KMS로 객체를 암호화. Key Mangement Service(KMS) 서비스를 사용해 키와 사용자의 키 사용을 감시한다. 만약 누군가가 KMS에서 키를 사용하면 CloudTrail 서비스에 로그가 남는다.
CloudTrail
은 AWS에서 일어나는 모든 일을 로그로 남긴다. 또한 헤더에"x-amz-server-side-encryption":"aws:kms"
를 설정해야한다. - SSE with Customer-provided Keys (SSE-C) 사용자가 직접 암호화 키를 제공. 키는 외부에서 관리되지만 서버에서 암호화를 진행하기 때문에 SSE에 포함된다. AWS는 사용자의 키를 사용 후 폐기한다. HTTPS 통신을 사용해야 하며, 모든 HTTP 요청의 헤더에 키를 전달해야 한다.
- SSE-S3 방식은 S3 Managed Keys로 암호화한다. (버킷 기본 설정) AWS에서 암호화 키를 소유하고 관리하기 때문에 사용자는 키에 접근할 수 없다. 또한 헤더에
- Client-Side Encryption(CSE) : 클라이언트 측에서 암호화한 다음 S3에 업로드. 클라이언트 측에서 자체적인 암호화 라이브러리를 사용하면 데이터를 직접 암호화하고 S3에 전송한다. 당연히 복호화는 S3 외부 클라이언트에서 수행한다.
SSE-KMS 주의점
SSE-KMS는 S3에 파일을 업로드하거나 다운로드할 때 KMS 키를 활용해야한다. 또한 KMS는 자체 API가 있어서 키를 불러올 때 GenerateDataKey
키 요청이나 Decrypt
같이 복호화 API를 요청해야한다. 이러한 KMS API 호출은 리전에 따라 초당 5,000 ~ 30,000회의 요청을 처리하도록 제한되어 있다. 그렇기 때문에 객체가 매우매우 많을 경우 KMS 키를 사용하여 모든 것이 암호화되므로 주의해야한다.
전송 중 암호화
HTTP 통신에서 전송 중 암호화는 SSL 혹은 TLS라고 한다. 기본적으로 S3에는 HTTP Endpoint와 HTTPS Endpoint가 존재한다.
따라서 S3를 사용할 때 데이터를 안전하게 전송하기 위해서 HTTPS를 사용하기를 권장한다. 또한 사용자의 암호화 키가 네트워크 올라가는 SSE-C 방식은 HTTPS 프로토콜 사용이 필수이다.
강제로 전송 중 암호화
S3 버킷에 버킷 정책을 추가하고 Statement에 "aws:SecureTransport가 false
일 때 모든 GetObject
Action을 Deny
한다"고 작성하면, 무조건 버킷에 객체를 업로드할 때 전송 중 암호화를 강제할 수 있다.
S3의 CORS
CORS는 교차 오리진 리소스 공유이다. 예를 들어 https://www.example.com
을 보면 암시적 포트는 https에대해 443이며 도메인은 **www.example.com**이다. CORS는 기본 오리진에 방문할 때 다른 오리진에 대한 요청을 허용하거나 거부하는 웹 브라우저 기반 보안 메커니즘
동일한 체계, 동일 호스트, 동일 포트가 있는 동일한 오리진을 고유하는 두개의 URL가 있는 반면, www.example.com
이나 other.example.com
같이 다른 오리진의 URL이 있을 수 있다. 다른 오리진의 웹 서버가 CORS 정책을 설정하여 CORS 헤더에 알려주지 않는다면 기본적으로 브라우저는 요청을 하지 않는다.
클라이언트가 S3 버킷에 교차 오리진 요청을 보낼 경우 올바른 CORS 헤더를 활성화해야한다. 이를 해결하기 위해 S3는 특정 오리진을 허용하거나 *을 통해 모든 오리진의 요청을 허가해야한다.
예를 들어 S3 버킷으로 정적 웹 사이트가 배포되어 www.example.com
웹사이트에 접속했다. 그리고 다른 S3 버킷인 other.example.com
에 있는 이미지를 www.example.com
에서 얻으려고 한다. 두 URL은 오리진이 다르기 때문에 교차 오리진 요청이 되고, S3 버킷이 올바른 CORS 헤더를 갖도록 구성되어 있지 않으면 요청을 거부하게 된다.
MFA Delete
MFA는 이전 포스팅에서도 나왔듯이 멀티 팩터 인증을 나타낸다. 이는 사용자가 컴퓨터가 아닌 다른 디바이스에서 받은 코드를 작성해 인증하는 방법이다. 따서 MFA가 활성화된 상태에서는 작업 전에 AWS S3에 입력해야한다. 다음과 같은 상황에서 MFA를 사용한다.
- 객체를 영구적으로 삭제할 때
- 버킷에 버전 관리를 일시 중단하려는 경우
위 두 경우 모드 객체의 원본에 영향을 미치기 때문에 MFA가 필요하다. 다만 버전 관리 시작이나 삭제된 객체 나열 같은 작업은 원본에 영향을 주는 행위가 아니기 때문에 MFA가 필요없다.
MFA Delete를 위해선 객체의 버전을 사용하기 때문에 버킷에 버전 관리 활성화가 필수이고, 오직 버킷의 **주인(root 계정)**만 MFA Delete가 가능하다. MFA Delete의 목적은 특정 객체 버전이 영구적으로 삭제되지 않도록 하는 추가 보호이다.
S3 Access Logs
감사를 위해, S3 버킷의 모든 액세스를 기록해야할 수 있다. 즉, 모든 계정에서 S3에 보낸 승인 또는 거절된 모든 요청을 다른 S3 버킷에 저장한다. 이러한 데이터는 Amazon Athena와 같은 데이터 분석 도구를 사용하여 분석할 수 있다. 하지만, 로깅하는 버킷들은 동일한 리전에 있어야한다. 모니터링 버킷과 로깅 버킷은 동일한 버킷을 사용하면 안된다. 무한한 로깅 루프가 생길 수 있기 때문!
사전 서명된 URL (Pre-Signed URLs)
사전 서명된 URL은 AWS CLI 또는 SDK를 사용해 생성할 수 있는 URL이며 만료기한이 있다. 만료기한은 S3 콘솔을 사용하는 경우 12시간이며 CLI를 사용하는 경우 168시간까지이다. 사전 서명된 URL은 미리 서명한 사용자의 권한이 URL에 상속되기 때문에 그 URL을 이용한 요청은 GET이든 PUT이든 사용자 권한 내에서 요청할 수 있다.
예를 들어 Private S3 버킷이 있는데 버킷을 Public으로 만들지 않고, 사전 서명된 URL을 공유해서 일시적으로 객체나 버킷을 Public과 유사한 상태로 만들 수 있다.
실제 예로는 로그인한 사용자만 S3 버킷에 있는 프리미엄 비디오를 다운로드할 수 있도록 하거나, URL을 동적으로 생성하여 파일을 다운로드할 사용자의 목록을 계속 변경되도록 하거나, S3 버킷을 Private으로 유지하면서 일시적으로 S3 버킷의 구체적인 위치에 사용자가 파일을 업로드하도록 하는 것이 있다.
S3 Access Points
많은 데이터가 저장된 S3 버킷이 있을 때, 데이터에 접근하고자하는 여러 그룹들이 있을 때, 매우 복잡한 S3 버킷 정책으로 관리되고, 사용자가 많아지고. 데이터가 많아질수록 점점 관리할 수 없게된다. 이때 Access Points를 사용할 수 있다.
관리자는 S3 정책과 매우 비슷하고 접두사에 대한 액세스 포인트 정책을 정의한다. 이처럼 각 Access Points 마다 다른 정책을 부여해서 하나의 S3 버킷 정책을 관심사의 분리한 것으로 볼 수 있다.
각 정책에 맞는 IAM 권한을 가진 그룹만 해당 Access Points를 접근할 수 있다. 따라서 각각의 DNS 이름이 존재하는 Access Points를 액세스 포인트 정책으로 관리하기 때문에 스케일러블하게 S3 버킷을 관리할 수 있다.
프라이빗 액세스를 가능하도록 만들기
특정 액세스 포인트의 VPC 오리진의 경우 프라이빗 액세스로 정의할 수 있다. VPC 내부에 있는 EC2 인스턴스가 S3 버킷의 Access Point에 접근하기 위해선 VPC 내부에 VPC Endpoint를 생성하고 VPC Origin을 통해 액세스 포인트에 Private하게 접근하는 방법이다. 또한 VPC Endpoint 정책은 허가 대상 버킷과 액세스 포인트가 적혀있다. 따라서 VPC Endpoint 정책을 사용하면 VPC와 S3 버킷의 액세스 포인트를 연결할 수 있다.
따라서 인스턴스가 S3 버킷의 액세스 포인트로 접근하기 위해선 액세스 포인트의 정책, Endpoint 정책, 그리고 버킷 정책을 지나야한다.
S3 Object Lambda
S3 액세스 포인트의 또 다른 활용 사례는 S3 Object Lambda이다. 즉 사용자 요청으로 객체를 응답하기 전에 AWS Lambda Functions를 사용하여 사전 작업을 수행할 수 있다.
분석 서버는 S3 Object Lambda 액세스 포인트에 액세스하고 이는 람다함수를 작동시킨다. 람다함수는 S3 버킷에서 데이터를 검색하고 코드를 실행해 데이터를 편집한다. 따라서 분석 서버는 배포 서버와 동일한 S3 버킷에서 편집된 객체를 확보한다.
정리하면 하나의 S3 버킷으로 서버의 목적에 따라 람다함수로 객체를 편집해서 제공할 수 있다. 이 과정에서 다른 S3 버킷을 람다함수가 사용해서 데이터를 보강할 수도 있다.
실제 예로는 XML을 JSON으로 데이터 형식을 변환하는 경우, 이미지 크기를 조정하고 워터마크를 추가하는 등의 작업을 람다함수에게 요청할 수 있다.