aws-vault로 AWS의 인증 정보 안전하게 사용하기

들어가며: aws-vault와 AWS 인증 정보

aws-vault는 99디자인스99desingns에서 개발한 AWS 인증 정보를 안전하게 보관하도록 도와주는 도구입니다. AWS CLI나 관련 도구를 로컬에서 사용하는 경우 IAM 사용자의 액세스키AWS Access Key ID와 비밀 키AWS Secret Access Key가 필요합니다.

AWS CLI의 경우 ~/.aws/credentials에 저장된 정보나 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 환경변수에서 이 값들을 읽어와 사용합니다. 이 정보를 사용하면 IAM 사용자에게 부여된 모든 권한에 접근가능합니다. 불행히도 일반적으로 이 정보들은 작업 환경에서 플레인 텍스트로 저장되거나 노출됩니다. 또한 IAM 사용자에게 부여되는 액세스 키는 영구적으로 권한을 보유하기 때문에 한 번 유출되면 되돌리기 어려운 문제가 발생할 수 있습니다. 실제로 의도치않게 개인 계정의 인증 정보가 유출되어 과도한 비용이 청구 되는 등의 사례는 비교적 쉽게 찾아볼 수 있습니다.

aws-vault는 이러한 문제를 해결하는 데 도움을 주는 도구입니다. aws-vault는 맥OS 키체인macOS Keychain, 윈도우 자격 증명 관리자Windows Credential Manager, 그놈 키링Gnome Keyring, K월렛KWallet 등을 백엔드로 사용해 인증 정보를 안전하게 저장하고, 키를 사용할 때도 사용자 키를 직접 사용하지 않고 STS를 경유해 임시 세션 키를 발급 받아 사용합니다. 따라서 처음에 인증 정보를 셋업한 이후에는 인증 정보가 유출되더라도 세션이 유효한 기간만 동작하기 때문에 비교적 안전합니다. 물론 이것도 유출되지 않는 것이 최선입니다. 99디자인스에서 aws-vault를 개발한 배경에 대해서는 다음 글을 참고해주세요.

이 글에서는 맥OSmacOS에서 aws-vault를 설치하고, 기본적인 사용법에 대해서 소개합니다. aws-vault는 AWS CLI는 물론 테라폼Terraform이나 기타 AWS 인증 정보가 필요한 도구들과도 함께 사용할 수 있습니다. 이에 대해서도 알아봅니다.

aws-vault 설치하기

AWS 인증 정보 발급과 AWS CLI 셋업에 대해서는 다음 글을 참고해주세요.

맥OSmacOS에서는 다음 명령어로 AWS CLI와 aws-vault를 설치할 수 있습니다.

$ brew install awscli
$ brew cask install aws-vault

다음 명령어로 정상적으로 설치되었는지 확인해봅니다.

$ aws-vault --version
v5.4.4

맥OS 이외의 운영체제에서도 운영체제 별 패키지 관리자를 통해서 aws-vault를 설치할 수 있습니다.

$ choco install aws-vault  # 윈도우 Chocolatey
$ scoop install aws-vault  # 윈도우  Scoop
$ brew install aws-vault   # Linux Homebrew
$ yay -S aws-vault         # Arch Linux AUR
$ pkg install aws-vault    # FreeBSD 
$ nix-env -i aws-vault     # NixOS

릴리스 페이지에서 운영체제 별로 빌드된 바이너리를 직접 다운로드 받을 수도 있습니다.

aws-vault 설정

~/.aws/credentials에는 AWS 인증 정보가 플레인 텍스트로 저장됩니다. 따라서 aws-vault를 설정하기에 앞서 기존에 사용하던 ~/.aws/credentials 파일이 있다면 삭제하는 것을 추천합니다.

다음 명령어로 AWS 접근을 위한 비밀 정보를 aws-vault에 등록할 수 있습니다.

$ aws-vault add <PROFILE_NAME>
Enter Access Key ID: ...
Enter Secret Access Key: ...
Added credentials to profile "<PROFILE_NAME>" in vault

