概要
AWS の講座などを見ていると,たいがい最初にIAMユーザーを作成する,というチャプターがあります。
IAMユーザーの権限が大きい場合,シークレットキーの漏洩で被害が大きくなる可能性があります。
ユーザーの権限を最小限にし,AssumeRoleにより一時的に開発用のロールを取得する方法を考えました。
Github Codespacesを使うことを想定して開発しますが,他の環境でも転用可能です。
assumeRoleについて
https://dev.classmethod.jp/articles/iam-role-passrole-assumerole/
コード(ロール,ユーザーの設定)
Cloudshellなどで,以下のコマンドを実行します。
"sts:AssumeRole"のみを実行できるIAMユーザーを作成し,"PowerUserAccess"ポリシーを保有するロールを使用できる権限を与えます。
#!/bin/bash
set -e
# ----------- 変数設定 -------------
IAM_USER_NAME="codespaces-user"
ROLE_NAME="codespaces-assumable-role"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# ----------- IAMユーザー作成 -------------
echo "👤 Creating IAM user: $IAM_USER_NAME (if not exists)"
aws iam create-user --user-name "$IAM_USER_NAME" 2>/dev/null || echo "ℹ️ User already exists."
# アクセスキー作成
echo "🔐 Creating access key for $IAM_USER_NAME"
ACCESS_KEYS=$(aws iam create-access-key --user-name "$IAM_USER_NAME")
ACCESS_KEY_ID=$(echo "$ACCESS_KEYS" | jq -r '.AccessKey.AccessKeyId')
SECRET_ACCESS_KEY=$(echo "$ACCESS_KEYS" | jq -r '.AccessKey.SecretAccessKey')
# ----------- AssumeRole パーミッション付与 -------------
echo "📜 Attaching sts:AssumeRole permission to $IAM_USER_NAME"
POLICY_DOC=$(cat <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::$ACCOUNT_ID:role/$ROLE_NAME"
}]
}
EOF
)
echo "$POLICY_DOC" > temp-user-policy.json
aws iam put-user-policy \
--user-name "$IAM_USER_NAME" \
--policy-name "AllowAssumeRole" \
--policy-document file://temp-user-policy.json
rm temp-user-policy.json
# ----------- IAMロール作成 -------------
echo "🎭 Creating IAM role: $ROLE_NAME (if not exists)"
TRUST_POLICY=$(cat <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::$ACCOUNT_ID:user/$IAM_USER_NAME"
},
"Action": "sts:AssumeRole"
}]
}
EOF
)
echo "$TRUST_POLICY" > trust-policy.json
aws iam create-role \
--role-name "$ROLE_NAME" \
--max-session-duration 4 \
--assume-role-policy-document file://trust-policy.json 2>/dev/null || echo "ℹ️ Role already exists."
rm trust-policy.json
# ----------- PowerUserAccess ポリシーをロールにアタッチ -------------
echo "⚡ Attaching PowerUserAccess policy to role: $ROLE_NAME"
aws iam attach-role-policy \
--role-name "$ROLE_NAME" \
--policy-arn arn:aws:iam::aws:policy/PowerUserAccess
# ----------- GitHub 用出力 -------------
echo ""
echo "📝 Add the following IAM user credentials to your GitHub Codespaces secrets:"
echo "-------------------------------------------------------------"
echo "AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID"
echo "AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY"
echo "-------------------------------------------------------------"
実行すると,codespaces-user
というIAMユーザー,codespaces-assumable-role
というIAMロールが作成されます。
ロールのほうには最大セッション時間を設定できる引数(--max-session-duration
)があるので用途に応じて変更します。(デフォルト:1時間)
コード(ログイン用)
上記のスクリプトで最後に出力される,codespaces-user
のAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYを控えておき,Githubレポジトリのシークレットに設定しておきます。
(このシークレットは"sts:AssumeRole"しか実行権限がないので幾分安全なはずですが,念のため漏洩には気を付ける必要があります)
export AWS_PERSISTENT_ACCESS_KEY_ID=xxxxxxxxxxxxxx
export AWS_PERSISTENT_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export AWS_DEFAULT_REGION=ap-northeast-1
以下のシェルスクリプトを実行するとAssume Roleが実行され,新たにAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKENという環境変数が設定されます。
これらは一定時間で無効化される一時的なアクセスキーです。
#!/bin/bash
ROLE_NAME="codespaces-assumable-role"
ACCOUNT_ID="アカウントIDを指定"
# 永続キーを Secrets から設定(最初のみ)
export AWS_ACCESS_KEY_ID=${AWS_PERSISTENT_ACCESS_KEY_ID}
export AWS_SECRET_ACCESS_KEY=${AWS_PERSISTENT_SECRET_ACCESS_KEY}
# AssumeRole 実行
CREDS=$(aws sts assume-role \
--role-arn arn:aws:iam::$ACCOUNT_ID:role/$ROLE_NAME \
--role-session-name codespace-session \
--duration-seconds 14400) # 4h
# 取得した一時トークンで上書き
export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r '.Credentials.SessionToken')
echo "✅ Temporary AWS credentials set"
echo "⏰ Credentials valid until: $(echo "$CREDS" | jq -r '.Credentials.Expiration')"
実行後はPowerUserAccessの権限を得ているので,例えば以下のようなコマンドが実行可能になります。
aws s3 ls
一定時間が過ぎトークンの有効期限が切れた後も,もう一度login.shを実行すれば再度認証できます。
まとめ
認証管理が有効期限つきのトークンになったので,鍵漏洩のリスクが少し減少した。