こんにちは。SCSK渡辺(大)です。
人生初のIDEとしてCloud9を使っていたのですが、とある理由からVisual Studio Codeを使いたくなりました。
Visual Studio CodeからAWSリソースにアクセスするには、アクセスキーが必要になります。
そこで今回は、ベストプラクティスに準拠してアクセスキーを利用する方法を考えてみました。
アクセスキーが漏洩した場合のリスク
一例ですが以下が挙げられます。
- 不正利用により予期せぬ多額の請求
- 顧客情報などの情報漏洩
- リソース削除によるサービス停止
IAMでのセキュリティのベストプラクティス
ベストプラクティスを確認します。
- 付与する権限は最小限にしましょう
- 一時的な認証情報を使用しましょう。それが無理ならアクセスキーをローテーションしましょう
- アクセス先をMFA強制にし、アクセス元にMFA設定にしましょう
MFAを強制したい
Visual Studio CodeからAWSリソースにアクセスするためには、ローカル環境に導入したAWSクレデンシャルファイルにアクセスキーとシークレットキーを明記する必要があります。
ただし、それだけではMFA強制にすることは出来ません。
AWS CLIでMFA強制にするにはひと手間必要です。
このひと手間が面倒だと感じたのでBashシェルスクリプトにしました。
■get-session-token.sh
#!/bin/bash
# credentialsを削除し、credentials.bkをcredentialsとしてコピー
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
if [ -f ~/.aws/credentials.bk ]; then
rm -f ~/.aws/credentials
cp ~/.aws/credentials.bk ~/.aws/credentials
echo "AWS credentials have been reset from backup."
else
echo "Backup file (credentials.bk) not found. Please ensure it exists."
exit 1
fi
# 現在の AWS 設定を確認
echo "Current AWS configuration:"
aws configure list
# MFAトークンコードの入力を求める
read -p "Enter your MFA token code: " token_code
# AWS STS get-session-tokenを実行
session_token=$(aws sts get-session-token --serial-number arn:aws:iam::[アカウントID]:mfa/[MFA名] --token-code $token_code)
if [ $? -ne 0 ]; then
echo "Failed to get session token. Please check your AWS configuration and MFA token."
exit 1
fi
# クレデンシャルを環境変数にエクスポート
export AWS_ACCESS_KEY_ID=$(echo $session_token | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $session_token | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $session_token | jq -r '.Credentials.SessionToken')
# AWSクレデンシャルファイルを更新
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 aws_session_token $AWS_SESSION_TOKEN
echo "AWS credentials have been updated."
# 更新された AWS 設定を確認
echo "Updated AWS configuration:"
aws configure list
# 現在のロールを表示
echo "Current role is..."
aws sts get-caller-identity --query "[Account, Arn]"
if [ $? -ne 0 ]; then
echo "Failed to get caller identity. Please check your AWS configuration."
exit 1
fi
ついでに、スイッチロールもBashシェルスクリプトにしました。
■change-role.sh
#!/bin/bash
# 現在の認証情報を表示
echo "Current identity:"
aws sts get-caller-identity
# ユーザーからアカウントIDとロール名を入力してもらう
read -p "Enter the AWS account ID: " account_id
read -p "Enter the role name: " role_name
# role assumeを実行
echo "Assuming role..."
role_credentials=$(aws sts assume-role --role-arn "arn:aws:iam::${account_id}:role/${role_name}" --role-session-name "${role_name}")
# 環境変数を設定
export AWS_ACCESS_KEY_ID=$(echo $role_credentials | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $role_credentials | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $role_credentials | jq -r '.Credentials.SessionToken')
# 新しい認証情報を確認
echo "New identity after assuming role:"
aws sts get-caller-identity
設計
方針
- IAMユーザーにはIAMロールへスイッチ(AssumeRole)できる権限のみを付与する
- IAMロールの信頼ポリシー上でも、IAMユーザーからのスイッチにはMFA強制にする
- IAMロールにはAdministratorAccessを付与する
構成図
準備
AWS側の作業
- IAMユーザーを作成する
- 自分のMFA設定、アクセスキー作成、下記IAMロールへのスイッチ、のみ許可する
- IAMロールを作成する
- 信頼ポリシーは上記IAMユーザーかつMFA強制でスイッチ許可する
- AdministratorAccessを付与する
- IAMユーザーでAWSマネジメントコンソールにログインする
- MFA設定する
- アクセスキーを作成する
ローカル環境側の作業
- Visual Studio Codeをインストールする
- AWS CLIを導入する
- Visual Studio Codeで「aws –version」と打ってバージョンが表示されることを確認する
- jqを導入ダウンロードする
- Bashシェルスクリプトで使う
- 公式サイトからダウンロードした.exeファイルをjq.exeにリネーム後、所定の場所(WindowsならC:\WINDOWS\system32\jq.exe)に移動する
- Visual Studio Codeで「jq –version」と打ってバージョンが表示されることを確認する
- AWSクレデンシャルファイルを修正する
- Visual Studio Codeで「aws config」と打ち、アクセスキー、シークレットキーを入力する(その他は任意)
- 前述のBashシェルスクリプトを作成する
- credentialsをコピーしてcredentials.bkを作成する
実行結果
1.BashシェルスクリプトでMFA認証します。
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ ./get-session-token.sh
AWS credentials have been reset from backup.
Current AWS configuration:
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************XXXX shared-credentials-file
secret_key ****************XXXX shared-credentials-file
region ap-northeast-1 config-file ~/.aws/config
Enter your MFA token code: 999999
AWS credentials have been updated.
Updated AWS configuration:
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************XXXX env
secret_key ****************XXXX env
region ap-northeast-1 config-file ~/.aws/config
Current role is...
[
"[アカウントID]",
"arn:aws:iam::[アカウントID]:user/[IAMユーザー名]"
]
2.MFA認証したものの、IAMユーザーには殆ど権限ないことを確認します。
特に、IAMロールのリストが表示できないことは重要です。
表示できてしまうと、アクセスキーの不正利用者が全てにスイッチロールすることを試すことが出来てしまうためです。
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ aws iam list-roles
An error occurred (AccessDenied) when calling the ListRoles operation: User: arn:aws:iam::[アカウントID]:user/[IAMユーザー名] is not authorized to perform: iam:ListRoles on resource: arn:aws:iam::[アカウントID]:role/ because no identity-based policy allows the iam:ListRoles action
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::[アカウントID]:user/[IAMユーザー名] is not authorized to perform: s3:ListAllMyBuckets because no identity-based policy allows the s3:ListAllMyBuckets action
3.IAMロールにスイッチロールします。
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ source ./change-role.sh
Current identity:
{
"UserId": "[UserId]",
"Account": "[アカウントID]",
"Arn": "arn:aws:iam::[アカウントID]:user/[IAMユーザー名]"
}
Enter the AWS account ID: [アカウントID]
Enter the role name: [IAMロール名]
Assuming role...
New identity after assuming role:
{
"UserId": "[UserId]:[IAMロール名]",
"Account": "[アカウントID]",
"Arn": "arn:aws:sts::[アカウントID]:assumed-role/[IAMロール名]/[セッション名]"
}
4.IAMロールにはAdministratorAccessが付与されているので、コマンドが受け付けられました。
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ aws iam list-roles
{
"Roles": [
{
"Path": "/service-role/",
~~(中略)~~
"AssumeRolePolicyDocument": {
^C
XXXXX@XXXXXX XXXXXX ~/work/awsTest
$ aws s3 ls
yyyy-mm-dd hh:mm:ss [S3バケット名]
まとめ
思ったより大変でした。
調査の途中、AWS Toolkitとごっちゃになってしまいました…
余談ですが、いまはAWS AmplifyとCDKをマイペースで勉強中です。
当記事もそうですが、アウトプットすることは自分の勉強になるので、次はAmplifyかCDKについての記事を投稿してみたいと思っています。