<PROFILE_NAME> 에는 액세스 키의 프로필 이름을 입력합니다. 새로운 이름을 사용해도 되고, 기존에 ~/.aws/config에 설정한 프로필 이름을 사용해도 됩니다. 여기에 IAM 사용자의 액세스 키와 시크릿키를 입력합니다. 등록과정에서 키체인에도 등록을 진행합니다. 키체인에서 사용할 새로운 비밀번호를 지정합니다.

AWS 인증 정보를 맥OS 키체인에 등록합니다.

AWS 인증 정보를 등록했으면, ls 서브커맨드로 키가 잘 등록되었는지 확인해볼 수 있습니다.

aws-vault ls
Profile                  Credentials              Sessions
=======                  ===========              ========
n42corp_ben              n42corp_ben

aws-vault 사용하기

aws-vault를 사용하는 가장 기본적인 방법은 다음과 같습니다.

$ aws-vault exec <PROFILE_NAME> -- <COMMAND>

<PROFILE_NAME>에 지정된 사용자로 <COMMAND> 명령어를 실행합니다. 예를 들어 nacyot 권한으로 aws s3 ls를 실행하고 싶다면 다음과 같이 실행합니다. 실행 과정에서 앞서 키체인에 지정한 패스워드를 입력합니다.

$ aws-vault exec nacyot -- aws s3 ls
2020-05-26 10:44:06 bucket1
2020-05-19 17:27:49 bucket2
...

정상적으로 S3 버킷 목록이 출력되면 정상입니다. 좀 더 자세한 원리가 보고 싶다면 --debug를 붙여서 실행해봅니다.

$ aws-vault exec --debug home aws s3 ls
...

다음 명령어로 실제로 인증에 사용되는 환경변수들을 확인해볼 수 있습니다.

$ aws-vault exec nacyot -- grep AWS
AWS_VAULT=nacyot
AWS_DEFAULT_REGION=ap-northeast-2
AWS_REGION=ap-northeast-2
AWS_ACCESS_KEY_ID=ASIA...aoeu
AWS_SECRET_ACCESS_KEY=...aoeu
AWS_SECURITY_TOKEN=...aoeu
AWS_SESSION_EXPIRATION=2020-06-03T09:10:20Z

여기에 보이는 액세스키는 IAM 사용자의 액세스키와 다른 STS 세션 키입니다. 또한 만료기간이 지정돼있는 것도 확인할 수 있습니다.

테라폼(Terraform)에서 사용하기

테라폼Terraform과 같이 AWS 인증 정보가 필요한 다른 커맨드라인 툴에서 사용하는 것도 어렵지 않습니다. exec 서브커맨드로 terraform을 사용하면 됩니다. 테라폼 프로젝트에서 아래와 같이 plan을 실행해봅니다.

$ aws-vault exec <PROFILE_NAME> -- terraform plan

플랜 결과가 정상적으로 출력되는 것으로 정상 동작되는 것을 확인할 수 있습니다.

2팩터 인증(MFA) 설정하기

보안 강화를 위해서 CLI에서 명령을 실행할 때도 MFA 기기를 지정해서 OTP를 입력하도록 설정할 수 있습니다. 단, 여기서 MFA를 설정하지 않더라도 대부분의 API는 정상적으로 호출할 수 있습니다. MFA 설정이 꺼져있을 때 API 호출을 금지하려면 별도의 IAM 권한 설정을 해주어야합니다. 이 내용은 이 글의 범위를 넘어섬으로 다루지 않습니다.

MFA를 활성화하지 않으면 사용할 수 없는 API도 있습니다. 바로 IAM입니다. IAM의 관련 API를 MFA 활성화 없이 호출하는 경우 InvalidClientTokenId 에러가 발생합니다.

IAM API를 로컬 환경에서 실행하기 위해서는 MFA를 활성화해주어야합니다. 공식 문서를 참고해서 사용자 계정에 MFA를 셋업합니다. 등록시 확인할 수 있는 MFA 기기의 ARN을 ~/.aws/config에 셋업해주면 AWS CLI에도 MFA가 적용됩니다.

