概要
データエンジニアをしています。
直近で参画したプロジェクトにて、データマートのデータをファイル形式にして外部のAWS S3へエクスポートする機能を開発する必要がありました。
我々のチームではデータパイプラインをスクラッチで内製開発したという経緯があり、データマートをファイル出力する機能自体は存在していました。
一方で、外部のAWS S3へ出力する機能は存在しなかったので、機能追加とともに主にAssume Roleについて改めて学習する機会となりました。
以降、主にAssume Roleに焦点を当てた内容となります。
Assume Roleの仕組み
まずはかんたんにAssume Roleの仕組みについて振り返ってみます。
IAMユーザーおよびリソースが、STS経由でロールの権限を一時的に引き受ける(Assume)仕組みとなります。引き受けた側は一時的にロールにアタッチされたポリシー相当の権限を行使することができます。
使い所としては下記のようなものがあります。
- 外部AWSアカウントのAWリソースの操作
- 外部AWSアカウントのロールを一時的に引き受けることで、外部AWSのリソースへアクセスできる
- 一時的な認証情報が都度発行されるため、クレデンシャルによるアクセスよりもセキュア
- クロスアカウントアクセス
- 例えばプロダクトや環境ごとに複数のAWSアカウントが存在するとき、それぞれのAWSアカウントにてIAMユーザーを設けるのではなく、それぞれのAWSアカウントにて作成したロールを使用して各アカウントへアクセスする
Assume Roleに対応するためのソースコード改修
ざっくりAssume Roleについて捉えたところで、具体的な必要作業について見ていきます。
今回、Pythonにてアップロードの処理を記述していたため、そこにAssume Roleによる一時的な認証情報の取得処理を加えます。
下記はソースコードの追加内容を簡略化したものです。
# stsへのコネクションを確立
sts_connection = boto3.client('sts')
# stsから一時的なクレデンシャルを発行してもらう
sts_credentials = \
sts_connection.assume_role(RoleArn="[Assume RoleのARN]", RoleSessionName="[任意のセッション名]")
STS_ACCESS_KEY = sts_credentials['Credentials']['AccessKeyId']
STS_SECRET_ACCESS_KEY = sts_credentials['Credentials']['SecretAccessKey']
SESSION_TOKEN =sts_credentials['Credentials']['SessionToken']
# stsの認証情報を用いて各リソースへ接続
s3 = boto3.resource(
's3',
aws_access_key_id=STS_ACCESS_KEY,
aws_secret_access_key=STS_SECRET_ACCESS_KEY,
aws_session_token=SESSION_TOKEN
)
# オブジェクトを外部S3へアップロードする処理
# ...
Assume Roleに対応するためのIAMの編集
Assume Roleによる権限委譲のために、ソースコードだけではなくIAMの編集が必要となります。
「ロールを引き受ける側」と「ロール側」に分けて、設定例を示します。
ロールを引き受ける側
まず、オレンジ色で示された「ロールを引き受ける側」部分の設定を実施します。
Assume Roleするためには、ロールを引き受けるIAMユーザーやリソースに、STSへのアクションを許可するポリシーを設定します。
これは、STSに対してXXXロールを使用するための認証情報の発行を依頼するためです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::[AWSアカウントID]:role/[使用したいロール]"
}
]
}
ロール側
次に、オレンジ色で示された「ロール側」部分の設定を実施します。
Assume Roleするためには、ロール側に「AAA(ユーザーおよびリソース)にロールを使わせてもいいよ」と明記してあげる必要があります。
これは、信頼ポリシーにて表現します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[AWSアカウントID]:user/[Assume Roleを許可するIAM]",
]
},
"Action": "sts:AssumeRole"
}
]
}
さらに、このロールにてどのようなアクションを許可するかも定義をしておきます。ここは要件に合わせて原則最小権限で設定をします。
例えば、AmazonS3ReadOnlyAccessを許可する場合はこのようになります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"s3:Describe*",
"s3-object-lambda:Get*",
"s3-object-lambda:List*"
],
"Resource": "*"
}
]
}
まとめ
- 外部のAWSアカウントへのアクセスをAssume Roleで実施した
- そのために、Assume Roleの概要を把握した後、ソースコードの改修とIAMの編集を実施した
- 既存のデータパイプラインの機能としては、IAMのクレデンシャルキーを用いたデータファイルのエクスポートにのみ対応していたが、Assume Roleによるアクセスも可能となった
- 様々な要件に対応可能となったうえ、よりセキュアな方式を提案することができるようになった