AWS SDK 개발 환경 구축

AWS CLI, AWS SDK를 사용해서 개발 환경을 구축해보도록 하겠습니다.

AWS를 이용하는 방법


AWS를 이용하는 방법에는 크게 3가지 방법이 있습니다. 여기에서는 실제 웹에서 로그인하는 AWS console 방식을 제외하고 AWS CLI, AWS SDK 를 이용하고 공부하는 방법에 대해서 알아보겠습니다. 또한 개발 환경에 맞게 세팅하는 방법에 대해서 알아보겠습니다.

임시 자격 증명(AssumeRole)


개발시 사용하는 AWS 자격증명은 크게 두가지가 있습니다.

Access key를 사용하는 경우는 유출시 치명적이므로, 반드시 AssumeRole을 이용해서 토큰을 발급받아 사용합시다. Assume의 대상인 역할(Role) 또한 필요한 최소 권한만 설정하는게 바람직합니다.

AWS CLI : AssumeRole

AWS CLI에서 아래의 명령을 통해 JSON 형태의 토큰을 발급 받을 수 있습니다. 하지만 토큰을 받아서 다시 그 토큰을 환경변수에 등록하기는 무척이나 번거롭습니다. 게다가 토큰의 최대 만료시간은 12시간이기 때문에 필요할때마다 매번 해당 작업을 반복해야 합니다.

$ aws sts assume-role --role-arn <ROLE_ARN> --role-session-name <session-name>
{
    "Credentials": {
        "AccessKeyId": "ASIA.......",
        "SecretAccessKey": "YwyGY8dF5.......",
        "SessionToken": "IQoJb3JpZ2.......",
        "Expiration": "2024-04-21T08:08:12Z"
    },
}

AssumeRole 스크립트 작성


AssumeRole에서 필요한 3가지 값은 다음과 같습니다. 이 값들을 자동으로 환경변수에 등록하는 스크립트를 작성해봅시다.

JSON 데이터를 처리하는 jq 패키지를 설치하고 스크립트를 작성합니다. $()는 쉘 스크립트에서 명령어 치환(Command Substitution)을 위해 사용되는 구문입니다. 이 구문은 괄호 안의 명령어를 실행하고, 그 결과를 출력합니다.

$ROLE_ARN 환경변수는 해당 스크립트가 실행 될때 원하는 역할(Role)을 입력 받을 수 있게 만들어둡니다.

jq -r 옵션은 출력을 raw 문자열로 반환하라는 의미입니다. 기본적으로 jq는 JSON 문자열 형태로 따옴표로 둘러싸여 있습니다. 하지만 -r 옵션을 사용하면, 따옴표 없이 raw 문자열을 출력합니다. 따옴표 없는 raw 형태의 토큰을 export 를 수행해서 AWS CLI에서 사용하는 환경변수명으로 등록 합니다.

$ apt install jq
#!/bin/bash

output=$(aws sts assume-role --role-arn $ROLE_ARN --role-session-name cli-assume-session)

export AWS_ACCESS_KEY_ID=$(echo $output | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $output | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $output | jq -r '.Credentials.SessionToken')

실행할때는 ROLE_ARN 환경변수에 원하는 역할 ARN 값을 입력합니다. source 명령으로 스크립트를 실행합니다. 현재 실행 중인 쉘에만 AssumeRole이 수행되고 환경변수값이 자동으로 세팅되는 것을 확인 할 수 있습니다. 쉘을 종료하거나 새로운 쉘에는 AssumeRole이 적용되지 않은 상태인 것을 기억하고 필요한 경우에는 해당 스크립트로 AssumeRole을 적용하면 됩니다.

$ export ROLE_ARN=arn:aws:iam::99842...:role/dev-assume-role-AmazonS3FullAccess

$ source ./scripts/set_assume_role.sh
$ echo AWS_SESSION_TOKEN

$ aws sts get-caller-identity

AWA CLI 디버깅


기본적으로 AWS CLI는 명령 출력의 명령 결과와 관련된 성공 또는 실패에 대한 정보를 제공합니다. --debug 옵션은 디버그 로깅을 활성화하는 옵션입니다. 아래의 명령을 통해 해당 로그를 파일로 저장할 수 있습니다.

aws s3 ls --debug 2> debug.txt

aws s3 ls --debug &> debug.txt