[default]

[profile nacyot]
region = ap-northeast-2
mfa_serial=arn:aws:iam::0:mfa/nacyot

이제 AWS CLI를 실행할 때 OTP 인증을 추가로 진행합니다.

$ aws-vault exec nacyot -- aws iam get-user
Enter token for arn:aws:iam::0:mfa/nacyot:

결과가 출력되면 정상입니다(여기서는 IAM 사용자에게 관리자 권한이 부여되어있다고 가정합니다).

IAM 사용자를 기반으로 IAM 역할 권한 사용하기

AWS에서는 사용자 계정의 권한을 직접 사용하는 대신 특정 IAM 역할IAM Role의 권한을 사용해서 작업할 수 있는 Assume Role(권한 위임) 기능을 지원하고 있습니다. 이 기능을 사용하면 IAM 사용자에게 직접 권한을 부여하지 않더라도 임시적으로 특정 역할을 권한을 사용할 수 있도록 하는 것이 가능합니다.

예를 들어 nacyot 프로필에서 AdminRole을 Assume Role로 사용하고자 한다면, 다음과 같이 새로운 프로필을 정의합니다. *

* 특정 IAM 사용자(A)에서 특정 IAM 역할(X)로 Assume Role을 수행하기 위해서는 추가적인 설정이 필요합니다. A 사용자는 X 역할에 대한 sts:AssumeRole 권한을 가지고 있어야하며, X 역할은 A 사용자에 대한 신뢰 관계Trust relationship를 가지고 있어야합니다. 이에 대한 자세한 정보는 AWS 공식 문서를 참고해주세요.

[profile nacyot]
region = ap-northeast-2
mfa_serial=arn:aws:iam::0:mfa/nacyot

[profile nacyot_admin_role]
source_profile=nacyot
mfa_serial=arn:aws:iam::0:mfa/nacyot
role_arn=arn:aws:iam::0:role/AdminRole

이제 nacyot_admin_role 프로필으로 nacyot 프로필 계정의 권한이 아니라 AdminRole 역할의 권한으로 작업을 수행할 수 있습니다. 앞서 살펴본 대로 exec 서브 명령어를 사용합니다.

$ aws-vault exec nacyot_admin_role -- aws s3 ls

특정 프로필로 AWS 웹 콘솔 로그인

다수의 AWS 계정과 IAM 사용자를 관리하는 경우 웹 콘솔을 사용하는 게 매우 번잡스러워지곤 합니다. aws-vaultlogin 기능을 사용하면 aws-vault에 등록된 프로필로 쉽게 브라우저를 실행할 수 있습니다.

$ aws-vault login nacyot

이 명령어를 실행하면 nacyot 프로필로 로그인 된 탭이 기본 브라우저에서 실행됩니다. 단, MFA가 활성화 되어있는 경우 sts:GetFederationToken 권한 문제로 명령어가 실패합니다.

$ aws-vault login nacyot
aws-vault: error: Login failed: Failed to get credentials for nacyot: AccessDenied: User: arn:aws:iam::0:user/nacyot is not authorized to perform: sts:GetFederationToken on resource: arn:aws:sts::0:federated-user/nacyot with an explicit deny
        status code: 403, request id: 224af095-1f29-41c9-b659-a3c55d198a78

이에 대한 자세한 정보는 aws-vault의 이슈에서 확인할 수 있습니다.

MFA를 활성화하더라도 Assume Role을 사용하는 경우 login 기능이 정상 동작하니, 로그인 기능을 사용하고자 하는 경우 Assume Role과 MFA를 조합해서 사용하는 것을 권장합니다.

참고로 --stdout 옵션을 사용하면 세션이 적용된 주소를 출력해줍니다.

$ aws-vault login nacyot --stdout

알프레드 워크플로우(Alfred Workflow)로 aws-valut 프로필 웹 콘솔 열기

