こんにちは。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についての記事を投稿してみたいと思っています。