AWS SDK : AssumeRole


1. 패키지 설치

AWS SDK를 이용해서 AWS CLI와 동일하게 AssumeRole을 통해서 토큰을 발급받는 개발환경을 구축해보겠습니다. 여기서 사용되는 SDK는 python 패키지인 boto3입니다. 테스트에는 pytestpython-dotenv를 사용하도록 하겠습니다. 필요한 패키지를 우선 설치합니다.

$ pip install boto3

$ pip install pytest python-dotenv

2. .env 파일 작성

.env 파일에 필요한 정보를 입력합니다. AssumeRole을 수행할 수 있는 Access key 정보를 입력하고 Role ARN 정보까지 입력합니다.

.env
AWS_ACCESS_KEY_ID=ASIA.......
AWS_SECRET_ACCESS_KEY=YwyGY8dF5.......

ROLE_ARN=arn:aws:iam::99842...:role/dev-assume-role-AmazonS3FullAccess

3. Access key 세션 생성

Access key를 사용하여 세션을 생성합니다. 이 세션을 fixture로 전달하여 다음 함수에서 AssumeRole을 수행합니다.

tests/conftest.py
import logging
import pytest

import os
from dotenv import load_dotenv

import boto3
from boto3 import Session

# .env 파일 로드
load_dotenv()


@pytest.fixture(scope="session", name="aws_user_session")
def setup_user_session() -> Session:
    aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID")
    aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY")
    region_name = os.getenv("REGION_NAME")

    return boto3.Session(
        aws_access_key_id=aws_access_key_id,
        aws_secret_access_key=aws_secret_access_key,
        region_name=region_name,
    )

4. AssumeRole을 통한 토큰생성 및 세션 생성

세션을 통해 AssumeRole을 수행합니다. 그 결과 발급된 토큰 Credentials을 사용하여 다시 새로운 세션을 만듭니다. 이 세션값을 통해 테스트를 수행 할 수 있습니다.

tests/conftest.py
@pytest.fixture(scope="session", name="assume_role_session")
def setup_role_credentials(aws_user_session: Session):
    role_arn = os.getenv("ROLE_ARN")

    credentials = assume_role(aws_user_session, role_arn)

    session = boto3.Session(
        aws_access_key_id=credentials["AccessKeyId"],
        aws_secret_access_key=credentials["SecretAccessKey"],
        aws_session_token=credentials["SessionToken"],
        region_name=os.getenv("AWS_REGION"),
    )

    logging.info("Role credentials are generated successfully")

    sts = session.client("sts")
    logging.info(sts.get_caller_identity())

    return session


def assume_role(aws_user_session: Session, role_arn: str):
    sts_client = aws_user_session.client("sts")

    response = sts_client.assume_role(
        RoleArn=role_arn, RoleSessionName="boto3-assume-session"
    )

    return response["Credentials"]

5. AssumeRole 세션

이제 AssumeRole을 통해 전환된 세션에 할당된 권한으로 개발을 진행합니다. 아래의 코드는 SecureGroup을 가져와서 출력하는 기능을 테스트하는 코드입니다.

src/ec2.py
import logging


def hello_ec2(ec2_resource):
    logging.info("Hello, Amazon EC2! Let's list up to 10 of your security groups:")
    for sg in ec2_resource.security_groups.limit(10):
        logging.info(f"\t{sg.id}: {sg.group_name}")
tests/test_ec2.py
import pytest

from src.ec2 import hello_ec2


class TestEC2:
    @pytest.fixture(autouse=True)
    def setup(self, assume_role_session):
        self.session = assume_role_session
        self.ec2_resource = session.resource("ec2")

    def test_hello_ec2(self):
        hello_ec2(self.ec2_resource)

정리


Access key를 그대로 개발환경에 사용하는 것은 보안상 위험할 수 있습니다. 따라서 AssumeRole을 통한 개발환경을 구축하는 것이 바람직합니다.

여기서는 AWS CLI와 AWS SDK에서 AssumeRole을 통해 발급받은 토큰을 활용하는 개발환경을 구축했습니다. 이제 구성된 환경을 바탕으로 아래의 URL 링크를 통해서 더 많은 AWS 서비스를 직접 사용하고 공부해 보시길 바랍니다! 😊

AWS CLI

AWS SDK

AWS AWS SDK