S3 - 객체 암호화
객체를 암호화 하는 방법은 4가지가 존재한다.
- Server-Side Encryption (SSE) 서버 암호화
- S3-Managed Keys (SSE - S3) - 버킷과 객체에 default로 활성화된 값이다.
- KMS Keys stored in AWS KMS (SSE-KMS)
- KMS라는 암호화 키를 통해 암호화를 하는 방법이다.
- Customner-Provided Keys (SSE-C)
- 사용자가 제공한 키를 통해 암호화 하는 방법이다.
- Client-side Encryption 클라이언트 측에서 암호화 한 후에 S3에 업로드하는 방식이다.
- 어떤 상황에 무엇을 사용하는지 이해하도록 하자
SSE-S3 방식
- 이 방식에 사용되는 키는 AWS에서 관리하고 소유한다.
- 사용자는 이 키에 접근할 수 없다.
- AWS 서버 측에서 객체를 암호화 한다.
- 암호화 타입은 AES-256이다.
- 헤더에 반드시 x-amz-server-side-encryption : AES256을 명시해줘야 한다.
- 새로운 버킷과 객체에는 기본적으로 SSE S3가 활성화된다.
사용자가 보낸 객체는 키와 결합하여 암호화 된 이후 버킷에 저장된다.
SSE-KMS
- AWS가 관리해주는 키를 사용해는 대신 사용자가 직접 키를 관리하는 방식이다.
- KMS에서 키를 생성하고 유저가 관리할 수 있으며
CloudTrail을 사용하여 감시도 가능하다- 누군가 KMS에서 키를 사용하면 서비스에 로그가 남기에 감시가 가능하다.
- AWS에서 일어나는 모든 일을 로그로 남기는 것을 CloudTrail이라 한다.
- x-amz-server-side-encryption:aws:kms 라는 헤더가 필요하다.
- 그러면 서버측에서 헤더를 보고 암호화 시킨다.
- 버킷에서 파일을 읽으려면 KMS 키에 대한 접근도 가능해야 한다.
- 또 다른 수준의 보안이라 할 수 있다.
SSE-KMS의 한계점
- S3에 파일을 업로드 하거나 다운로드 할 때 KMS 키를 활용해야 한다.
- KMS 키는 자체 API가 존재한다.
- 업로드를 할 때는 GenerateDataKEY 라는 API를 사용해야 한다.
- 복호화 할 때는 DEcrypt API를 사용해야 한다.
- 따라서 KMS 서비스에 API 호출을 해야 업로드와 다운로드가 가능해진다.
- 리전에 따라 초당 5000~30000의 요청을 처리할 수 있다.
- 콘솔에서 서비스 할당량을 늘릴 수 있다.
- 만약 처리량이 아주 많은 버킷이 있다면 KMS를 사용하여 암호화 하는 것은 안 좋다.
- 모든 처리마다 API를 호출해야하기 때문
SSE-C
- 키는 AWS 외부에서 사용자에 의해 관리되지만 서버 측에서 암호화를 한다.
- 사용자가 제공한 키는 아마존에서 절대 저장하지 않는다.
- 사용 후에 폐기한다.
- 아마존에 키를 전송해야하기 때문에 반드시 HTTPS 통신을 사용해야 하며
- 모든 요청 헤더에 키를 포함해야 한다.
- 물론 파일을 읽을 때도 사용자는 다시 키를 전송해야 한다.
Client-Side Encryption
- S3 Client-Side Encryption library를 사용하면 된다.
- 클라이언트 암호화는 클라이언트가 데이터를 직접 암호화한다는 것이다.
- 물론 복호화도 가져와서 클라이언트가 알아서 수행한다.
- 클라이언트가 키, 암호화 주기 전체를 관리해야 한다.
Encrytion in transit (SSL,TLS)
이제 전송 중 암호화를 살펴보자
- S3는 기본적으로 두 개의 엔드포인트가 존재한다.
- HTTP: 암호화 되지 않은 엔드포인트
- HTTPS: 암호화된 엔드포인트
- HTTPS 사용이 권장된다.
- SSE-C 간은 메커니즘을 사용하는 경우엔 HTTPS 사용이 필수다.
- 사용자의 키를 AWS에 보내기 때문이다.
전송 중 암호화를 강제하는 방법
- 버킷 정책을 사용하면 된다.
- Statement에 aws SecureTranport가 false인 경우에 모든 요청을 Deny 하면 된다.
이러면 http의 모든 요청은 거부된다.
S3 기본 암호화 VS 버킷 정책
- 기본적으로 모든 버킷은 기본 암호화인 SSE-S3을 사용한다.
- 이는 자동으로 적용된다.
- SSE-KMS와 같은 다른 암호화로 변경할 수 있다.
- 버킷 정책을 통해 암호화 헤더가 없는 API 호출을 거부하도록 하여
암호화를 강제할 수도 있다.
- 이와 같이 kms 헤더를 사용하고 있지 않다면 모두 deny 할 수도 있다.
- 버킷 정책을 통해서도 암호화 강제가 가능하다.
- 버킷 정책은 항상 암호화 설정보다 먼저 수행된다.
CORS
- 교차 지역 자원 공유란 의미다.
- origin은 프로토콜과 도메인 그리고 포트 번호의 조합을 의미한다.
- 즉 셋 중 하나만 달라도 다른 Origin이다.
- 서로 다른 origin에서 자원을 공유할 때 요청을 허용하거나 거부하는 보안 메커니즘이다.
- 다른 origin으로 자원 요청을 할 때 CORS 헤더를 사용한 요청을 허용해야만 자원을 공유할 수 있다.
S3에서 CORS
- 클라이언트가 S3 버킷에 교차 오리진 요청을 보낼 경우 올바른 CORS 헤더를 활성화해야 한다.
- 이를 빠르게 처리하는 방법은 특정 오리진을 허용하거나
- 모든 오리진을 허용하는 것이다.
S3에서 정적 웹 사이트를 호스팅 중일 때
유저가 해당 웹 사이트에 접근했다. 해당 웹사이트는 밑의 다른 버킷에서 이미지를 가져와 유저에게 보여줘야한다.
이 경우 밑의 버킷에서 위의 버킷에 대한 CORS 설정이 돼있지 않으면 유저는 웹 사이트에 이미지를 띄울 수 없다.
S3 - MFA Delete
MFA delete란 그냥 MFA 사용하는 거다.
S3 버킷에서 객체를 삭제할 때 추가적인 보안을 제공하는 것이다.
- MFA Delete는 언제 필요할까?
- 한 객체의 버전을 영구적으로 삭제하고자 할 때
- 버킷의 버전 관리를 일시 중단하려는 경우에
- 버전관리를 활성화 하거나 삭제된 버전을 나열하고자 하는 경우에는 MFA가 필요하지 않다.
- MFA Delete를 활성화 하려면 버킷 버전 관리가 활성화된 상태여야한다.
- 활성화 및 비활성화는 루트 사용자만 가능하다.
이상한 사람에게 특정 객체 버전이 영구적으로 삭제되지 않도록 하는 추가 보호임을 기억하자
S3 Access Logs
- S3 버킷의 모든 액세스를 로그로 남길 수 있다.
- S3 버킷에 보낸 모든 요청이 승인되든 거부되든 다른 S3 버킷에 파일로 기록된다.
- 그리고 해당 데이터는 Amazon Athena와 같은 데이터 분석 도구를 사용하여 분석할 수 있다.
- 로그가 기록된 로그 버킷은 대상 버킷과 동일한 region에 있어야 한다.
액세스 로그를 다룰 때 주의할 점
- 로깅 버킷을 모니터링 버킷과 동일한 버킷으로 설정해서는 안된다.
- 동일한 버킷을 로깅 버킷으로 설정할 경우 무한 루프에 빠진다.
S3 PreSigned URLs
- S3 콘솔, Cli, SDK 등을 사용해 생성할 수 있으며 만료 기한이 존재한다.
- 콘솔을 사용하는 경우 최대 12시간 유지 가능
- CLi를 사용하는 경우 최대 168시간 유지 가능하다.
- 프라이빗 버킷이 있으며, 외부의 사용자가 해당 버킷에 접근 가능하게 하려고 한다.
- 파일을 퍼블릭으로 만들고 싶지 않으며 보안에 지장이 생기면 안 된다.
- 이 때 버킷 주인이 presigned url 생성을 요청한다.
- 버킷은 URL을 제공한다.
- URL은 파일에 액세스할 권한을 부여하여 자격 증명을 이관하게 된다.
- 이제 이 URL을 사용하여 외부 사용자는 일시적으로 버킷에 접근이 가능하다.
- presigned url은 특정 파일을 다운로드 하거나 업로드 하기 위한 일시적인 액세스가 필요할 때
자주 사용된다.
예시로
로그인한 사용자만 S3 버킷에 있는 비디오를 다운로드 할 수 있도록 하거나
URL을 동적으로 변경하여 파일을 다운로드할 사용자의 목록을 계속 변경되도록 하거나
일시적으로 구체적인 위치에 사용자가 파일을 업로드하도록 할 수 있다.
S3 Access Points
- 많은 데이터가 저장된 S3 버킷이 있다.
- 그리고 해당 버킷에 접근하는 매우 다양한 그룹과 사용자가 존재한다.
- 사용자가 많아지고 데이터가 많아질수록 버킷에 접근 가능한 그룹과 사용자를 관리하는게 복잡해질 것이다.
- 이를 S3 액세스 포인트를 활용해 해결할 수 있다.
- 예를 들어 재무 데이터에 연결할 재무 액세스 포인트를 만들었다고 하자
- 여기서 재무 액세스 포인트는 재무 액세스 정책을 정의해야 한다.
- 해당 정책은 S3 버킷 정책과 매우 유사하고
재무 접두사에 대한 액세스를 승인하고, 읽고 쓰는 권한을 관리한다.
- 해당 정책은 S3 버킷 정책과 매우 유사하고
- 한 마디로 특정 접두사에 대한 정책을 정의하여 접두사 별로 권한을 관리하는 것이다.
- 여러 개의 접두사에 대한 정책을 정의할 수도 있다.
이제 액세스 포인트에 설정한 권한을 바탕으로 특정 사용자만이 특정 액세스 포인트에 접근할 수 있고
해당 액세스 포인트를 통하여 버킷의 자원에 접근할 수 있다.
- 액세스 포인트를 사용하면 S3 버킷의 보안 관리를 간단하게 만들며
- 각 액세스 포인트에는 각각의 DNS 네임이 존재한다
- VPC를 통해 인터넷에 연결되도록 할 수도 있다.
S3 Access Points - VPC Origin
- S3 액세스 포인트에 VPC 오리진을 설정하면
해당 액세스 포인트는 특정 VPC에서만 접근이 가능해져 외부 네트워크를 차단할 수 있다. - 해당 VPC 오리진에 대한 액세스 권한을 얻으려면
액세스 포인트에 액세스 하려 할 때 VPC 엔드포인트라고 하는 것을 만들어야 한다.- VPC 엔드포인트는 VPC에 내장된 것으로 VPC 오리진을 통해
액세스 포인트에 프라이빗하게 연결할 수 있게 하는 요소다. - VPC 엔드포인트 정책을 사용하면 VPC, S3의 액세스 포인트와 S3 버킷에 모두 연결할 수 있다.
- VPC 엔드포인트는 VPC에 내장된 것으로 VPC 오리진을 통해
S3 Object Lambda
- S3 액세스 포인트의 또 다른 활용 사례는 S3 객체 람다다
- 주요 기능은 다음과 같다
- 원본 객체 수정 없음: 원본 객체를 그대로 유지한 채 사용자 요청 시에만 맞춤형 응답을 제공한다
- 실시간 데이터 변환: 실시간으로 데이터를 변환하거나 필터링한 후 사용자에게 전달한다.
- 사용방법
- S3 객체를 어떻게 변환할지 정의하는 람다 함수를 정의한다.
- 기존 S3 액세스 포인트와 연결된 람다 액세스 포인트를 설정한다.
- 람다 액세스 포인트를 통해 데이터를 요청하면 S3 는 해당 객체를 람다 함수로 전달하여 결과를 반환한다.
특히 워터 마크는 객체를 요청하는 사용자 별로 워터마크를 지정하기 때문에 람다 액세스 포인트의
사용 사례로 대표적이다.