당신이 AWS 계정을 만들고 가장 먼저 해야 할 일 들과 하지 말아야 할 일 들

이 글은 tmknom님이 Qiita에 올려주신 ‘AWS 계정을 만들고 나서 바로 해야 할 일들 정리(AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ)‘에서 영감을 받아 작성되었습니다. 처음 AWS 계정을 만들고 나서 무엇을 해야 할 것인가도 중요하지만 하지 말아야 할 것을 아는 것도 중요하기 때문에 해야 할 것들과 하지말아야 할 것들에 대해서 정리해 보았습니다.


AWS 계정(루트 사용자) 보호

루트 사용자란?

AWS에 가입할때 맨 처음 만드는 e-mail어드레스와 패스워드로 인증하는 계정을 루트 사용자 라고 합니다. 이 루트 사용자는 그야말로 모든 권한을 지니고 있으며 권한에 대한 제약이 불가능하기 때문에 각별히 신경써서 다루어야 합니다. AWS의 모범사례에 의하면 AWS 루트 사용자를 만든 이후 가장 먼저 해야 할 일은 IAM 계정을 만들고 권한을 부여할 수 있는 IAM 관리자 계정을 만들고 이후 루트 사용자 대신 그 계정을 사용하는 것 입니다. 루트 사용자는 원칙적으로는 평상시엔 사용하지 않는 것이 좋습니다. 혹시 이 글을 읽으시는 분 중에 아직 루트 사용자를 이용하여 작업을 하시는 분이 계시다면 지금 즉시 관리자 권한을 지닌 IAM유저를 만들고 루트 사용자의 사용을 중지하시기 바랍니다.

AWS 계정에 대한 액세스 키를 만들지 말 것

AWS는 패스워드 인증 이외에 CLI나 SDK 사용을 위한 액세스 키 인증을 제공합니다. 하지만 루트 사용자에 대해서 액세스 키를 만들지는 마세요. 이미 있다면 삭제하시고 다른 IAM유저의 액세스 키를 사용해서 작업하시기 바랍니다.

루트 사용자 암호 변경

루트 사용자의 경우 강력한 암호를 사용하시기 바랍니다. 루트 사용자의 암호 변경 방법은 아래 링크에서 확인하실 수 있습니다.

루트 사용자에 대해 MFA 활성화

보안을 강화하기 위해 패스워드만 사용한 인증보다는 MFA(Multi-Factor Authentication)을 사용한 인증을 설정해 두세요. AWS에서는 Google Authenticator와 같은 개방형 TOPT 표준을 지원하는 애플리케이션을 MFA에 사용할 수 있습니다. 루트 사용자의 인증에 MFA를 설정하는 방법은 아래 링크를 참고하시기 바랍니다.

관리자용 IAM 그룹과 사용자의 작성

관리자용 IAM그룹을 만들고 IAM 사용자를 작성하여 관리자 그룹에 배치시킵니다. 구체적인 방법은 아래 링크를 참고하세요.

IAM유저 중에서도 관리자 권한과 같은 중요한 권한을 지닌 유저에 대해서는 MFA사용을 강제하는것이 좋습니다. 루트 사용자가 아닌 IAM유저에 대해서는 하드웨어 MFA나 가상 MFA이외에 휴대폰 문자 메세지(SMS)에 의한 MFA 사용도 가능합니다.

암호 정책 구성

관리자용 계정으로 로그인 한 후에 암호 정책을 설정하여 IAM 사용자의 암호에 대하여 복잡성 요건과 의무적인 교체주기를 지정할 수 있습니다.

보안 상태(Security Status)의 확인

