아마존, KMS, Lambda and API Gateway

By | 2017년 7월 31일

아마존의 KMS를 이용하여 암호화 하는 방법은 2가지 방법이 있습니다.

첫번째는 마스터키를 가지고 암호화 복호화 하는 방법입니다.

두번째는 마스터키를 가지고 DataKey를 요청해 DataKey로 암호화/복호화 하는 방법입니다. DataKey를 요청하면 암호화된 DataKey와 평문 DataKey를 리턴해 줍니다.
평문 DataKey로 암호화를 한 후 암호화된 DataKey는 잘 보관하고 있다가 복호화 해야할 시점에 KMS로 암호화된 DataKey를 전송해 평문 DataKey를 받아서 복호화 하는 형태입니다.

여기서는 첫번째 방법으로 해보겠습니다.

별도의 암호화 복호화 서버를 이용하지 않고 Lambda로 암호화 복호화 Function을 만들고 API Gateway로 API URL을 생성하는 형태입니다.

순서는 크게 다음과 같습니다:

  1. KMS에 마스터키 생성 (IAM 메뉴에 포함되어 있네요.)
  2. Lambda Function 생성
  3. API Gateway 연결
  4. Route53 도메인 연결

중간 중간에 권한을 설정 하는 부분이 있는데 이 부분만 헤매지 않는 다면 어렵지 않습니다.

1. KMS에 마스터키 생성

IAM -> Encryption keys -> Create Key 를 선택합니다. 
(참고로 저는 Asia/Seoul Region에 생성했습니다.)

2. Lambda Function 생성

AWS Lambda -> Create a Lambda function 을 선택합니다.
(이때 주소창에 접속된 Region을 잘 기억해 두세요. 제 경우는 ap-northeast-2 네요.)

여러가지 템플릿이 나오지만 단순한 암호화/복호화 Function 만 만들것이므로 Blank Function을 선택합니다.

trigger를 선택하는 화면이 나오지만 일단은 NEXT.

마지막 단계로 Function 이름과 설명, 코딩에 사용할 Runtime 언어를 설정합니다.
(저의 경우 Runtime 언어를 Python 3.6으로 선택했습니다.)

일단 코딩은 나중(?)에 하고 Function 설정부터 하겠습니다.

Lambda function handler and role 에서 Role 항목을 “Create new role from template(s)”를 선택합니다.

그런 다음 Role name에 생성할 Role 이름을 입력합니다.

Advanced settings에서 KMS key 항목에서 1단계 에서 생성 하였던 KMS key를 선택합니다.

그런 다음 NEXT (다른 항목들은 필요에 따라 변경하시면 됩니다.)

최종적으로 생성될 Function 정보를 확인 후 Create Function 버튼을 눌러 생성을 완료합니다.

생성이 완료 되었으면 이제 코딩을 시작하면 됩니다.
(급히 막 코딩해서 일부 버그가 있을 수 있습니다. 참고용으로만 써주세요.)

소스코드를 보면 아시겠지만 복호화 할때는 KMS key가 필요하지 않습니다.
아마도 암호화된 문장안에 관련 정보도 포함되어 있는듯 보입니다.

저장 후 코드 테스트는 API Gateway로 해보겠습니다.

3. API Gateway 연결

API Gateway페이지로 이동 후 API생성 버튼을 눌러 새 API를 생성합니다.

API 이름 및 설명은 적당히 써줍니다.

생성 후

작업 버튼을 눌러 ‘메서드 생성’을 선택합니다. 메서드는 POST를 선택합니다.
생성 후 POST를 선택하면 오른쪽에 통합 포인트를 선택하는 화면이 나옵니다.
여기서 Lambda 함수를 선택하고 Lambda 리전에 Lambda 만들선 선택한 리전을 선택합니다.
선택 후 생성하였던 Lambda 함수를 입력해줍니다. 그리고 저장.
이때 Lambda 함수에 API Gateway을 부여하는 확인창이 나오는데 여기서 확인을 선택합니다.

