암호화 메커니즘
TLS/SSL
- 전송중 암호화
SSL -> TLS
- 데이터가 전송되기 전에 암호화가 되고 받은 후에 복호화 하는 것
- 데이터를 암호화 하기 위해 TLS 인증서를 사용한다.
- 전송 중 암호화 하는 이유
- 데이터를 네트워크를 통해 전송할 때는 공공 네트워크를 사용한다.
공공 네트워크를 사용하기 때문에 데이터는 여러 다른 서버를 통해 지나간다.
그렇기 때문에 중간에 공격받는 '중간자 공격' 방지하기위해 전송 중 암호화를 한다.
- TLS로 인해 목표하는 대상 서버만 데이터를 받을 수 있게 한다.

서버 측 저장 암호화
- 데이터 암호화 과정이 서버에서 받은 후에 일어나게해 안전하게 저장되도록 하는 것.
- 데이터가 해독되는 것은 고객에게 되돌려 보내기 전에 진행된다.
- 암호화 된 상태로 저장되고, 키를 이용해서 진행되며 이 키는 주로 데이터 키이다.
- 암호화와 복호화를 위한 키를 관리하는 것은 어딘가에서 이 관리가 일어나고, 서버가 이 키에 대한 접근을 할 수 있어야 한다는 것이다.
- 예시

예를 들어 S3 서비스로 예를 들면
- HTTP(S)로 객체를 보낸다
- 서비스가 이 객체를 받고 해독이 된다.
즉, 서비스는 데이터키를 사용할 수 있고 그 데이터 키와 해독된 객체를 사용해서 그 객체의 저장 중 암호화를 할 수 있는 것.
- 그리고 이 객체를 다시 고객에게 전송할 때 암호화된 객체와 데이터키가 함께 해독하기 위해 사용될 것이다.
- 그럼 해독된 객체를 갖게 되고 그 객체가 HTTPS를 통해 다시 고객에게 전송될 것이다.
즉, 해독된 객체를 받을 수 있도록 한다.
- 서버 측 암호화는 모든 암호화와 해독이 서버에서 일어나는 것
클라이언트 측 암호화
- 데이터가 클라이언트 측에서 암호화와 해독되며 서버는 이 데이터를 해독할 수 없어야 한다.
서버를 신뢰할 수 없는 경우
- 이 경우 봉투 암호화를 사용할 수 있다.
- 예시