kangaechu/aws-vault-alfred-workflow를 사용하면 알프레드 워크플로우Alfred Workflow에서 aws-vault의 특정 프로필을 선택해 브라우저에서 여는 것이 가능합니다.* 사용하려면 릴리스 페이지Packal 사이트에서 aws-vault-alfred-workflow를 설치합니다.

* 알프레드Alfred는 맥OSmacOS에서 동작하는 범용 런처입니다. 알프레드에서 제공하는 스크립팅 기능인 워크플로우를 사용하려면 알프레드 파워팩을 구매해야합니다.

Open AWS via aws-vault 알프레드 스크립트

v0.0.4 기준 약간의 버그가 있는 걸로 보여 직접 수정해줍니다. 먼저 가운데의 > 모양을 더블 클릭하면 변수 설정 화면이 나옵니다.

다음 스크립로 넘겨주는 변수 내용을 수정합니다

value 값에 {aws_vault_path}{var:aws_vault_path}로 고쳐줍니다. 아래 값도 마찬가지로 {default_profile}{var:default_profile}로 고쳐줍니다. 저장합니다.

그리고 오른쪽의 /bin/zsh 스크립트를 더블 클릭합니다. aws-vault 실행 경로를 지정하는 내용입니다.

스크립트의 일부 내용을 수정해줍니다.

일곱 번째 라인의 내용을 수정해줍니다.

# before
login_url=$(aws_vault_path login ${aws_account} --prompt=osascript --stdout)

# after
login_url=$(${aws_vault_path:-/usr/local/bin/aws-vault} login ${aws_account} --prompt=osascript --stdout)

aws_vault의 경로나 실행할 브라우저를 변경하려면 오른쪽 위에 [x](변수설정) 아이콘을 클릭해서 수정합니다. 기본 브라우저는 크롬(chrome)이며, 파이어폭스(firefox)도 지원합니다.

스크립트에서 사용되는 변수값을 설정합니다

브라우저로 실행시 aws-vault 프로필 별로 브라우저 프로필을 만들어줍니다. 브라우저의 기본 프로필에서 실행하려면 스크립트 수정이 필요해보입니다.

이제 알프레드 런처에서 aws를 입력하면 사용가능한 프로필 목록이 나옵니다. 이 중에 하나를 선택하면 해당 인증정보로 로그인 된 웹 브라우저가 실행됩니다.

aws-vault의 세션 관리 및 장시간 인증 유지하기

aws-vault를 사용하면 sts를 통해 임시 세션 인증 정보가 발급됩니다. 세션을 더 이상 사용하지 않는 경우 세션이 만료되기 전에 미리 삭제하는 것이 가능합니다.

$ aws-vault ls
Profile               Credentials              Sessions
=======               ===========              ========
nacyot                nacyot                   22342345195 (mfa)
nacyot_admin_role     -                        -

$ aws-vault remove nacyot --sessions-only

$ aws-vault ls
Profile               Credentials              Sessions
=======               ===========              ========
nacyot                nacyot                   -
nacyot_admin_role     -                        -

세션의 만료 시간은 앞서 살펴본 대로 AWS_SESSION_EXPIRATION 환경변수를 통해 확인할 수 있습니다.

$ aws-vault exec nacyot -- grep AWS_SESSION_EXPIRATION
AWS_SESSION_EXPIRATION=2020-06-03T09:10:20Z

aws-vault exec 도움말을 보면 별도로 세션 시간을 지정할 수 있으며, 기본값이 1시간인 것을 확인할 수 있습니다. 세션 시간은 최대 36시간까지 지정할 수 있습니다. 롤을 사용하는 경우, 롤에 지정된 최대값(최대 12시간)을 따릅니다. 자세한 내용은 공식 문서 임시 보안 자격 증명 요청하기의 AWS STS API 작업 비교 절을 참고해주세요.

$ aws-vault exec --help
...
-d, --duration=DURATION        Duration of the temporary or assume-role session. Defaults to 1h
...

이보다 더 긴 시간의 작업을 해야하는 경우 2가지 방법이 있습니다.

