...
웹사이트의 경우 외부에 공개하는 정보가 아닌 이상 S3에 저장하는 데이터는 기본적으로 암호화할 필요가 있다. 또한 만일 인프라가 외부의 공격으로 인해 털렸을때 암호화 설정을 해놓는다면 도둑들은 쉽게 안의 중요한 데이터를 볼수 없을 것이다.
대개 S3에 데이터를 암호화는 거는 방식은 크게 두가지 방식이 있는데, 데이터를 저장할 때 암호화 KEY를 이용해 암호화/복호화로 관리하거나, Amazon의 암호화된 API 엔드포인트를 이용해 S3에서 다른 서비스 또는 리소스로 전송되는 데이터를 암호화 할 수 있다.
S3 Key로 암호화하기
키를 이용해 S3 데이터를 암호화할때 어느 주체 기준으로 암호화하는지에 따라, 서버측 과 클라이언트로 나뉘게 된다.
이 둘은 각 상황과 특징에 따라 쓰임새가 달라 자신의 서비스 환경에 맞게 선택하여야 한다.
서버측 암호화
서버 측 암호화는 데이터를 받는 애플리케이션 또는 서비스에 의해 데이터를 암호화하는 것이다.
서버측 암호화는 S3 플랫폼 내에서 진행되며, 디스크에 저장될 때 데이터 객체를 암호화하고, 적절한 권한 증빙을 통해 데이터 인출을 요청할 때 복호화해 전송한다.
서버측에서 S3에서 암호화를 하는 방법은 다음과 같이 3가지가있다.
- SSE-S3 : AWS 회사 자체에서 관리 되는 keys를 이용해 암호화.
- SSE-KMS : KMS(아마존 키 매니저 서비스 - AWS의 암호를 관리해주는 서비스)를 이용해 암호화
- SSE-C : 사용자에 의해 직접 정의된 keys를 이용해 암호화
SSE는 Server Side Encryption의 약자이다. 말 그대로 서버에서 암호화를 뜻한다.
SSE-S3
- 이 방식은 아마존 S3 에서 관리하는 키를 사용하여 암호화하는 방법이다. S3 managed data key는 S3에 의해 완전히 소유되고 관리 된다.
- AES-256 알고리즘을 이용해 암호화 한다.
- 서버에서 암호화 하도록 만들기 위해서는 헤더에 아래 내용을 보내야 한다.
- "x-amz-server-side-encryption": "AES256" (amz는 amazon의 약자이다)
- 아래의 과정을 거쳐 암호화 된다.
- 암호화되지 않은 객체를 S3 로 업로드하여 SSE-S3 암호화를 할 것이다.
- S3 로 객체를 전송할 때 HTTP/HTTPS 프로토콜로 헤더에 "x-amz-server-side-encryption":"AES256" 을 설정해 전송한다.
- 그러면 Amazon S3 는 이 헤더를 통해 S3 Managed Data Key 로 전송받은 Object 를 암호화 하고 저장한다.
- 즉, S3 에서 암호화 하는 데이터 키를 소유하고 관리하고 있는 방식이다.
만일 암호화가 걸리지 않은 파일을 버켓에 못올리게 하고 싶을때, 버켓 정책 설정을 통해 구현이 가능하다.
SSE-KMS (Key Manager Service)
- KMS란, EC2, RDS 같이 아마존 키 관리를 중점으로 하는 하나의 서비스를 말한다.
- 위의 SSE-S3과의 다른점은, 조금 더 사용자 단위의 컨트롤을 할 수 있다는 점이다.
- KMS 에서 키를 관리하는 이유는 어떤 사람이 키에 접근 가능하게 하고 어떤 사람은 키에 접근하지 못하게 하는 것이 가능하고, 추적도 가능하기 때문이다.
- 객체는 SSE-S3에서와 마찬가지로 서버에서 암호화 된다.
- 헤더는 다음과 같이 보내야 한다.
- "x-amz-server-side-encryption": "aws:kms" - 아래의 과정을 거쳐 암호화 된다.
- Amazon S3 는 전송받은 객체의 헤더를 확인하고 어떤 방식으로 암호화 할 지 설정한다.
- SSE-KMS 방식이기 때문에 S3 에서 암호화 할 때 사용하는 키는 KMS 에서 미리 세팅해놓은 KMS Customer Master Key 를 사용하여 전송받은 객체를 암호화한다.
- 그리고 암호화 한 객체를 S3 버킷에 저장한다.
단, KMS는 요청당 과금이 되는 형태이므로 요금 부담이 있을수 있다.
SSE-C
- 키값을 외부에서 사용자가 완전하게 관리하는 암호화 방식이다.
- Amazon S3 는 고객이 제공한 암호화 키를 서버에 저장하지 않는다. 그리고 사용한 암호는 바로 폐기 된다.
즉, AWS는 제공된 키를 가지고 암호화 시키는 역할만을 수행한다. - 따라서 데이터를 AWS 로 전송할 때는 반드시 HTTPS 프로토콜을 사용해야 한다. 왜냐하면 고객이 암호화 키를 보내야 하기 때문에 암호화는 필수이다. (암호화 키는 HTTPS 헤더에 있다)
- 아래의 과정을 거쳐 암호화 된다.
- 고객은 객체와 암호화 키를 HTTPS 프로토콜을 사용해서 Amazon S3 로 보낸다
- AWS S3 에서 전송받은 키로 객체를 암호화하여 S3 버킷에 저장한다.
- 만일 고객이 S3 부터 파일을 받으려면 똑같은 암호화 키를 아마존 S3 로 보내줘야 한다.
- 서버 측에서 키를 관리하는 것과 다르게 클라이언트에서 해야 할 일들이 많다.
이처럼 사용자가 직접 HTTPS를 사용해 데이터를 암호화하고 버킷에 업로드 하는 형식으로, 따로 S3 콘솔 메뉴를 지원을 하지 않는다.
따라서 REST API를 사용하여 객체를 생성할 때 고객 제공 암호화 키(SSE-C)를 사용하여 서버 측 암호화를 지정한다.
SSE-C를 사용하는 경우 다음 요청 헤더를 사용하여 직접 암호화 키 정보를 제공해야 한다.
이름 | 설명 |
x-amz-server-side-encryption-customer-algorithm | 헤더를 사용하여 암호화 알고리즘을 지정. 헤더 값은 "AES256" |
x-amz-server-side-encryption-customer-key | 이 헤더를 사용하여 256비트의 base64 인코딩 암호화 키를 Amazon S3에 제공하여 데이터를 암호화하거나 암호 해독 |
x-amz-server-side-encryption-customer-key-MD5 | 이 헤더를 사용하여 RFC 1321에 따라 암호화 키의 128비트 base64 인코딩 MD5 다이제스트를 제공. Amazon S3는 메시지 무결성 검사에 이 헤더를 사용하여 암호화 키가 오류 없이 전송되었음을 확인. |
클라이언트측 암호화
- 클라이언트 측 암호화(Client side encryption)는 로컬에서 데이터를 암호화하는 작업이다. (SSE-C와 차이점은 S3 서버가 암호화 과정에 전혀 관여하지 않는다는 점이다)
- 객체를 S3에 업로드 하기 전에 클라이언트에서 암호화 한다.
- Amazon S3 Encryption Client 라는 라이브러리를 사용하여 암호화를 한다. (이 때문에 복호화 할 때도 클라에서 알아서 암호 키를 이용해 복호화 해야 한다)
- 따라서 클라이언트가 암호 키와 암호화 과정을 모두 알아서 관리하게 된다.
- 대부분은 간단하게 설정 할 수 있는 서버측 암호화를 사용하겠지만, 기업 및 기관에 따라 암호화 키를 직접 생성 및 관리하려는 경우가 있기 때문에 클라이언트 암호화 기능을 사용한다.
- 아래의 과정을 거쳐 암호화 된다.
- 클라이언트는 AWS 에서 제공하는 암호화 SDK 를 사용하여 객체를 암호화 한다.
- 암호화가 클라이언트 측에서 일어나므로 객체는 클라이언트에서 완전히 암호화가 된다.
- 암호화 된 객체를 S3 버킷에 업로드한다.
S3 전송중에 암호화 (On Transit)
SSL/TLS
- 통신 암호화 방식으로 SSL 과 TLS 가 사용된다.
- HTTPS를 이용하는 경우 전송 중 암호화를 하게 되는데, 이 때 SSL/TLS 인증서를 이용하게 된다.
- HTTPS 를 사용하면 클라이언트와 아마존 S3 사이를 이동하는 데이터가 모두 암호화되어 전송되기 때문에 Encryption in transit 이라고 부른다.
- SSE-C 즉, 서버 측 암호화를 사용해 클라이언트가 키를 제공해야 하는 경우에는 HTTPS 프로토콜 사용이 필수다.
S3 실전 객체 암호화 해보기
버킷 전역 암호화 설정
먼저 S3 콘솔 메뉴에 들어가서 버킷에 들어간다.
그리고 속성 메뉴에 들어가 밑으로 스크롤하면 기본 암호화 설정할 수 있는 섹션이 나온다.
개별 객체 암호화 설정
일부 객체만 암호화 설정하고 싶다면 역시 따로따로 관리가 가능하다.
암호화 객체 업로드
객체를 업로드 할때 암호화를 해주고 업로드 해주는 방식이다.
서버 측 암호화 설정 메뉴에 들어가보면, 다음과 같이 '암호화 키를 지정하지 마십시오' 와 '암호화 키 지정'을 선택할 수 있게 된다.
여기서 약간 설정이 난해하게 분기되어 있는데 차근차근 하게 따라와 보자.
1. 기본 암호화 설정 안했을 경우
만일 위에서 버킷 기본 암호화를 설정안했을 경우,
- 암호화 키를 지정하지 마십시오 : 객체 암호화를 사용하지 않음
- 암호화 키 지정 : 이 객체만 암호화 설정을 함
2. 기본 암호화 설정 했을 경우
만일 위에서 버킷 기본 암호화를 설정을 했을 경우,
- 암호화 키를 지정하지 마십시오 : 기본 암호화 설정을 따름
- 암호화 키 지정 :
- 기본 암호화 버킷 설정 사용 : 기본 암호화 설정을 따름
- 기본 암호화 버킷 설정 재정의 : 따로 암호화 설정을 함
기존 객체 암호화
기존에 이미 있는 객체 데이터도 작업 수정을 통해 암호화 설정이 가능하다.
AWS CLI 에서 S3 암호화 설정
SSE-S3를 사용한 기본 암호화
$ aws s3api put-bucket-encryption --bucket bucket-name --server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'
S3 버킷 키와 SSE-KMS를 사용한 기본 암호화
$ aws s3api put-bucket-encryption --bucket bucket-name --server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "KMS-Key-ARN"
},
"BucketKeyEnabled": true
}
]
}'
# 참고자료
https://bikramat.medium.com/s3-encryption-for-objects-d892f5ce7b38
https://awstip.com/creating-a-high-availability-cluster-with-aws-cli-efdf47ca4d8e
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.