- 고객이 객체를 가지고 있고 데이터 키는 클라이언트 측이다.
- 암호화 이후에 암호화된 객체를 받는다
- 그 암호화된 객체는 어느 스토리지 서비스든 안전하게 전송된다.
FTP,S3,EBS든 뭐든 안전하다.
- 그리고 암호화된 상태로 저장될 것이다.
즉, 대상 서버도 데이터 내용을 해독할 수 없다.
- 이후 이 암호화된 객체를 되찾을 때 클라이언트 측 데이터 키에 접근할 수 있어 복호화 해 데이터를 다시 받을 수 있다.
AWS KMS(Key Management Service)
- 암호화 키 관리 서비스
- KMS를 사용하면 CloudTrail을 통해, 키를 사용하기 위해 이루어진 모든 API 호출을 감사할 수 있다.
- 다양한 AWS 서비스에서 사용 가능하다.
- KMS를 사용할때 API 호출을 통해서도 KMS를 사용할 수 있다.
AWS CLI, SDK등으로 모든 비밀을 KMS 키로 암호화 가능하다.
암호화된 비밀을 예를 들어 코드나 환경 변수에 저장할 수 있다.
KMS 키 유형
- 대칭 KMS 키(AES-256)
- KMS가 통합된 모든 AWS 서비스는 대칭키를 사용
- KMS 대칭 키를 생성하거나 사용할 때 키 자체에는 액세스 불가능
- 단지 AWS API 호출을 이용해 키를 사용할 뿐이다.
- 비대칭 KMS 키(RSA & ECC)
- 데이터 암호화로 퍼블릭 키 사용, 복호화로 프라이빗 키 사용
- 암호화/복호화 또는 서명/확인 형태의 작업을 할때 사용
- KMS에서 퍼블릭 키를 다운받을 수 있지만 프라이빗 키는 액세스할 수 없다.
프라이빗 키는 AWS API 호출만 사용가능
- AWS Cloud 외부에서 KMS API 키에 액세스할 수 없는 사용자에 의해 암호화를 하려는 경우
퍼블릭 키를 사용해 데이터를 암호화하고 클라우드로 전송한다.
그리고 계정 안에 있는 사용자는 AWS의 프라이빗 키를 사용해 복호화
KMS 키
- AWS가 소유한 키(무료)
- SSE-S3, SSE-SQS, SSE-DDB(DynamoDB)를 사용할 때 사용하는 키
- AWS 관리형 키(무료)
- aws/* 유형의 서비스
ex: aws/rds, aws/ebs, aws/dynamodb
- 무료이지만 키가 지정된 서비스 안에서만 사용할 수 있음.
- 고객 관리형 키($1/달)
- 자동 키 순환
- 키가 AWS 관리형 KMS 키라면 자동으로 1년마다 순환된다.
- 고객 관리형 키라면 자동 순환을 활성화하면 적용
1년 마다 순환
단, 임포트한 KMS키라면 수작업으로만 순환 가능.(Alias 사용)
KMS 키 범위
- KMS 키는 리전 단위이다.

- KMS 키로 암호화된 EBS 볼륨을 다른 리전에 복사하기
- EBS 볼륨 스냅샷 찍기
- 암호화된 스냅샷의 스냅샷을 찍으면 그 스냅샷 자체도 동일한 KMS 키로 암호화 된다.
- 그리고 스냅샷을 다른 리전에 복사하기 위해 다른 KMS 키를 사용해 스냅샷을 다시 암호화해야 한다.
- 동일한 KMS 키가 두 리전에 있을 수 없음.
- 다른 키를 사용해 KMS로 암호화된 EBS 스냅샷이 있고 다른 리전에 있게 된다.
- KMS를 이용해 그 스냅샷을 원래의 EBS 볼륨으로 복구한다.
- 그 KMS 키 B는 ap-southeast-2에 속한다.
KMS 키 정책
- KMS 키 액세스 관리 정책
- S3 버킷 정책과 비슷
하지만 내 키에 KMS 키 정책이 없다면 아무도 키에 접근할 수 없다는 점이 다르다.
- 기본 KMS 키 정책
- 특정한 커스텀 KMS 키 정책을 제공하지 않았을 때 생성된다.
- 기본값은 내 계정에 있는 모든 사람이 이 키에 액세스 허용한다.
즉, 사용자 또는 역할이 이 키 정책에 액세스하도록 허용하는 IAM 정책이 있다면 문제 없이 접근 가능하다.
- 커스텀 KMS 키 정책
- KMS 키에 액세스할 수 있는 사용자와 역할을 정의
- 키를 누가 관리할 수 있는지 정의
- KMS 키에 대한 교차 계정 액세스의 경우 특히 유용
다른 계정이 우리의 KMS 키를 사용하도록 승인할 수 있기 때문이다.
- 고객 관리형 KMS 키로 암호화된 스냅샷을 생성
- 교차 계정 액세스를 승인하기 위한 KMS 키 정책을 첨주한다.

- 그리고 암호화된 스냅샷을 타겟 계정과 공유한다.
- 타겟 계정 안에서 스냅샷의 사본을 생성하고, 다른 고객 관리형 키를 사용해 그 타겟 계정 안에서 암호화를 진행한다.
- 그러면 타겟 계정 안에서 스냅샷으로부터 볼륨을 생성할 수 있다.
커스텀 KMS 키 생성
- 키 유형 선택
- 용도 선택
- 키 구성 요소 원본: KMS, 외부 , AWS CloudHSM 키 스토어 선택
- 리전 구분: 단일 리전키, 다중 리전키 선택
- 별칭 설정
next
- 키 관리자 설정: 관리자를 정의하지 않으면 기본 KMS 키 정책을 사용한다.
- 키 사용자 정의: 사용자를 설정
- 키 액세스에 다른 AWS 계정 선택 옵션
-> 암호화된 EBS스냅샷을 공유할 때 다른 계정을 추가해서 키에 액세스하도록 허용
- 생성 이후 자동 키 교체를 활성화하려면 자동 키 교체에 체크박스를 선택하면 매년 키가 자동으로 교체된다.
# CLI를 이용해 KMS 사용해보기
# ExampleSecretFile.txt
secretpassword
# CLI 암호화
aws kms encrypt --key-id alias/<KMS 별칭> --plaintext fileb://ExampleSecretFile.txt --output text --query CiphertextBlob --region ap-northeast-2 > ExampleSecretFileEncrypted.base64
# CLI base64 디코딩 (2진 파일)
## 리눅스
cat ExampleSecretFileEncrypted.base64 | base64 --decode > ExampleSecretFileEncrypted
## 윈도우
certutil -decode .\ExampleSecretFileEncrypted.base64 .\ExampleSecretFileEncrypted
# CLI KMS 복호화
aws kms decrypt --ciphertext-blob fileb://ExampleSecretFileEncrypted --output text --query Plaintext > ExampleFileDecrypted.base64 --region ap-northeast-2
# base64 디코딩
## 리눅스
cat ExampleFileDecrypted.base64 | base64 --decode > ExampleFileDecrypted.txt
## 윈도우
certutil -decode .\ExampleFileDecrypted.base64 .\ExampleFileDecrypted.txt
KMS - 멀티 리전 키

- 한 리전에 기본 키를 가지고 다른 리전으로 복제
- 다중 리전 키
- 다른 AWS 리전에서 사용할 수 있는 KMS 키 세트로 서로 교차해서 사용 가능
한 리전에서 암호화 후 다른 리전에서 복호화 가능
- 다중 리전 키는 동일한 키 ID와 동일한 키 구성 요소를 갖는다.
- 기본 키의 자동 교체를 활성화했고 실제로 자동으로 교체된 키는 다른 리전에도 복제된다.
- 다중 리전 키의 핵심
한 리전에서 암호화하고 다른 리전에서 복호화해 다음 리전으로 복제할 때나 교차 리전 API 호출을 실행할 때 데이터를 재암호화하지 않아도 된다.
- 그러나 KMS 다중 리전 키는 전역으로 사용할 수 없다.
기본 키가 있고 복제본이 있는 것.
- 각 다중 리전 키는 자체 키 정책 등으로 각각 독립적으로 관리된다.
- 다중 리전 키 사용을 권장하진 않음.
- 다중 리전 키 사용 사례
- 전역 클라이언트 측 암호화
함 리전에서 클라이언트 측 암호화를 하고, 다른 리전에서 클라이언트 측 복호화를 하는 것
또는 DynamoDB 전역 테이블이나 Global Aurora에서 암호화할 때 사용
DynamoDB 전역 테이블과 KMS 다중 리전 키를 클라이언트 측 암호화 원리
- 전체 테이블만 암호화 하지 않는다.
저장 데이터 암호화이므로 테이블의 속성을 암호화해 특정 클라이언트만 사용할 수 있게 된다.
데이터 베이스 관리자도 사용할 수 없음.
-> 이럴때 DynamoDB 암호화 클라이언트를 사용한다.

- KMS 다중 리전 키는 다른 리전에 복제 된다.
- 클라이언트 애플리케이션에서 DynamoDB에 데이터를 삽입하려면 속성을 암호화해야 한다.
- 다중 리전 키를 사용해 암호화할 속성을 암호화하고,
- 대부분의 DynamoDB 테이블 필드는 클라이언트 측 암호화가 되지 않지만 사회 보장 번호는 암호화될 것이다.
- DynamoDB 테이블에 액세스할 수 있는 데이터베이스 관리자가 '사회 보장 번호' 속성을 암호화하는 데 사용한 KMS 키에 액세스할 수 있는 권한이 없다면 액세스할 수 없다.
데이터베이스 관리자로부터도 보호할 수 있는 것
- DynamoDB 테이블이 전역 테이블인 경우 해당 테이블의 데이터는 다른 리전으로 복제된다.
- 다중 리전 키로 데이터 속성을 암호화했기 때문에 다른 리전의 클라이언트 애플리케이션은 열을 검색해 해당 속성이 암호화 됐는지 확인 후 API 호출을 실행해 복제된 다중 리전 키를 사용해 해당 속성을 복호화한다.
- 클라이언트 측 암호화 기술을 사용하면 데이터의 특정 필드나 속성을 보호할 수 있게 된다.
- 그리고 API 키 액세스 권한이 있는 클라이언트만 복호화할 수 있다.
- 전역 테이블 덕분에 데이터뿐만 아니라 암호화 키도 함께 복제할 수 있다.
Global Aurora - KMS 다중 리전 키
- AWS Encryption SDK를 사용한다.

- 두 리전에 걸쳐 복제된 KMS 키가 있다.
- 클라이언트 애플리케이션이 SSN 열을 암호화하려면 데이터를 Aurora DB에 테이블로 삽입해야 한다.
- 해당 행에서 다중 리전 키인 MRK로 암호화된 SSN 열을 제외한 다른 열의 데이터는 암호화되지 않는다.
- 전역 DB이므로 테이블이 전역으로 복제될 것이다.
- 다른 리전의 클라이언트는 테이블에서 암호화된 데이터를 가져오고 다중 리전 키를 사용해 KMS에 로컬 API 호출을 보내 해당 속성을 복호화한다.
-> 지연 시간이 단축됨
- 클라이언트 측 암호화를 사용하면 DB 관리자로부터 데이터를 보호할 수 있음.
- Aurora DB에 액세스할 수 있는 DB 관리자가 '사회 보장 번호' 열에 액세스하고자 할 때 KMS 키에 대한 액세스 권한이 없으면 해당 데이터를 읽을 수 없다.
S3 복제와 암호화된 객체의 연관성
- 한 버킷에서 다른 버킷으로 S3 복제를 활성화하면 암호화되지 않은 객체와 SSE-S3로 암호화된 객체가 기본으로 복제된다.
- 고객 제공 키인 SSE-C로 암호화한 객체도 복제될 수 있다.
- SSE-KMS로 암호화된 객체도 있다.
- 이는 기본적으로 복제되지 않지만 복제하려면 옵션을 활성화해야 한다.
- 어떤 KMS 키로 대상 버킷 내 객체를 암호화하는지 지정해야 한다.
그리고 이 KMS 키 정책을 대상 키에 적용해야 하고 S3 복제 서비스를 허용하는 IAM 역할을 생성해 소스 버킷의 데이터를 먼저 복호화하도록 한 뒤 대상 KMS 키로 대상 버킷의 데이터를 다시 암호화한다.
- 이는 수많은 암호화와 복호화가 발생하기 때문에 KMS 제한 오류가 발생할 수 있으며, 이 경우 서비스 할당량 증가를 요청할 수 있다.
- S3 복제에 다중 리전 키를 사용해야 할까?
공식 문서에는 S3 복제에 다중 리전 키를 사용할 수 있지만 현재는 S3 서비스에서 독립 키로 취급하고 있어 객체는 여전히 복호화될 것이고, 다중 리전 키여도 동일한 키로 암호화 된다.
AMI를 다른 계정과 공유하는 과정
- AMI는 KMS 키로 암호화 되어 있다.

- AMI는 소스 계정에 있고, KMS 키로 암호화 되었다.
- 어떤 방식으로 A 계정의 AMI에서 B 계정의 EC2 인스턴스를 시작할까?
- 먼저, 시작 권한으로 AMI 속성을 수정해야 한다.
시작 권한은 B 계정에서 AMI를 시작하도록 허용해 AMI를 공유한다.
- 시작 권한을 수정하고 특정 대상인 AWS 계정 ID를 추가하는 것
- B 계정에서 사용하도록 KMS 키도 공유해야 하므로 일반적으로 키 정책으로 실행된다.
- B 계정에서 KMS 키와 AMI를 모두 사용할 수 있는 충분한 권한을 가진 IAM 역할이나 IAM 사용자를 생성한다.
- 따라서 DescribeKey API 호출과 ReEncrypted API 호출, CreateGrant, Decrypt API 호출에 관한 KMS 측 액세스 권한이 있어야 한다.
- 모두 완료한 후에는 AMI에서 EC2 인스턴스를 시작하면 되는데
- 선택 사항으로 대상 계정에서 자체 계정의 볼륨을 재암호화하는 KMS 키를 이용해 전체를 재암호화할 수 있다.