첫 번째는 exec 서브 명령어 실행 시 --no-session 옵션을 사용해 프로필에 저장해둔 액세스키를 직접 사용하는 방법입니다. 이 경우 세션 인증 정보가 아닌, 영구적으로 유효한 액세스 키가 사용 되므로 aws-vault를 사용하는 의미가 무색해질 수 있습니다.

또 다른 방법은 로컬 인스턴스 메타데이터 서버를 사용해 인증 정보를 자동적으로 갱신해주는 방법입니다. 다음과 같이 -s 옵션을 붙여서 exec를 실행하면 인스턴스 메타데이터 서버가 인증 정보를 갱신해주기 때문에 장시간에 걸친 작업이 가능합니다.

$ aws-vault -s nacyot -- <long-operation>

direnv와 함께 사용하기

direnv는 특정 디렉터리로 이동했을 때 디렉터리 별로 작업 환경을 셋업해주는 도구입니다. direnv에 대한 자세한 내용은 44BITS에서도 소개한 적이 있으니 다음 글을 참고해주세요.

여기서는 다음 글을 참고해 aws-vault를 direnv와 함께 셋업하는 방법을 소개합니다.

먼저 ~/.direnvrc 파일에 다음 헬퍼 함수를 추가해줍니다.

use_aws_profile(){
  profile_name=$1

  export $(aws-vault exec $profile_name -- env | grep AWS_ | grep -v AWS_VAULT)
}

이제 각 디렉터리의 .envrc 파일에 다음 내용을 추가합니다.

use aws_profile <PROFILE_NAME>

<PROFILE_NAME>에는 사용할 aws-vault의 프로필 이름을 지정합니다. 이제 설정된 디렉터리로 이동할 때 키체인 정보와 MFA 인증을 해야합니다. (조금 번거로울 수도 있습니다)

또한 디렉터리로 이동할 때 1회성으로 환경변수를 설정해주는 방식이므로 세션이 만료되면 reload를 통해서 다시 세션을 셋업해주어야합니다.

$ direnv reload

앞서 살펴보았듯이 인증 세션 길이는 기본적으로 1시간으로 지정되며, 세션 타입에 따라서 설정할 수 있는 값이 조금씩 달라집니다. 공식 문서에 따르면 아래 환경변수들로 세션 타임아웃 기본값을 변경할 수 있으니, .envrc에 적절한 값을 함께 지정해서 편리하게 사용할 수 있습니다.

마치며

보안 관점에서는 적절한 권한 부여와 인증 정보 관리는 한꺼번에 이뤄야만 하는 목표라고 할 수 있습니다. aws-vault가 모든 문제를 해결해주지는 않지만, IAM 사용자를 기반으로 액세스 키를 발급해서 사용하고 있다면 훨씬 더 안전하게 인증정보를 관리할 수 있도록 도움을 줍니다.

안전한 AWS 생활이 되시길!

셸에서 멀티라인 명령어 편집하고 실행하기

🗒 기사, 2019-01-29 - 셸에서 긴 명령어를 다루는 일은 어려운 일입니다. 긴 명령어를 입력하다보면 실수를 하는 경우가 많습니다. 복사해서 붙여넣어봐도 이상하게 입력되는 경우가 많습니다. 이럴 때 에디터에서 긴 명령어를 편집하고 셸에서 바로 실행할 수 있다면 좀 더 편리하지 않을까요? Bash와 Zsh에는 이미 이 기능이 준비되어있습니다.

아마존 EKS(Amazon EKS) 50% 요금 인하 발표 - 시간당 0.10 USD

🗞 새소식, 2020-01-28 - 아마존 EKS는 아마존 웹 서비스에서 제공하는 매니지드 쿠버네티스 서비스입니다. AWS에서는 2020년 1월 21일 50% 요금 인하를 발표했습니다. 기존에는 시간당 0.2USD였습니다만 이제 0.1USD로 사용할 수 있습니다.

44BITS 뉴스레터 2020년 12주

🗞 새소식, 2020-03-23 - 2020년 12주 44BITS 뉴스레터입니다. 44BITS의 업데이트와 IT / 개발 관련 새소식을 전합니다.