Post

AWS-CLI MFA 갱신 자동화 스크립트

서두

AWS CLI를 사용할 때 MFA가 활성화된 계정에서는 프로필의 MFA 토큰을 통해 인증을 받아야 한다.
여러 리전에서 인증을 받아 사용해야 하는 경우, 각 프로필마다 MFA 인증을 받는 과정이 번거로울 수 있다.

이를 자동화하기 위한 로컬용 스크립트를 작성하고자한다.(요즘에는 pc에서 바로 mfa 값을 받던데.. 더 간단할지도..)

주요 고려사항

1. Json 데이터 파싱

  • jq 라이브러리 대신 표준 Unix 도구인 sed를 사용
  • sed는 추가 설치가 필요 없는 장점이 있지만, 예상 가능한 JSON 구조에만 적용 가능
    • 말그대로 텍스트 편집 도구이기에 편집할 데이터가 예상가능한 경우에만 도움된다.
    • 이 경우에는 aws sts get-session-token을 통해 반환받은 json 데이터를 위해서만 처리하기위해 사용하고 데이터의 구조가 고정적이기에(aws가 바꾸지않는한) exit code 처리 필요

2. 스크립트 구성

  • 해당 스크립트에 필요 설정값들을 추가해 작성합니다
  • mfa 토큰값을 파라미터로 스크립트 파일을 실행합니다 ex) ./aws_login.sh 123456
  • aws-cli를 사용합니다 ex) s3 버킷목록을 조회한다 가정하면 aws s3 ls --profile {myProfile}

3. 보안 고려사항

  • 반드시 로컬 환경에서만 사용 (MFA 토큰값, 액세스 토큰 등의 민감한 정보 포함)
  • 또한, 토큰의 만료시간 설정 또한 중요(긴 시간일수록 편하겠지만, 그만큼 보안에 취약하다는 뜻)

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/bin/bash

# 파라미터로 입력받은 mfa token값을 변수에 저장
mfa_token=$1

# 설정을 위해 필요한 값들을 설정
aws_access_key_id={}
aws_secret_access_key={}
aws_region={}
arn_number={}
duration_time={}

# 각 설정값들을 제대로 넣었는지 체크
if [[ -z $aws_access_key_id || -z $aws_secret_access_key || -z $aws_region || -z $arn_number || -z $duration_time ]]; then
    echo "환경 변수가 설정되어 있지 않습니다. 확인 후 다시 시도해주세요."
    exit 1
fi

read -p "우선 ~/.aws/config와 ~/.aws/credentials 기존 파일 내용을 clear합니다. 계속하시겠습니까? (y/n): " response
if [[ "$response" != "y" ]]; then
    echo "스크립트를 종료합니다."
    exit 1
fi

echo "config를 clear합니다."
> ~/.aws/config

echo "credentials을 clear합니다."
> ~/.aws/credentials

echo "clear complete"

aws configure set aws_access_key_id $aws_access_key_id
aws configure set aws_secret_access_key $aws_secret_access_key
aws configure set region $aws_region

echo "configure complete"

sts_output=$(aws sts get-session-token --serial-number "${arn_number}" --token-code "${mfa_token}" --duration-seconds $duration_time)

# 종료코드(정상:0)로 체크
if [ $? -ne 0 ]; then
    echo "STS 토큰 요청 중 오류가 발생했습니다."
    exit 1
fi

echo "sts complete"

access_key_id=$(echo "$sts_output" | sed -n 's/.*"AccessKeyId": "\([^"]*\)".*/\1/p')
secret_access_key=$(echo "$sts_output" | sed -n 's/.*"SecretAccessKey": "\([^"]*\)".*/\1/p')
session_token=$(echo "$sts_output" | sed -n 's/.*"SessionToken": "\([^"]*\)".*/\1/p')

# 추출된 값이 비어 있는지 확인
if [[ -z "$access_key_id" || -z "$secret_access_key" || -z "$session_token" ]]; then
  echo "sts_output에서 값 추출에 실패했습니"
  exit 1
fi

cat <<EOF > ~/.aws/credentials
[default]
aws_access_key_id = ${access_key_id}
aws_secret_access_key = ${secret_access_key}
aws_session_token = ${session_token}
EOF

echo "success"

결과

  • 아래처럼 mfa 토큰 값을 입력하면 매우 간단하게 mfa인증을 통해서 작업이 가능하다.

result - image

다만 한계도 존재하는데 자동화 스크립트여도 여러 리전의 프로필을 한번에 인증하는건 불가능했는데 아래처럼 이미 사용한 mfa토큰을 다른 리전 프로필 인증에 사용할 수 없기때문

  • 원하는 리전을 선택받도록해서 하나하나 인증하는 방식을 고려해봐야함
1
2
An error occurred (AccessDenied) when calling the GetSessionToken operation: MultiFactorAuthentication failed with invalid MFA one time pass code. 
STS 토큰 요청 중 오류가 발생했습니다.
This post is licensed under CC BY 4.0 by the author.