MFA 코드와 AWS CLI를 이용해 로그인하기

  • Post author:
  • Post category:칼럼
  • Post comments:1 Comment
  • Post last modified:March 10, 2020

AWS 명령줄 도구에서 MFA 로그인을 해야 하는 상황이 있다. 로그인하는 방법은 Authenticate Access using MFA Through the AWS CLI에서 자세히 설명하지만 이 글을 다 읽는다 해도 그 과정이 엄청나게 번거롭다는 생각에 정신이 아득해질 뿐이다.

그래서! 인생을 편하게 해줄 간단한 스크립트를 작성했다. 사용법은 매우 간단하다.

$ awslogin.sh
This will save new AWS credentials into the profile aws4-mfa once signed with MFA token, which issued with the profile aws4.

Would you like to proceed? [y/n]:
$ AWS_LOGIN_PROFILE=my-profile AWS_PROFILE=my-profile-mfa awslogin.sh 987654
Successfully logged in

혹시라도 실패하는 경우에는 간단하게 안내를 해준다.

An error occurred (AccessDenied) when calling the GetSessionToken operation: MultiFactorAuthentication failed with invalid MFA one time pass code.

USAGE: source awslogin.sh 123456
See https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/

오류 문구

이 스크립트를 사용하려면 먼저 AWS의 Access key와 Secret key를 ~/.aws/credentials 파일이나 환경변수로 등록해야 한다. 그리고 AWS_LOGIN_PROFILEAWS_PROFILEdirenv 같은 도구를 이용해 설정하면 더욱 편리하다.

  • AWS_LOGIN_PROFILE: AWS에서 발급 받은 키 값을 가진 Profile을 적는다.
  • AWS_PROFILE: awslogin.sh로 MFA 로그인하면 임시로 세션을 발급 받는데 그 세션 토큰 값을 저장할 Profile을 가리킨다.
#!/bin/bash -e
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
err_report() {
echo ""
echo -e "${RED}USAGE: $(basename $0)${NC}"
echo -e "${RED}USAGE: AWS_LOGIN_PROFILE=my-profile AWS_PROFILE=my-profile-mfa $(basename $0) 123456${NC}"
echo -e "${RED}See${NC} https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/"
echo ""
exit 1
}
trap err_report ERR
type aws > /dev/null || brew install awscli
while [[ "${AWS_LOGIN_PROFILE}" == "" ]]; do
read -p "$(echo -e ${GREEN}Enter AWS_PROFILE you use to sign in with your MFA token: ${NC})" AWS_LOGIN_PROFILE
echo ""
[[ "${AWS_LOGIN_PROFILE}" == "" ]] && continue
SECTION_FOUND=$(sed -n "/^\[\s*${AWS_LOGIN_PROFILE}\s*\]\s*$/p" "${HOME}/.aws/credentials")
if [[ "${SECTION_FOUND}" == "" ]]; then
echo -e "${RED}AWS profile '${AWS_LOGIN_PROFILE}' can not be found!"
AWS_LOGIN_PROFILE=""
fi
done
DEFAULT_AWS_PROFILE="${AWS_LOGIN_PROFILE}-mfa"
if [[ "${AWS_PROFILE}" == "" ]]; then
read -p "$(echo -e ${GREEN}Enter AWS_PROFILE you use to access to AWS resources after signed in with MFA token \(Default: ${NC}${DEFAULT_AWS_PROFILE}${GREEN}\): ${NC})" AWS_PROFILE
echo ""
fi
if [[ "${AWS_PROFILE}" == "" ]]; then
AWS_PROFILE="${DEFAULT_AWS_PROFILE}"
fi
echo -e "${GREEN}This will save new AWS credentials into the profile ${NC}${AWS_PROFILE}${GREEN} once signed with MFA token, which issued with the profile ${NC}${AWS_LOGIN_PROFILE}${GREEN}.${NC}"
echo ""
while [[ ! "${ANSWER}" =~ ^\s*[yYnN]\s*$ ]]; do
read -p "$(echo -e ${GREEN}Would you like to proceed? [y/n]: ${NC})" -n 1 ANSWER
echo ""
done
if [[ ! "${ANSWER}" =~ ^\s*[yY]\s*$ ]]; then
exit 0
fi
AWS_MFA_CODE=$1
while [[ ! "${AWS_MFA_CODE}" =~ ^[0-9]{6}$ ]]; do
read -p "$(echo -e ${GREEN}Enter the MFA token: ${NC})" -n 6 AWS_MFA_CODE
echo ""
done
eval $( AWS_PROFILE=${AWS_LOGIN_PROFILE} aws sts get-caller-identity | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" )
export AWS_ACCOUNT_ID="${Account}"
export AWS_IAM_USER=$( echo -n "${Arn}" | sed -e "s|^arn:aws:iam::$AWS_ACCOUNT_ID:user/\(.*\)|\1|" )
eval $( AWS_PROFILE="${AWS_LOGIN_PROFILE}" aws sts get-session-token –serial-number arn:aws:iam::${AWS_ACCOUNT_ID}:mfa/${AWS_IAM_USER} –token-code ${AWS_MFA_CODE} | jq -r '.Credentials | to_entries[] | .key + "=" + .value' )
if [[ "${AccessKeyId}" == "" || "${SecretAccessKey}" == "" || "${SessionToken}" == "" ]]; then
err_report
fi
SECTION_FOUND=$(sed -n "/^\[\s*${AWS_PROFILE}\s*\]\s*$/p" "${HOME}/.aws/credentials")
if [[ "${SECTION_FOUND}" == "" ]]; then
echo -e "\n[${AWS_PROFILE}]" >> "${HOME}/.aws/credentials"
fi
AWS_PROFILE="${AWS_PROFILE}" aws configure set aws_access_key_id "${AccessKeyId}"
AWS_PROFILE="${AWS_PROFILE}" aws configure set aws_secret_access_key "${SecretAccessKey}"
AWS_PROFILE="${AWS_PROFILE}" aws configure set aws_session_token "${SessionToken}"
echo -e "${GREEN}Successfully logged in${NC}"
view raw awslogin.sh hosted with ❤ by GitHub

This Post Has One Comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.