여기까지 진행하셨다면 AWS를 안전하게 사용하기 위한 최소한의 조치가 완료되었습니다. IAM 서비스 페이지(https://console.aws.amazon.com/iam/home)로 이동하면 Security Status가 다음과 같이 모두 녹색이 되어 있는것을 확인합니다.

Security Status

청구정보 관련 설정

IAM에 대한 설정이 끝났다면 다음은 청구정보에 대한 설정을 진행해 봅시다.

IAM유저의 청구서 정보에 대한 액세스 허가

기본설정에서는 루트 사용자 이외에 유저가 청구정보에 접극하는것이 허가되어 있지 않습니다. 루트 사용자를 가급적 사용하지 않기 위해 IAM유저가 청구서 정보에 접근할 수 있도록 허가해 봅시다.

IAM유저에 대해 결제 정보 액세스를 허용했다면 이후 작업은 관리자 권한을 지닌 IAM유저를 사용해서 진행 할 수 있습니다.

청구정보와 비용 관리에 대한 설정

이메일로 청구서 받기

아래 링크의 지시에 따라 간단한 설정으로 이메일로 청구서를 받아볼 수 있습니다.

또한 프리티어 한고를 초과할 경우 메일이나 휴대폰 문자(SMS)를 통해 알려주는 결제 경보를 생성할 수도 있습니다.

그 밖의 설정들

이메일 설정

AWS로부터의 이메일을 설정합니다. 마케팅 메일을 받을지는 알아서들…

AWS Email Preferences

CloudTrail 유효화

AWS API호출에 대한 이력을 추적할 수 있는 CloudTrail이라는 서비스가 있습니다. 추적 내용은 S3 버킷에 저장됩니다.

git-secrets

git-secrets는 AWS가 만들어 공개하고 있는 툴로서 시크릿 액세스키와 같은 비밀 정보가 git에 커밋 되는 것을 막아줍니다.

GitHub에는 이렇게 잘못 올라온 비밀정보를 노리는 봇들이 수없이 동작하고 있어 실수로 정보가 공개되게 되면 악용되게 될 소지가 큽니다.

Lambda + CloudWatch Events + KMS를 사용하여 AWS 메니지먼트 콘솔에 대한 무단 액세스를 빠르게 감지하기

제목 그대로 입니다. 사실 내용이 초급자가 진행하기엔 만만치 않지만 도움이 되시는 분 도 있을것 같아 링크를 올려봅니다. 원문은 일본어 기사인데 조만간 번역해서 소개해 보기로 하고 일단은 구글번역 링크를 적어봅니다.

끝으로

이것으로 일단 가장 기본적인 설정이 끝났습니다.

추가적으로는 아래 IAM 모범 사례의 내용을 살펴보고 적용시킴으로서 더욱 강력한 보안을 확보 할 수 있습니다. 몇가지는 이 글과 겹치는 부분도 있지만 상세한 내용을 읽고 확인해 두는것도 좋을듯 합니다.

KMS로 인증 정보를 암호화 하고 Lambda 실행시에 복호화 하기

원문: KMSで認証情報を暗号化しLambda実行時に復号化する

데이터베이스나 API서버와 같은 외부 시스템과 연결하는 경우 종종 인증 정보를 필요로 하게 됩니다.

이번에는 AWS Key Management Service(이하 KMS)의 공통 키 암호방식을 사용하여 암호화 된 인증 정보를 AWS Lambda 함수의 코드에 포함 된 함수 호출시 인증 정보를 해독하는 방법을 소개합니다.

decrypt-sensitive-data-with-kms-on-lambda-invocation

기본적인 아이디어는 다음 블로그에 쓰여져 있으며, 이 포스팅에서는 KMS를 사용한 암호화 작업만을 추려내었습니다.

http://ijin.github.io/blog/2015/08/06/github-to-lambda-to-slack/

KMS는 마스터 키를 사용한 암호화와 복호화 처리를 API로 분리해 내었기 때문에 이를 사용하여 인증 정보를 암호화 합니다.

KMS와 Lambda의 연계

다음의 순서로 동작을 확인합니다.

  1. AWS KMS 마스터 키 생성
  2. AWS CLI로 마스터 키를 사용하여 암호화와 복호화 처리를 확인
  3. AWS Lambda에서 암호화 된 데이터(ciphertext)를 복호화 하여 출력
  4. AWS Lambda 함수에 KMS:Decrypt 권한을 부여
  5. AWS Lambda 함수를 실행하고 복호화 되어 있는지를 확인

KMS 마스터 키 생성

우선 Lambda 함수에서 사용할 마스터 키를 만듭니다.

관리 콘솔에 로그인한 후 IAM에서 Encryption Keys를 선택하면 KMS관리 화면으로 이동할 수 있습니다. KMS라는 이름은 메뉴상에서는 존재하지 않으므로 주의하시기 바랍니다.

kms_management_console

KMS 키는 리전에 보관됩니다. Filter의 풀다운 메뉴에서 키를 생성하는 지역을 선택하고 “Create Key”를 클릭하여 마스터 키 생성화면으로 이동합니다.

Key Administrative Permissions 와 Key Permissions 에는 평소 사용하는 시스템 관리자를 선택합니다.

AWS CLI에서 암호화및 복호화 처리 확인

프로그램을 작성하기 전에 CLI에서 암호화 및 복호화 작업을 확인합니다.

마스터키의 일람을 확인합니다.

$ aws kms list-keys
{
    "Keys": [
        {
            "KeyArn": "arn:aws:kms:ap-northeast-1:123456789012:key/xxx-yyy-zzz",
            "KeyId": "xxx-yyy-zzz"
        }
    ],
    "Truncated": false
}

마스터키의 ARN을 환경변수에 설정합니다. 키를 지정하는 방법에는 KeyId 또는 별칭(Alias)을 사용하는 두가지 방법이 있습니다.

$ export KEYID=arn:aws:kms:ap-northeast-1:123456789012:key/xxx-yyy-zzz # KeyId
$ export KEYID=arn:aws:kms:ap-northeast-1:123456789012:alias/lambda # Alias

마스터키를 사용한 복호화

마스터키로 암호화를 하기위해서는 Encrypt API를 사용합니다.

$ aws kms encrypt --key-id $KEYID --plaintext 'hello, world!'
{
    "KeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/xxx-yyy-zzz",
    "CiphertextBlob": "CiAUkK3nep3+LDfCjRPA5NDnd5NEXv5BWWjweqEySvaTLBKUAQEBAgB4FJCt53qd/iw3wo0TwOTQ53eTRF7+QVlo8HqhMkr2kywAAABrMGkGCSqGSIb3DQEHBqBcMFoCAQAwVQYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxHrDshpbxSGRgMAXECARCAKHfUd1sJjxRX/7tq7twil6vaXjtPZsnr9AURI1gjR+RPL4WlQTvNDjE="
}

응답(response)의 Plaintext는 복호화한 데이터(즉 plaintext)를 base64로 엔코드한 것 입니다.

base64로 디코드하면 plaintext가 됩니다.

$ aws kms decrypt --ciphertext-blob fileb://encrypted --query Plaintext --output text | base64 --decode
hello, world!

Lambda 함수화

KMS로 암호화 한 후 base64로 엔코딩한 문자열을 람다 함수내에 적어넣어 Lambda함수 실행시에 복호화해 보겠습니다.

보통은 암호화한 유저데이터를 사용하여 무언가 처리를 하지만 이번에는 복호화한 문자열을 그대로 반환합니다.

Lambda함수는 파이썬으로 구현하였습니다.

import base64
import boto3

# base64 encoded ciphertext
ciphertext_blob_encoded = 'CiAUkK3nep3+LDfCjRPA5NDnd5NEXv5BWWjweqEySvaTLBKUAQEBAgB4FJCt53qd/iw3wo0TwOTQ53eTRF7+QVlo8HqhMkr2kywAAABrMGkGCSqGSIb3DQEHBqBcMFoCAQAwVQYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxHrDshpbxSGRgMAXECARCAKHfUd1sJjxRX/7tq7twil6vaXjtPZsnr9AURI1gjR+RPL4WlQTvNDjE='

# ciphertext
ciphertext_blob = base64.b64decode(ciphertext_blob_encoded)

def lambda_handler(event, context):
    kms = boto3.client('kms')
    dec = kms.decrypt(CiphertextBlob = ciphertext_blob)
    return dec['Plaintext'] #plaintext

변수 ciphertext_blob_encoded 에는 ciphertext를 base64로 엔코드한 문자열을 설정했습니다. 위에서 CLI로 암호화한 문자열을 적어줍니다.

KMS 사용권한을 Lambda 함수에게 부여한다

Lambda함수에 설정한 역할(Role)에 마스터키를 사용한 복호화 권한을 추가합니다. 역할에 인라인 정책(Inline policy)을 추가합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1448696327000",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:ap-northeast-1:123456789012:key/xxx-yyy-zzz"
            ]
        }
    ]
}

Resource에는 KMS 마스터키의 arn을 설정합니다.

Lambda 함수를 실행한다

$ aws lambda invoke \
        --function-name kms_demo \
        --payload '' \
        response.txt
{
    "StatusCode": 200
}

$ cat response.txt
"hello, world!"

무사히 복호화 되었군요.

마무리

민감한 정보는 KMS로 암호화 함으로서 프로그램의 소스코드 내에 안심하고 적어넣을 수 있습니다. 소스코드와 KMS의 Decrypt API를 실행권한을 모두 획득하지 않는 이상 원래 정보를 손에 넣는것은 불가능합니다.

KMS는 어떻게 써야 하는지 잘 모르겠다고 하는 이야기가 가끔 들려오지만 사용법이 단순하면서도 보안성을 높이는데 있어서 대딘히 강력한 서비스 입니다. 이번 포스팅에서는 이러한 KMS의 유즈케이스를 소개해 보았습니다.