위에서 만들었던 Lambda 함수를 테스트하기 위해 ‘테스트’ 버튼을 누릅니다.
그러면 아래와 같이 테스트 할 수 있는 화면이 나옵니다.
요청본문에 json 형태로 아래와 같이 입력하고 테스트 버튼을 누릅니다.

응답 본문에 보면 myTestFunctionRole에 kms:Encrypt 를 실행한 권한이 없다는 에러 메시지가 보입니다.
에러 해결을 위해 권한을 부여해 보겠습니다.

IAM 페이지로 이동해 Roles메뉴를 선택합니다.
그리고 오른쪽에서 Lambda Function 생성시 생성한 Role를 선택합니다. 제 경우는 myTestFunctionRole 이라고 만들었기때문에 myTestFunctionRole을 클릭 했습니다.

Permissions 탭에 Inline Policies 부분을 펼친 후 There are no inline policies to show. To create one, click here. 부분에 click here를 눌러 새 Policy Generator를 선택 후 Select 버튼을 누릅니다.

위와 같이 선택 후 Add Statement 버튼을 눌러 추가합니다. 그리고 Next Step.

Review Policy 에서 확인 후 Apply Policy 버턴을 누릅니다.

이제 다시 API Gateway로 이동 후 다시 테스트 해 봅니다. 정상적으로 동작하는 것을 볼 수 있습니다. (똑같이 권한 오류가 날 경우 조금 기다려 주세요. 권환 설정 저장 후 Lambda Function 적용되는데 몇십초 정도 걸리는듯 합니다.)

다음으로 리소스를 선택 후 POST 를 선택합니다. 작업 메뉴에서 API 배포를 선택하여 배포단계는 ‘새 단계’를 선택하고 단계 이름에는 적당해 배포 단계 이름을 넣어 주세요. 제경우는 release 라고 입력했습니다.

4. Route53 도메인 연결

도메인을 연결하기 전에 먼저 API Gateway에서 배포 도메인 주소를 생성해야 합니다.

API Gateway 에서 사용자 지정 도메인 이름으로 이동 후 사용자 지정 도메인 이름 생성 버튼을 눌러 새로 생성합니다.

도메인 이름에는 사용할 도메인 이름을 쓰고, ACM 인증서를 선택합니다.
기본 경로 매핑에 경로는 안써주셔도 되고(URL 중간에 사용될 경로입니다.) 대상에는 생성한 Lambda Function을 선택하시고 배포단계는 위에서 생성하였던 이름을 선택해 줍니다. 그리고 저장!!

한참을 기다리면 배포 도메인이 생성됩니다. (오래걸리니 다른것을 하는게 정신건강에 좋을듯 합니다.)

배포 도메인 이름을 복사해 둡니다. Route53에서 써야 합니다.

이제 Route53으로 이동합니다.

Hosted zones로 이동하여 대상 도메인을 선택합니다. Create Record Set를 눌러 오른쪽에 서브도메인 명을 입력하고 Type 에는 A — IPv4 Address를 선택합니다.
Alias에서 Yes를 선택하고 Alias Target에는 API Gateway에서 생성한 배포 도메인을 입력하고 Create 버튼을 누르면 됩니다.

몇분 후 해당 도메인으로 테스트를 해보면 됩니다. (DNS 설정에 따라 시간이 조금 걸릴 수도 있지만 새로 생성한 서브도메인이라면 금방 될 것 입니다.)

마지막으로 KMS 사용 시 몇가지 고려할 점이 있습니다.

  • Lambda Function을 통한 대량의 실시간 암호화 복호화는 부적합하다. 
    : 초당 암호화 복호화 수 제한이 있음.
  • DataKey로 암호화 했을 경우 DataKey 보관 이슈는 그대로 존재한다.
    : 암호화된 DataKey를 잃어버릴 경우 복호화 불가.