<섹션30 AWS 보안 및 암호화>
<426 개요 & 암호화 기본 개념>
> 시험에서 보안문제 많이 물어봄
> 지금까지 종종 나왔지만, 정확하게 이해가 필요함 - KMS , Param Store 등등
<기본 개념 : Encryption 의 동작 (in flight) TLS/LLS>
> 기본적으로 보내기 전에 encrypt 를 하고, 받을 때 decrypt 를 하는 것임
> Encryption 을 진행할 때 TLS Certificate (인증서) 가 사용된다 - https 프로토콜을 사용할 때 적용된다
> 하는 이유 : 네트워크를 통해 (종종 public network 를 통해) 여러 서버들을 왔다 갔다 하는데, 중간에 공격을 받을 수 있기 때문 - MITM (man in the middle attack)
>> 서버로 전송 중인 packet 을 관찰하는 것! 보안화가 필요한 이유
>> SSL 을 적용하는 것은 수신하는 서버만이 Client 가 보내는 Data 를 Decrypt 할 수 있도록 적용하는 것이다
> Client 가 서버에게 username / password 를 전달해서 로그인을 한다고 해보자
> Client 사이드에서 보낼 때 TLS 암호화를 고객 측에서 자동적으로 적용, 데이터가 암호화되어서 네트워크를 통해 전송됨 (질문 : 어떻게 고객측에서 서버마다 다른 암호화 방식에 대해 알고 있나요?)
>> 중간에서는 암호화된 메세지를 해독할 수 없다
>> 수신 Server 에서만 이 암호화를 해독할 수 있어서 Username / Password 를 읽을 수 있다
< 기본 개념 2 : Server Side Encryption (at rest) :: 내 시스템 안에서 유용할 듯>
> 서버가 수신하고 처리한 이후 Store 할 때 encrypt 하는 것을 말한다
> 서버가 데이터를 꺼내서 다시 sending 을 할 때는 decrypt 를 한다
> (보통 Data Key) 활용하는 Key 를 통해 Encrypt 를 진행한 후 저장한다 (Data Key 의 첫 등장, 그냥 키임 ㅅㅂ)
> 이 encrypt / decrypt 를 위한 key 는 manage 되어야 한고, 이 Server 가 이 Key 를 access 할 수 있어야 함!!
> HTTP / HTTPS 로 응답을 수신한 서버는 raw 한 데이터를 들고 있을 것이다 (SSL 해제 이후 상황)
> 그럼 Data Key 를 활용해서 Encrypt 하여 보관할 수 있다 (at rest)
> 이 정보를 다시 요청한 곳에 전송해주기 위해서 Data Key 를 함께 사용해서 해독하여 해독된 객체를 다시 고객에게 전송하게 된다
>> at rest & in-flight 에 대한 보안은 서로 독립적인 것을 이해해야한다
>>(중요) At Rest 보안 같은 경우 모든 암호화 / 해독이 서버에서 일어난다
< Client-Side Encryption :: 남의 서버 쓸 때 유용할 듯?>
> 개념2와 반대로, Client 에서 암호화 / 해독을 진행하는 것이다.
> 서버는 절대 Data 를 해독할 수 없어야 한다 (사용할 Storage 서버의 보안을 신뢰하지 못하는 경우에 적합)
> 이 경우에는 [Envelope Encryption] 기법을 사용할 수 있다 (곧 나옴 ㅇㅇ)
> 고객이 데이터를 가지고 있고, Client-Side 의 Data Key 도 가지고 있어서 전송할 Encrypted Data 를 준비할 수 있다
> 이를 서버에 저장하라고 요청을 보내는 것 (FTP 서버, S3, EBS 볼륨 등등)
> 서버는 이를 암호화된 상태로 보관한다 (서버 측도 해독 못함)
> 고객측에서 원하는 데이터를 fetch 하면, 직접 decrypt 해서 원하는 Data 를 사용할 수 있다
---------------------------------------
<428 KMS 개요>
> KMS 는 AWS 의 키 관리 서비스로, 지금까지도 매우 많이 사용했음
> AWS 가 Encryption Key 를 KMS 로 관리해주며, IAM 과 권한 부여를 위해 상호작용함
> 데이터 엑세스 제어를 쉽게 할 수 있음
> CloudTrail 을 사용해서 KMS 의 키를 통해 사용된 API 들을 감시할 수 있다
> 많은 리소스들에서 쉽게 사용할 수 있음 (ex: S3 에서 at-rest 암호화를 하고 싶으면, KMS 암호화 활성화만 하면 됨)
>> 참고로, Secret 정보가 있으면 plaintext 로 절대 노출시켜 저장/사용하면 안된다
> KMS 암호화를 사용하려는 경우 SDK, CLI 를 통한 API 호출로도 사용이 가능하다
> 그냥 암호화하고 싶은 어떤 것이든 KMS 키로 암호화가 가능하다 뜻. 이 상태로 code 에는 저장해도 되며, 환경변수로도 사용해도 된다
<KMS Key 종류>
> KMS Key (이전 Master Key)
>> Symmetric (AES-256 Key) : 대칭키 (암호화/복호화에 오직 한가지 키가 사용됨)
>>> 서비스들이 KMS 와 통합하면 대부분 이 대칭키를 사용한다
>>> KMS 대칭 키를 만들거나 사용하면, unencrypted 된 키 자체에는 절대 접근할 수 없다 (단순히 사용하기 위해 KMS API 만 호출할 수 있음)
>> Asymmetric Key (RSA & ECC Key Pair) : 비대칭 키 (암호화에 사용되는 공개키 / 복호화에 사용되는 비공개키)
>>> 암호화/복호화 or 서명/확인작업 등에 자주 사용됨
>>> KMS 키를 통해 public Key 는 다운 받을 수 있지만, 비공개 키는 역시 접근할 수 없다 (브라우저에서도 웹사이트들의 공개키는 다운받을 수 있음)
>>> Use Case : AWS 클라우드 외부의 유저가 데이터를 암호화 해야 할 때 (KMS API 를 사용할 수 없을 때)
<Key 자체의 종류? 말하는건가?>
> AWS Owned Key (무료) : SSE-S3, SSE-SQS, SSE-DDB (선택 옵션이 있던 것)
>> 사실상 KMS 는 아니지만, AWS 에서 제공하는 기본 옵션이다
> AWS Managed Key : 관리형 키 역시 무료, aws/{service-name} 의 형태라서 본 적이 있음 (ex: aws/rds or aws/ebs)
>> 할당된 서비스 내에서만 사용 가능
> Customer Managed Keys : 직접 관리하는 키를 KMS 를 통해서 사용하려면 1달에 1달러 듬
>> 이 키를 import 하는 것도 가격 동일 (뭔차인지 잘 모르겠음) (대칭키만 가능)
>> API 호출에 사용되는 횟수별로도 가격이 부과
> Key Rotation 제공
>> AWS 관리형 KMS Key 라면, 1년마다 자동으로 교체된다
>> Customer 관리형 KMS Key 라면, 활성화를 해야 1년마다 자동으로 교체된다
>> Imported KMS Key 라면, 수동으로 교체해야 함, 별칭을 사용해야 함
<Region 에 걸쳐 Snapshot 복사하기>
> KMS Key 는 Region 별로 부여됨
> 특정 Region 에서 KMS 키로 암호화된 EBS 볼륨을 다른 리전으로 복사하려면 단계가 필요
>> 1) Encrypted EBS 를 Snapshot 하면 이 스냅샷도 Encrypted with KMS 임
>> 2) 다른 리전으로 복사하려면 또다른 KMS Key 로 이를 암호화 해야 함 (그러면 그냥 덮어씌우는듯..? 이부분 이해가 좀 안가긴 함)
>>> 동일한 키는 서로 다른 Region 에 존재할 수 없기 때문
>> 3) 그러면 Key B 를 가지고 있는 다른 Region 에서는 B 로 encrypt 된 스냅샷이 있기 때문에 이를 그대로 EBS 볼륨으로 복원할 수 있음
>>>> 잘 이해 안감 ㅅㅂ
<KMS Key Policies>
> KMS Key 에 대한 접근을 제어하기 위한 방법, S3 Bucket Policy 같은 것과 유사
>> 단, 차이점은 KMS Key 는 KMS Key Policy 가 없다면 그 누구도 접근할 수 없다
> Default KMS Key Policy
>> 아무것도 지정하지 않으면 사용됨
>> AWS Account 내 모든 사용자들이 접근 가능
>>> 즉, Key Policy 에 접근할 수 있도록 명시되어 있는 IAM Policy 만 가지 있다면 User or Role 은 무조건 접근 가능
> Custom KMS Key Policy
>> KMS Key 에 접근할 수 있는 User / Role 을 정의한 KeyPolicy
>> Key 를 관리할 사람도 지정할 수 있다 (administrator)
>> KMS - Key 에 대해서 Cross-Account 접근을 하고 싶을 때 사용하기 유용한 정책임 (KMS Key Policy 에 다른 Account User 를 authorize 하도록 정의할 수 있음)
<Cross Account 로 Snapshot 공유하기 - 아까 다른 리전 공유랑 과정은 동일한듯, Policy 추가된 거 빼면>
> 암호화된 Snapshot 을 여러 계정에 복사하려고 한다고 해보자
>> 1) 나의 KMS Key (Customer Managed Key) 로 암호화된 Snapshot 을 만든다
>>> Customer Managed Key 여야 Custom Key Policy 를 attach 할 수 있다는 것 같음
>> 2) KMS Key 에 Custom Key Policy 를 attach 한다 (위 예시) - cross-account 접근을 허용하는 모습
>> 3) 암호화된 스냅샷을 대상 계정들과 공유
>> 4) 공유된 계정 안에서는 Snapshot 의 복사본을 만들고, 그 계정 내의 다른 Customer Managed Key 로 다시 암호화한다 (아까 그 ReEncrypt 과정이랑 동일한 듯)
>> 5) Snapshot 을 사용해서 Volume 을 띄운다
---------------------------------------
<429 KMS 기본 실습, Key 의 종류>
3. Custom Key Store (x) - 시험범위 아님
1. AWS Managed Key
> KMS 로 이동하면 AWS 서비스들을 사용하면서 받았던 키들을 볼 수 있음
> AWS 가 자동으로 생성해주면 다 AMK 임. 형태는 CMK 랑 똑같음 ㅇㅇ
> Key Policy 보임. 이 키에 대한 액세스 권한이 있음 ex : EBS 관련 키 (Caller Account 가 이 계정이어야 함 이런거)
> SQS 관련 키를 보면 동일한 계정, 호출 가능 서비스는 SQS 이런거가 적혀잇음
> 암호화방식 이런거 살펴보면 KeyType 은 Symmetric 이란 것도 알 수 있음
2. Customer Managed Key (CMK, 앞으로 많이 활용)
> AWS Managed Key 가 아니라 직접 KMS 안에서 관리할 키를 만들 때 사용
> 만들면 한달에 1달러 듬
> 대칭키 / 비대칭키 선택 가능 (비대칭 키는 시험에 안나온대)
>> 대칭키는 기본적으로 단순히 암호화/복호화에 사용될 수 있다
> Key Origin 은 KMS (KMS 한테 만들어줭 하는거임)
> Single Region 키 선택 (KMS 의 전통적인 키 방식)
>>> 이후부터 단계적으로 Key Policy 만드는거임 (CMK 의 Key Policy 가 만들어지는 과정)
> Key 관리자를 설정할 수 있음
>> 만약 안하면 기본 KMS Key Policy 대로 적용됨
>> 원한다면 키를 관리할 User / Role 을 지정할 수 있음
> Key 사용자를 설정할 수 있음
>> 적절한 IAM 권한을 가진 사람/ 역할에게 key 사용을 허락한다 ex: stephane user 에게만 허용 등
>> 만약 안한다면 기본대로, IAM 권한 있으면 모두 다 사용가능 으로 적용된다
> Cross-Account 접근을 설정할 수 있음
>> Other AWS Account 에서 추가할 수 있음
>> 그냥 모두 다같이 Key Policy 를 만드는 작업임
> 최종적으로 Key Policy 를 확인할 수 있고, Custom Key 가 생성되었음
> 구성 중 [Key Rotation] 확인 (이거 자동화되는거 기억! AMK, CMK 만 지원!)
>> 교체를 활성화하고 싶으면 활성화 하면 됨 -> 매년 KMS 키가 자동으로 교체된다
>> KMS 로 만들었을 때만 적용 가능함
> 구성 중 [alias] 확인
>> 아까 만드는 단계 중 잇었는데, KMS 를 지칭하는 별칭 설정 가능, ARN 이 조금더 단순하게 제공
<Key 암호화 복호화 실습해보기>
$ aws kms encrypt --key-id {KMS_ID} --plaintext {encrypt_file_with_path} --output {output_path} --query CiphertextBlob --region {KMS_region} > {output_file_name}
> 사용할 파일 하나 만든다 (txt) - SuperSecretPassword 라고 적어두자
> 첫 명령 - key-id (아까 만든거 alias 로 명시해도 되고, ID 써도 되고, ARN 써도 됨) -plaintext 는 파일 위치, 암호화된 컨텐츠라는 쿼리를 명시(??), 텍스트 그대로 저장 등등을 명시
> 위 명령어를 수행하면 Base64 의 암호화된 파일이 튀어나온다 (암호화 바이너리 정보를 또 인코딩해서 보여줌)
>> 인코딩은 그냥 바이너리 파일을 보여주기 위한 수단임
> 그 파일이 생성되면, 암호화된 파일임을 확인할 수 있다
> Base64 로 간단히 디코딩 해볼 수 있는데, binary 파일로 나와서 에디터가 읽을 수도 없음.
>> 이 상태로 공유하는거라고 함! (공유해야할 일이 있으면)
$ aws kms decrypt --ciphertext-blob {encrypt_file_with_path} --output{out_put_path} --query Plaintext > {output_file_name} --{region_name}
> 이 바이너리 파일을 동일한 키 (대칭키였으므로) 를 사용해서 복호화해볼 것
> 제시된 명령어를 사용해서 복호화를 해보면, 똑같이 Base64 인코딩 되어서 튀어나옴
>> 그걸 다시 디코딩 해서 열어보면, 내가 처음에 입력한 SuperSecretPassword 가 있음
> 참고로, KMS KEY ID 는 안넣어주는것을 알 수 있음 (KMS 에서 사용한 키 자동인지)
---------------------------------------
<430 KMS 암호화 패턴 및 Envelope 패턴>
> Encrypt / Decrypt API 를 좀 더 알아보자 (위에서 한 내용을 분석)
> 위와 같은 루틴으로 실행하는데, 중간중간에 API 를 수행할 적합한 IAM 권한이 있는지도 확인
> KMS 는 복호화 API 를 사용할 경우 어떤 KMS 키를 사용해서 암호화되었는지 자동으로 인지함
> 꽤나 간단하지만 4KB 로 크기 제한이 있음
<Envelope 암호화 기법>
> 4KB 를 넘어서는 파일의 경우 봉투 암호화 기법을 사용한다
> 주요 API 는 GenerateDataKey API 임 (이게 Envelop Encryption 을 사용하는 API)
> "주요 암호화 문서 생성" 자체를 Client 에서 한다는 차이가 있음
>>>>>>> 여기까지만 알면 됨 시험에서는. Envelop 기법에 대해 살펴볼건데, 이하내용은 시험에 안나옴
> SDK 가 GenerateDataKey 를 호출한다. CMK 를 사용할거고 IAM 권한 확인함 (동일)
> 권한이 있다면 "KMS 는 Data Key 를 작동시킨다" (CMK 로 Data Key 를 만드는건가봄?)
> 그러면 "PlainText of Data Key Encryption" 을 받게되는데, 이걸 DEK 라고 부른다
>> 참고로 받을때 이 DEK 가 암호화되어 있는 파일도 받게 된다. (어차피 필요한건 Plaintext 긴 함)
> 이 DEK 를 사용해서 Client 측에서는 직접 암호화를 수행한다
> 그러면 이제 Encrypted File 을 가지고 있는 것 (Plaintext DEK 로 암호화)
> 이제 Final File 을 준비하는데, 이게 바로 Envelope 의 역할을 한다 (Wrapper)
> 이 Final File 에는 1) 아까 받았던 "암호화된 DEK" 2) Client 가 만든 Encrypted 정보를 저장함
> 복호화하는 방법도 알아보자. 일단 아까 Envelope File 은 있는 상태이다 (공유받은 고객 같은 느낌)
> Decrypt API (얘는 4KB 안나눠져있음, 요청한거에 대해 수행함) 를 사용한다. 이 때 요청하는 것은 "암호화된 DEK 를 님이 가진 CMK 키로 복호화해서 PlaintextDEK 내놔라" 이다.
> 그럼 KMS 는 권한을 확인한 뒤 CMK 를 통해 DEK 를 복호화해서 PlainText DEK 로 전달한다
> 그럼 Client 는 이 PlainText DEK 를 통해 아까 Envelope 에 있던 "Encrypted File" 을 복호화할 수 있게 되는 것!!
>> 전체적인 목적 : KMS 는 지가 잘하는 키 관리 / 생성을 하는 일만 하고, 주요 암호화/복호화는 Client Side 에서 직접하는 것에 목적을 두고 있음 (CPU 를 직접 사용)
< Encryption SDK >
> 위 Envelope 과정은 매우 복잡하니~ AWS 에서 SDK 를 만들어서 제공해준다
> Encryption SDK 는 CLI Tool 로 설치해서 사용할 수 있고, Java / Python / C / JS 등에서 implement 할 수 있다
> 이 SDK 에는 Data Key Caching 이라는 기능도 제공한다
>> 매번 Object 를 암호화할 때마다 Data Key 생성하고 ㅈㄹㅈㄹ 할게 아니라, Data Key 를 재사용 하는 것
>> KMS API 호출을 줄이는 좋은 수단이지만, Security 품질로 봤을 때는 안좋아지는게 사실 (Trade off) - Throttling 오류 발생시 해결방안 중 하나
>> 근데 실제로 많이 사용된다
>> LocalCryptoMaterialsCache 라는 것을 사용하면 되는데, max age, max bytes, # of msg 등은 직접 구성하여 설정할 수 있다
< 시험을 위해 기억할 것 정리 >
> Encrypt API - KMS 로 4KB 이내의 데이터 암호화해줌
> GenerateDataKey API - Envelop 방식에서 사용됨. Unique 한 대칭 Data Key 를 생성해줌 (DEK)
>> 결과는 두가지로 반환됨 1) Plaintext of DEK, 2) 암호화된 DEK (1번을 우리가 지칭한 CMK 로 암호화 한 것)
> GenerateDataKeyWithoutPlaintext API - 말그대로 위 API 랑 똑같은데 1번 안주는거임 (나중에 사용을 위함)
>> 시험에서 물어볼 수 있는 것: 당장 쓸건데, WithoutPlaintext API 쓰면 되지?? 이러는거임. 이건 틀렸음. 당장 쓸거면 GenerateDataKey API 를 써야 함
>> 암호화를 위해서는 Plaintext 가 필요하기 떄문!!!!!
> Decrypt API - 4KB 이내의 데이터를 복호화한다. (DEK 도 포함)
> GenerateRandom : random byte string 을 전달해줌 (갑자기 웨..?)
---------------------------------------
<431 Encryption SDK 실습 - SDK 쓰니까 4KB 넘어도 됨 - 걍 대충 설명함>
> CLI Tool을 설치했음 (과정을 보기 위함이지, 명령어 시험에 안나옴)
> 사용할 CMK 의 ARN 을 사용해서 encrypt 명령어를 수행한다
>> 참고로 output 은 output 폴더 만들어서 이쪽으로 지정해놓음 (명령 수행에 대한 metadata 도 만드는데 output 이랑 동일한 폴더에 저장될 수 없다고 함)
> metadata 를 구경하면 JSON 이 나오는데, 사용한 암호화 알고리즘, Encrypted Data Key 도 나옴
> output 폴더에 저장된 결과를 보면, 읽어보면 암호화되어 읽기 어려운 바이너리 파일이 튀어나옴
> decrypt 를 반대로 수행, 똑같이 키는 알아서 인지함
> Encryption SDK 로 4KB 이상의 파일을 편하게 암호화 / 복호화 했음 (KMS Involved)
---------------------------------------
<432 KMS Request Quotas - 한도>
> KMS API 에 대한 한도를 넘기면, Throttling Exception 을 받게됨
> 주의 : KMS 는 어떤 cryptographic operation 에 대해서는 한도를 공유한다 계정간 리전간 전체공유
> AWS 에서 이루어지는 어떤 요청 (직접이 아니더라도, S3가 SSE-KMS 를 사용한다든가..) 은 이 키를 쓰기 때문에, 할당량에 포함되는 것!
> 해결법 (기억!!) - 3가지 기억
>> Exp Backoff - 지수적으로 증가하는 시간을 두고 Retry 진행
>> GenerateDataKey API 를 사용 중이라면 DEK 캐싱을 쓸 수 있다 (Encryption SDK)
>> AWS 고객문의 혹은 API 호출을 통해 한도 증가를 할 수 있다 (Request Quota Inc)
---------------------------------------
<433 람다와 연계 실습>
> 파이썬 람다 생성, 람다 내에서 환경 변수 Encryption 을 해볼 것임 (CMK 사용)
> 사용하는 이유 예시 (람다에서 보안이 필요한 값을 사용해야 할때)
db_password = "SuperSensitiveInfo"
def lambda_handler(event, context):
db_connect = connect(db_password)
return {
'great!'
}
>> 람다에서 DB 에 접근하는데, DB Password 가 필요한 경우
>> 누군가 람다에 접근하면, DB 비번을 볼 수 없게 해야한다! 그래서 환경변수에 넣을 수도 있겠음.
>> 근데 그냥 환경변수에 넣어도, 누군가 람다 구성 접근을 한다면, 비번을 바로 알게됨 (개발자 권한으로는 DBA 가 관리하는 DB에 비번을 몰라야 할 수도 있음)
>> 람다에서 환경변수 설정에서 Encrypt 하는 탭이 있음
>> 여기서 CMK Key 를 선택할 수 있다! 그럼 Encrypt 되어서 저장된다 (이건 유저 권한이 필요한거라, 람다가 쓰는게 아님)
>>> 값에도 Encrypt 된 text 가 보여지게 된다
from base64 import b64decode
ENCRYPTED = os.environ['DB_PASSWORD']
# 위에서 API 쓸 때와 비슷한 설정들을 볼 수 있다
DECRYPTED = boto3.client('kms').decrypt(
CiphertextBlob=b64decode(ENCRYPTED),
EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']}
)['Plaintext'].decode('utf-8')
def lambda_handler(event, context):
// do_things
return "great!"
>> Decrypt secrets snippet 이라는게 있는데, 복호화하기 위한 코드가 제공된다. 따라서 이걸 복사해서 람다에 넣어주면, 실제 DB에게 전달할 땐 DECRYPTED 변수를 넣어주면 된다 (코드에도 노출 안되고, 환경변수 설정에서도 확인할 수 없음)
>> 이 코드에 EncryptionContext 를 설정해주는 부분이 있는데, "이 람다 함수가 Operation 을 수행할 것" 이라고 하는 부분 - 이 람다 함수는 분명히 KMS Key 를 이용할 권한이 아직 없음
> 이걸 Test 하면 권한이 부족함. Permission 으로 이동해서 Role 에 가서 Inline Policy 를 Role 에 추가한다
>> KMS 에 대한 DECRYPT API 권한을 준다. (허용하게 할 Key ARN 을 명시)
>> Inline Policy 는 약간 1:1 처럼 보조해주는 권한 느낌임.
> 로그를 보면 실제로 잘 해독한걸 볼 수 있음 (당연히 실제로는 로그에 해독한걸 출력하면 안됨)
---------------------------------------
<434 S3 Bucket Key>
> SSE-KMS 암호화를 사용하는 경우 S3 버킷 키 사용 기능
> S3 에서 KMS 에게 API 호출하는 횟수를 99% 가량 줄일 수 있는 기능 (비용절감가능)
> DATA KEY 를 사용함 (S3 버킷 키를 생성)
> CMK 로 S3 버킷 키를 만듬
> 객체를 암호화하는데 CMK 를 계속 호출해서 쓰는게 아니라 S3 버킷 키를 사용해서 많은 양의 Data Key 를 만듬 (envelope 기법 사용)
> API 가 적게 사용되므로 KMS CloudTrail 로그도 적음
> S3 구성하다가 Encryption 부분에서 KMS-AWS Managed Key 선택 - Bucket Key 활성화 가능 (기본적으로 ON)
-----------------------
<435 KMS 키 정책 예시 및 IAM 보안 주체>
> Key Policy 는 너의 KMS 키에 접근/관리 권한이 있는 사람을 정의할 때 사용한다
> 아무것도 설정 안하면 Default KMS 키로 적용
> 이 기본 정책은, "계정에 속한 사람 누구나 IAM 권한이 있다면 KMS 키에 접근 가능" 임
> 직접 제어하면 특정 User, Role, Federated User 등에게 부여할 수도 있음 (위 우측)
>> 어떤 KMS 액션들을 허용하는지도 확인할 수 있음
> 참고로 Principal 로 명료하게 사용가능성이 확인된 User 는 추가적인 IAM Policy 가 필요 없음 (지난번에 배운 IAM 에 대해 생각해보면, 합쳐서 평가함. 명시적인 허용이 하나에라도 있으면 된다고 배웠음)
<명시적 허용 설정들 - Key Policy 혹은 IAM 에>
> AWS Account & Root User
>> AWS:: 계정번호
>> AWS:: 계정IAM:root
>>> 이런식으로 해두면 해당 계정 내의 모~든 보안 주체 권한이 부여됨
> 특정 IAM Role 을 Role ARN 을 명시적으로 적으면서도 허용 가능
> IAM Role Session 도 명시적으로 허용 가능, (Assumed Role, Federation - Cognito Identity, SAML 등)
> 당연히 IAM User 명시적으로 설정 가능 - AWS::계정번호:user/{user_name}
> FederatedUser Session 명시적 설정 가능
> 특정 서비스만 명시적 허용 가능
> 모든 서비스, 모든 사용자에게 키 사용 허용도 가능
-----------------------
<436 Cloud HSM>
> KMS 가 SW 암호화를 지원하는 키를 관리해준다면, HSM 은 encryption HW 를 지원한다
> HSM (HW Security Module) 을 프로비저닝 해준다
> 이 때는 AWS 가 아닌, 우리 스스로 Encryption Key 를 관리한다
> HSM 은 AWS 클라우드 내에 설치되지만, (FIPS 104-2 레벨 3 규정?? 을 준수한다고 함) 변조 방지 기능 (tamper-resistant) 이 있다
>> HSM 장치에 수동 접근 금지. 수동 접근 시도시 HSM 중지 및 사용자 차단
> 대칭키 비대칭키 모두 지원 (SSL 키도 사용가능)
> Client 측도 특정 Client SW 를 사용해야 하며 꽤 복잡함. Free Tier 없음
> DB 암호화 및 키 관리에 HSM 을 활용하려면 Redshift 계열은 Integration 을 지원함
> S3 보안에 SSE-C 레벨의 암호화를 구현하려는 경우 매우 적합함
>> Customer- 키관리 쪽 말하는 듯. HSM 은 스스로 암호를 관리해야 하기 때문인듯
> HSM 은 서비스와 독립적으로 돌아감
> Client 측에서는 Cloust HSM SW 를 켜야 둘이 Connection 이 형성되어 Key 관리를 시작할 수 있다
>> Manage Key, Manage User, Manage Permissions
> Client 측은 다음과 같은 IAM Permission 필요
>> CRUD an HSM Cluster
> KMS 에서는 모든 권한이 IAM 으로만 이루어진다는 점에서 차이점이 잇다고 하는데 이것도 뭔소린지 잘 모르겠음
<High Availability>
> HSM Cluster 는 Multi-AZ 에 흩어져 있어서 HA & Durability 를 보장함
> 두 AZ를 사용하면 한 AZ 에 있는 HSM 을 다른 AZ에서 복사해둠. 그리고 Client 는 둘 중 하나를 사용
<HSM 과 AWS 서비스 Integration>
>KMS 를 통해서 통합한다
>KMS 에서 KMS Custom Key Store 을 정의하고, 이것을 Cloud HSM 으로 사용함
>> EBS, S3, RDS 등 다양한 서비스들이 CloudHSM 보안을 받을 수 있음
> HSM 클러스터 생성하고, KMS 를 등록하며 Custom Key Store 를 정의 - 이걸 HSM 으로 지정
> 이 KMS 를 통해 RDS DB 인스턴스 생성 / EBS Volume Encryption 연계 등을 하면, 이 KMS 암호화는 HSM 내의 암호화 키를 사용하게 됨
>> Client 와 HSM 간의 Key 관리와는 별개인걸 이해해야함. 사용과 관리는 별개
>> 장점 : HSM 을 쓸 수 있다는게 장점 / CloudTrail 로 KMS 연계가 되어 API 호출들에 대한 로깅 가능 /
<HSM vs KMS>
> KMS 의 키 종류는 3가지 HSM 은 1가지
> HSM 에서는 Hashing 이 하나 더 있음
> Key 접근성 : KMS 는 Region 단위로 접근 제어, HSM 은 VPC 에 배포되므로 VPC Peering 으로 공유 가능
> 암호화 가속화(빠르게 하는건가) : KMS 없음, HSM 에서는 SSL/TLS 가속화 (LB 영역) 가능, 오라클 기반 DB 가속화도 사용 가능
> 접근 & 인증 : KMS 는 IAM 만 사용, HSM 은 자체 보안 메커니즘 사용 (직접 사용자 생성 및 권한/키 관리)
> 고가용성 : KMS 는 AWS 관리형 서비스, HSM 은 AZ 에 overall 가능
> Audit : HSM 은 MFA 지원도 됨
> KSM 은 프리티어 영역
-----------------------
<437 SSM Param Store>
> AWS System Manager 에 소속된 변수 공유 저장소 (SSM - AWS System Manager)
> Secret 정보 / Configuration 을 위한 안전한 저장소
> 민감한 정보를 암호화하여 싶다면 KMS 를 통한 암호화 후 저장까지 가능
> SDK 도 있고, 서버리스, 확장성 및 내구성 있음
> 구성 업데이트 시 버저닝된다
> IAM 으로 보안 적용 가능, EventBridge 로 알림가능
> CF 와 연계 가능 (CF 가 스택에서 매개변수로 SSM Param Store 을 사용할 수 있음)
>앱이 구성을 평문으로 저장 요청 -> SPS 가 권한 확인 후 구성 데이터 암호화 함.
>> 이 때, KMS 를 사용해서 암호화함 (encrypt & decrypt)
>> 따라서 앱이 서버 내부에 있는 KMS 키에 대한 Access 권한이 필요 (ex: 람다 함수에서 SSM Param 으로 부터 가져옴 등)
< SSM Param Store Hierarchy>
> 저장할 변수들을 계층화해서 저장 가능
> 변수들을 구조화해서 관리가 쉽게 할 수 있고, IAM Policy 앱들에게 부여할 액세스 권한 정의시 보다 Fine-grained 하게 적용 가능 (특정 dept, 특정 app 수준)
> 참고로 Secret Manager의 Secret 정보(?) 를 SSM 을 통해 가져오고 싶다면(??) 다음과 같은 경로에서 가져올 수 있다
>> /aws/reference/secretsmanager/secret_ID_in_Secrets_Manager
>> AWS System Manager (SSM) 자체도 메타데이터를 param store 에 저장할테니 그걸 가져올 수 있다는 것인듯
> Public Parameter 사용 가능 - AWS 에서 발행한 것들을 사용 가능
>> ex :: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
>> 특정 리전에서 사용할 수 있는 최신 linux 2 AMI 를 찾을 수 있는 경로, 이 경로로 API 를 호출해서 가져올 수 있음
> 위 그림처럼, 람다에서 SSM 에 접근해서 GetParameter/GetParametersByPath API 를 사용할 수 있음
> 각 람다는 각 app 내 특정 env 에 대해서만 권한이 있을 수 있다
<SSM Param Tier>
> 파라미터 크기 차이 있음
> Param Policy 사용 가능 여부
<Adv Tier 내의 Parameter Policy>
> 각 파라미터 단위로 TTL 을 설정 가능 - 민감한 Data (PW 따위) 등에 대한 update / delete 강제화 가능
>> 가령, DB PW 를 만료되게 하고, TTL Expiration 응답을 시키면, 관리자는 강제로 DB PW 업데이트 해야함
> 여러 Policy 적용 가능
> 1번은 삭제를 위한 만료 정책. 그 시간이 되면 그 Param 을 삭제해라
> 2번은 Event Bridge 연계 Policy. 만료 및 삭제되기 15일 전에 나한테 알람을 오게 하라
> 3번은 일정 기간마다 갱신하고 싶은데, Noti 받고 싶을 경우 20일마다 나한테 알려주라는 Policy
-----------------------
<438 SSM Param Store 실습>
> AWS System Manager (SSM) 으로 이동하면 좌측 탭에서 찾을 수 있음
> UI 콘솔로 Parameter 추가 가능 (아무렇게나 추가)
> /my-app/dev/db-url 이름으로 저장 (S3 처럼 프리픽스로 활용되는 듯), value 로는 dev.db.com:3306 으로 함
> Param 을 수정하면 updated at 이 최신화되고, Version 이 업데이트 된다
> /my-app/dev/db-pw 로 저장, value 는 SecureString (암호화적용, KMS 내부적으로 사용됨, 권한 이슈 체킹 필요) - 근데 할 때 다 선택할 수 있음, "SAMPLE_PW"라고 입력 - 권한은 콘솔에서 사용시 다 만들어주는듯.
> /my-app/prod/db-pw, url 도 똑같이 만듬
> CLI 를 통한 액세스를 해보자
> (강의에서 봤던 모습 기억하기, getParam 했는데 Azd9fu2098jfcoaejfg983yh9fh/sdflkjsolfejh8i 이런식으로 온거)
> $aws ssm get-parameters -name {param_name1} {param_name2} ...
>> 그러면 저장된 변수들이 오는데, db-password 같은 경우는 암호화된 데이터가 전달된다 (KMS 암호화된 상태로 저장되기 때문)
>> 사용하려면 직접 해독하거나, --with-decryption option 을 추가해야함
>> 위 명령어에 이 옵션 추가시, 명령어를 날리는 Client 가 저 암호화된 키 (자동인지) 를 사용하여 decrypt 할 수 있는 권한이 있는지 체크하게됨
>> 권한이 당연히 있으니, PW 가지 raw_test 로 전달된다
> $aws ssm get-parameters-by-path 를 사용할 수도 있음, 뒤쪽에 path value 를 줄 수 있음
> $aws ssm get-parameters-by-path --path /my-app/dev/
>> dev 경로 이하에 있는 모든 parameter 들이 당연히 전달된다 (secure 옵션은 동일함) - PARAM 구성시 Tree 구조가 유용한 이유
-----------------------
<439 SSM Param Store 실습 - WITH LAMBDA (SDK)>
> Lambda 를 만든다
> SSM Param Store 에서 읽기 쓰기 할 수 있는 권한을 Lambda Execution Role 에 추가해준다 (안쓰고 하면 당연히 권한 오류 발생함)
>> SSM 에 대한 GetParameters/~ByPath API 권한 추가, Specific Resource 명시 후 ssm-paramater 중 /my-app/* 에 대한 권한 추가함 (굉장히 fine-grained 한 편) - 이런 단일성은 Inline Policy 로 많이 추가
> 코드를 다음과 같이 추가
import boto3
ssm = boto3.client('ssm', region_name="eu-west-3");
def lambda_handler(event, context):
db_url = ssm.get_parameters(Names=["/my-app/dev/db-url"]) # SDK 쓸 때랑 걍 똑같이 직관적인 사용법
db_password = ssm.get_parameters(Names=["/my-app/dev/db-password"])
print(db_url + "," + db_password)
return 'worked'
> 아까 처럼 db-url 이 출력되고, db-password 가 출력되는데, SecuredString 이란 type 과 암호화된걸 볼 수 있음
> 아까처럼 WithDecryption=true 라는 옵션을 get_parameters 함수에 추가함
> 진행하면 에러가 뜰텐데, 그건 KMS 에 대한 Decryption 접근 오류가 있기 때문 (중요!!)
> 람다가 SSM Param 에서 가져온 값과는 별개로, KMS Decrypt API 를 활용하려고 하기 때문
> 다시 Execution Role 이동
> Role 에 대해 Inline Policy 또 추가, (Inline Policy 는 이렇게 재사용 없게 하는 1:1 느낌이 강함!!)
> KMS 에 대해, Decrypt API 권한만 추가, Resource 는 명시적으로 사용하는 CMK 의 ID 를 적어줌
> 이제 시도해보면 정상적으로 동작함!
> 람다에서 환경변수로 사용할 수 있는 trick
> 함수 자체에 DEV_OR_PROD 라는 환경 변수 추가. DEV 용 람다에는 dev 라고 적고, PROD 용 람다에는 prod 라고 적음 (한 함수로 각자 자신이 가져올 parameter 들을 유동적으로 설정 가능)
> 함수를 다음과 같이 변경
...
sam = boto3.~~
dev_or_prod = os.environ['DEV_OR_PROD']
def lambda_handler:
db_url = ssm.get_parameters(Names = ["/my-app/" + dev_or_prod + "/db_url"]
...
> 이런식으로 하면 PROD, DEV 용 람다에서 각자 자신의 Path 를 사용할 수 있고, 더 나아가 각자에게 필요한 권한만 주어서 fine-grained 한 관리가 가능하다
-----------------------
<440 Secrets Manager>
> 비밀 정보 저장을 위한 Service (SSM 이 Secret Manager 가 아님!!)
> N일마다 secret 정보가 순환되도록 강제할 수 있음
>> 더 강한 Secret management schedule
> 따라서 람다 함수와 연계하여 Rotation 을 위한 Secret Generation 을 자동화 할 수 있음
> AWS RDS 서비스들과 Integration 이 좋음 (MySQL, PostgreSQL, Aurora 등)
> 비밀 정보들은 KMS 를 이용하여 저장된다 (암호화는 역시 알아서 선택! ㅋㅋ 스케줄링만 해주는 것)
> 시험에서 [Secret 정보, integration with RDS, Aurora Secrets] 등등이 나올 때는, Secret Manager 를 생각해라
<Secret Manager - Multi-Region Secrets>
> 여러 지역에 걸쳐서 Secret 정보를 복제 가능
> SM 은 지속 원본과 동기화를 해준다
> 사용 이유 1: a 지역에 문제가 생길 경우, b 지역에 있는 Replica 를 독립적인 secret 으로 분리시켜 사용 가능
> 사용 이유 2: Multi-Region App 으로 사용할 수 있음
>> 그 밖에 재앙 대체 전략으로도 가능, RDS 가 유사하게 복제되어 있다면 똑같은 복제된 Secret 을 써서 통합 가능 등등 생각하는 것들 그대로 ㅇㅇ
-----------------------
<441 Secrets Manager 실습>
> 사실 전체적인 아이디어는 동일. Secret 정보를 Store 에 저장하고 다른 곳에서 Runtime 시 사용한다는 것
> RDS 와의 통합, Manage Scheduling 강화 정도의 측면이 추가된 것
> 생성시 설정할 수 있는 여러 통합 솔루션이 잇지만, 간단하게 Secret 저장을 하면 바로 n 개를 추가해볼 수 있음
> 사용할 KMS 키 선택 가능
> Key Automatic Rotation 활성화 가능
>> 회전 주기 설정 가능 / 회전에 사용할 Lambda 함수 지정 가능 (새로운 secret 들로 직접 refresh 해서 넣어줘야 함)
>> 회전 주기마다 자동으로 람다를 실행시켜 줌
> 시크릿 정보를 가져올 수 있는 샘플 코드와 코드내 예외들도 구경할 수 있다
<만약 처음에 RDS DB 를 선택했을 경우>
> 기본적으로 RDS DB 에 대한 name / password 를 secret 에 저장하도록 함
> 해당 정보를 활용하여 DB Instance 연결을 해주기도 하는 듯
-----------------------
<442 SSM Param Store VS Secret Manager>
> 후자
> 더 비쌈. 후자는 RDS, RedShift, Document DB 에 대해서는 자동 람다 함수를 제공해준다
> KMS 암호화가 필수, CF 와 연계 가능
> 전자
> 간단한 API, 조금 더 wider 한 Use Case
> 시크릿 rotation 이 기본적으로 있는건 아님 (물론 알아서 쥐어짤 수는 있음)
> KMS 암호화가 선택사항, CF 와 역시 연계 가능
> SM secret 들을 SSM Param Store API 로도 뽑아낼 수 있다
> Secret Manager 자체에서 람다 함수를 자동 호출 스케줄링 할 수 있다
>> ex : RDS 비밀번호를 30일마다 바꾸도록 람다 함수를 짜서 이걸 호출
>> RDS 비밀번호 rotation 정도는 AWS 에서 제공해주는 람다 함수 사용 가능 (당연히 직접 해야 하는 것도 많음)
> SSM Param Store 의 스케줄링은 native 한 기능이 아니다
> EventBridge 따위로 활용할 수 있다 (30일마다 invoke 하는 event 작성)
>> change value at SSM Param Store 과 직접 RDS 비밀번호를 변경하는 Lambda 함수를 직접 작성해야 함
-----------------------
<443 CW Log 암호화 >
> CW Log 를 KMS Key 로 암호화 할 수 있음
> Encryption 은 Log Stream 이 아닌, Log Group 단위에서 발생한다
> CW Console 에서 CMK 와 Log Group 을 연결할 수는 없음
>> CLI 와 SDK 에서 CW Log API 를 사용해서만 연동할 수 있음
>>> $ associate-kms-key : 현존하는 Log Group 과 KMS 키를 연동하는 것
>>> $ create-log-group : log group 이 존재하지 않을 경우 생성해 KMS 키와 연동함
<실습>
> CW 에서 Log Group 을 확인하는데, 하나 들어가보면 KMS Key ID 는 비어 있고, 이걸 설정할 곳이 UI 어디에도 없음
> 밖에서 CLI 를 사용해봄
> $ aws logs associate-kms-key --log-group-name {log_group_name} --kms-key-id {key_arn} --region {region_name}
>> 현존하는 Log Group 과 지정한 KMS Key 를 연계하여 암호화를 적용
>> 사용하면 오류가 남 : 이 Log Group 에 KMS Key 가 사용되도록 허가되지 않음 (Access Denied 뜸)
{
"Version" : "2012-10-17",
"Id" : "key-default-1",
"Statement" : [ {
"Sid" : "Enable IAM User Permissions",
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::Your_account_ID:root"
},
"Action" : "kms:*",
"Resource" : "*"
},
{
"Effect": "Allow",
"Principal": { "Service": "logs.region.amazonaws.com" },
"Action": [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
],
"Resource": "*"
}
]
}
> 따라서 Key Policy 를 적용해줘야 한다 (적용 안하면 Default 기 때문에 현 User 가 Permission 없으면 AD 뜨는것) - KMS Key Policy 를 적용하는 좋은 예시
> 위와 같은 Key Policy 를 추가하여, CLI 를 사용하는 현 유저가 접근할 수 있도록 하고, logs 에서 사용할 수 있는 권한을 추가 함 (세부 내용은 구체적으로 알 필요 없을듯)
> 명령어를 다시 실행하면, Console 에 KMS Key ID 가 적용되어 있는 모습을 확인할 수 있다
>> 즉 CW Log 들은 encryption 되어서 at rest 상태로 있는 것
> 두번째 create-new-group 명령어를 실행해봐도, 동일하게 새로운 로그그룹이 생성되고, KMS KEY ID 가 적용된 상태임을 확인할 수 있다
-----------------------
<444 CodeBuild Security >
> CB 는 기본적으로 VPC 외부에서 생성되기 때문에, VPC 내부에서 사용하기 위해 내부 생성 설정이 필요
> CodeBuild 의 Secret 보관
>> 당연히 CodeBuild 환경변수에 PlainText 로 보관하면 안됨
>> 환경 변수가 SSM Param Store 참조 하거나 SM 을 참조할 수 있음
>> 당연히 CB의 IAM 이 SSM Param Store 혹은 SM 에 대한 접근 권한을 가지고 있어야 함
> CB 로 가서 Additional configuration 으로 이동
> 여기서 VPC 내부 생성을 할 수 있음
> 아래 환경 변수 설정 가능
>> 가령, RDB 에 접근해야하는데 RDB PW 가 필요함
>> 환경변수 Type 에서 보안 정보는 Parameter / Secret Manager 중 선택 가능 (당연히 미리 생성되어 있어야)
>> Value 로는 그냥 Param 이름 (경로가 포함된 이름) 을 기입해주면 됨
>> SM 을 선택할 경우도 완전히 똑같이 하면 됨
--------------------------------------
<445 AWS Nitro Enclaves>
> 클라우드 내에서 매우 민감한 Process 를 하고 싶어 완전 독립되어 고립된 환경에서 실행하고 싶을 수 있음
> ex 개인 식별 데이터, 금융 처리, 신용카드 처리 등등
> 이걸 하고 싶으면 VPC 를 새로 파고, 네트워크 제한을 직접 제어하고 등등을 해야 했음
> 솔루션 : Nitro Enclaves
> Fully isolated and highly constrained
>> 컨테이너 X, Storage X, 교류하는 형태 X, 외부 네트워킹 X
>> 민감한 Data Process 만을 하기에 최적인 공간
>> EC2 에 적용할 수 있는 가장 높은 수준의 보안
>> Cryptographic Attestation - 암호화 증명을 사용해서 authorized code 만 Enclave 에서 Process 되도록 할 수 있음
<그림>
> Nitro-based EC2 인스턴스 실행, EncalveOption 활성화
>> EC2 내에서 nitro enclave 실행 가능
> Nitro CLI 를 활용해서 실행할 App 을(?) Encalve Image File (EIF) 로 컨버팅 진행
> 이 EIF 파일을 input Data 로 사용해서 NitroCLI 를 통해 인스턴스 내에 Enclave 를 생성 (띄우는 명령어를 쓰는 듯)
> Enclave 를 생성하면, 완전히 독립된 VM 으로서 동작하여, 자체 Kernel, Memory, CPU 를 가지고 운영된다 (진짜 VM 같음)
< 아래 그림>
> EC2 Host 를 아까 말했듯이 "Nitro-Based" 로 실행하면, Nitro-Hypervisor 가 실행중이다
> EC2 인스턴스가 Nclave 로부터 분리됨 (둘은 오직 Secure local channel 로만 통신함)
> 동일한 host 내의 다른 Instance 들과도 분리됨
>> EC2 Host vs EC2 Instance..?!
----------------------------------------
<퀴즈>
====================================================================================
교육 출처
- AWS Certified Developer Associate 시험 대비 강의 - Udemy
'웹 운영 > AWS' 카테고리의 다른 글
[AWS] Certified Developer - Associate (DVA-C02) 자격증 후기 (1) | 2025.01.25 |
---|---|
[CDA] 섹션 31 - 기타 서비스 (0) | 2024.11.04 |
[CDA] 섹션 29 - 고급 자격 증명 (0) | 2024.10.21 |
[CDA] 섹션 28 - 기타 서버리스 : Step Functions & AppSync & Amplify (0) | 2024.10.10 |
[CDA] 섹션 27 - 유저가 누군지 알아보는 Cognito (0) | 2024.10.06 |