AWS의 모든 기능은 API화되어 있다. 이 API들은 페이스북 Graph API의 GraphQL같이 크게 특별한 것 없이, 대부분의 엔지니어에게 익숙한 HTTP API로 만들어져 있다. 이러한 API에 접근하기 위한 HTTP call들을 wrapping해서 Python용 SDK를 만든 것이 botocore고, 이를 더 high-level로 끌어올린 것이 boto3다.

boto3에서 AWS의 자원에 대한 접근 자격을 증명하기 위해, AWS IAM에서 얻어낼 수 있는 AWS access key IDAWS secret access key, 또는 임시 자격 증명을 위한 aws_session_token, 또는 AWS의 컴포넌트(EC2, Lambda 등)에게 pass된 role을 사용한다.

awscli 등의 도구를 통해 ~/.aws/credentials 파일에 자격 증명 데이터를 설정하고, boto3는 여기에 접근해 자격 증명을 진행하는 것이 기본적인 사용 예다. 그러나 boto3를 사용하는 어플리케이션에서 자격 증명 정보가 하나로 고정되지 않거나, 별도의 access key를 사용하지 않고 특정 IAM role을 사용하도록 유도해야 하는 상황이 생길 수 있다.

다행히도, boto3는 자격 증명 데이터를 얻어낼 때까지 여기저기에 순서대로 접근한다.

boto3의 자격 증명 정보 접근 순서

1. client, resource 함수에 자격 증명 데이터를 매개변수로 전달

import boto3

ACCESS_KEY = '...'
SECRET_KEY = '...'
SESSION_TOKEN = '...'

s3_client = boto3.client(
    's3',
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY,
    aws_session_token=SESSION_TOKEN
)

s3 = boto3.resource(
    's3',
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY,
    aws_session_token=SESSION_TOKEN
)

client, resource, Session 등을 얻을 때 aws_access_key_id, aws_secret_access_key, aws_session_token이라는 문자열 타입의 선택 인자를 사용할 수 있다. 이 선택 인자로 자격 증명 정보가 들어오면, boto3는 다 무시하고 얘네들을 쓴다. 시스템 설정을 무시하고, 자격 증명 정보를 별도로 명시하고 싶을 때 대부분 이 방법을 사용한다.

2. 환경 변수

client, resource, Session에 자격 증명 정보가 인자로 전달되지 않으면, 환경 변수를 확인한다.

AWS_ACCESS_KEY_ID

AWS 계정의 access key

AWS_SECRET_ACCESS_KEY

AWS 계정의 secret key

AWS_SESSION_TOKEN

AWS 계정의 세션 키

3. 공유 자격 증명(Shared credentials) 파일

그 다음부턴 파일들에 접근하기 시작한다. 공유 자격 증명 파일의 기본 위치는 ~/.aws/credentials이고, AWS_SHARED_CREDENTIALS_FILE 환경 변수를 설정하여 위치를 변경할 수 있다. credentials는 .ini 형식의 파일이고, 각 섹션마다 자격 증명을 위한 세 가지의 변수를 지정할 수 있다.

[default]
aws_access_key_id=foo
aws_secret_access_key=bar

[dev]
aws_access_key_id=foo2
aws_secret_access_key=bar2

[prod]
aws_access_key_id=foo3
aws_secret_access_key=bar3

섹션 각각을 profile이라고 부른다. session을 생성할 때 AWS_PROFILE 환경 변수를 설정하거나 profile_name 인자에 이름을 전달하여 어떤 profile을 사용할 지 명시할 수 있다. 여기서 session은 client나 resource를 생성할 수 있도록 자격 증명에 대한 '상태'를 저장하고 있는 객체다.

import boto3

session = boto3.Session(profile_name='dev')
# Any clients created from this session will use credentials
# from the [dev] section of ~/.aws/credentials.
dev_s3_client = session.client('s3')

별도로 명시하지 않으면, [default] profile을 사용한다. IAM Role을 사용하지 않는 경우, 이렇게 credentials를 사용하는 방식을 쓰는 것이 일반적인 것 같다.

4. AWS Config 파일

기본 위치는 ~/.aws/config이고, AWS_CONFIG_FILE 환경 변수를 설정하여 위치를 변경할 수 있다. config 파일은 credentials 파일과 거의 동일하게 작성한다. 유일한 차이점은, profile 섹션을 [profile [name]] 포맷으로 표현한다는 것이다.


[default]
aws_access_key_id=foo
aws_secret_access_key=bar

[profile dev]
aws_access_key_id=foo2
aws_secret_access_key=bar2

[profile prod]
aws_access_key_id=foo3
aws_secret_access_key=bar3

5. AssumeRole 호출

AWS_CONFIG_FILE 환경 변수에 명시된 파일이나, 기본 경로인 ~/.aws/config 파일에서 role에 대한 정보를 명시하여, boto3가 자동으로 AWS STS에 AssumeRole을 호출하도록 할수도 있다. role_arn, source_profile, role_session_name 등의 파라미터가 필요하다.

[profile crossaccount]
role_arn=arn:aws:iam:...
source_profile=development

6. boto2 config

그 후에는, boto2 config 파일에서 자격 증명을 로드한다. BOTO_CONFIG 환경 변수가 나타내는 경로의 파일을 먼저 검사하고, 그렇지 않으면 /etc/boto.cfg~/.boto 파일을 순서대로 검사한다. [Credentials] 섹션만 사용한다.

[Credentials]
aws_access_key_id = foo
aws_secret_access_key = bar

7. IAM Role

Amazon EC2에서 실행 중이며 위의 방법들로 자격 증명을 찾지 못한 경우, boto3는 EC2 인스턴스의 메타 데이터 서비스에서 자격 증명을 로드한다. EC2 인스턴스를 시작할 때 IAM role을 지정해 두었다면, 별도의 명시적인 구성을 하지 않아도 boto3가 알아서 인스턴스의 자격 증명을 사용한다.

Best Practice

boto3는 자격 증명 정보를 얻기 위해, 결론적으로 아래의 순서를 따른다.

  1. client/resource/Session에 전달되는 자격 증명 정보
  2. 환경 변수
  3. AWS_SHARED_CREDENTIALS_FILE에 명시된 파일 또는 ~/.aws/credentials에 접근
  4. AWS_CONFIG_FILE에 명시된 파일 또는 ~/.aws/config에 접근
  5. AWS_CONFIG_FILE에 명시된 파일 또는 ~/.aws/config에 접근하여 role에 관련된 데이터(arn 등)로 AWS STS에 AssumeRole
  6. BOTO_CONFIG에 명시된 파일에 접근
  7. /etc/boto.cfg에 접근
  8. ~/.boto에 접근
  9. EC2 인스턴스의 IAM role 설정에 접근

EC2 인스턴스에서 boto3를 사용하는 경우 IAM role을 사용하는 것이 좋고, 그렇지 않은 경우라면 공유 자격 증명 파일(~/.aws/credentials)을 쓰는 것이 좋다고는 하는데, AWS의 컴퓨팅 파워를 사용한다면 되도록 Role을 사용하는 것을 추천하고 싶다. Access Key들은 계정 비밀번호와 같아서, 탈취되면 별도의 필터링 없이 아무나 다 쓸 수 있는데, IAM Role은 trust relationship을 설정해서 Assume 대상을 한정(Lambda만 쓸 수 있게, API Gateway만 쓸 수 있게 등)지을 수 있기 때문이다.