はじめに ─ AI 開発で変わった、AWS の触り方
MOOBON は複数のクライアントの AWS 環境を運用しています。これまでは、クライアントごとにコンソールにログインできる IAM ユーザーを作ってもらい、必要な作業を画面から手動で進める形で管理してきました。
ところが、開発の進め方が AI 中心になってから、少し事情が変わってきました。AI に任せると、AWS CLI を華麗に使って、わかりやすく調査しながら納得の行く形で設定作業を進められます。まずは自社 AWS アカウントだったので、アクセスキー(AKIA…)を発行して使っていたのですが、クライアントの AWS アカウントとなると、セキュリティ意識が一段あがります。
そこできちんと考え直し、アクセスの足回りを SSO + スイッチロールへ作り替えることにしました。セキュリティ面で強固になるだけではなく、AWS コンソールへのログインも格段に便利になりました。
本記事で「やめる」と言っているのは、長期アクセスキーを持つ IAM ユーザーのことです。SSO(IAM Identity Center)やスイッチロールの裏側では IAM ロールを使い続けます。なくすのは「無期限・固定のシークレット」であって、IAM そのものではありません。
本記事のアカウント ID・SSO の開始 URL・クライアント名などは、すべて
<ACCOUNT_ID> や clienta といったプレースホルダに置き換えています。設定の形と考え方が伝わるようにしてあり、実際の固有値は載せていません。1. なぜ AI 開発現場でアクセスキー方式が危ないのか
MOOBON では、開発も運用も AI に任せる場面が増えてきました。Claude Code のような AI エージェントはとても便利なのですが、その同じ環境に長期キーが置いてあると、気をつけるべきことが一気に増えます。具体的には、次の二つです。
鍵だけで全権限が通る ── MFA も期限もない
ユーザーログインでは 2 段階認証(MFA)が当たり前のセキュリティ運用になっていますが、アクセスキーとシークレットアクセスキーだけで同じ権限のコマンドが通るのはセキュリティホールと同じです。しかも接続元管理や期限管理もないので、漏洩した際のリスクは恐ろしいものになります。
大量のコマンドを回す現場ほど、鍵がログに混入しやすい
ログ・エラー出力・チャット履歴に鍵がうっかり混ざるリスクは、AI が自動で多くのコマンドを実行する現場ほど高くなります。自分は気をつけていたとしても、会社の全員の動きを徹底管理することはできません。
SSO + AssumeRole 方式なら、その前提を根本から変えられます。
- そもそも長期シークレットを PC に置かない = AI に渡しうる「無期限の鍵」が存在しない。
- 使うのは数時間で自動失効する一時キー = 漏れても被害範囲が桁違いに小さい。
- 入口で MFA 必須 = エージェントが勝手に再認証することはできない。
2. アクセスキーと SSO + AssumeRole の比較
では、これまでのアクセスキー(長期キー)と、これからの SSO + スイッチロールは何が違うのか。観点ごとに並べると、差がはっきりします。
| 観点 | アクセスキー(従来) | SSO + AssumeRole(これから) |
|---|---|---|
| PC に置くもの | 長期シークレット(AKIA…) | 置かない。都度発行の一時キーのみ |
| 漏れたときの被害 | 無期限の鍵なので、気づくまで悪用され続ける | 一時キーなので、時間で自動的に切れる |
| MFA | 後付けでの強制が難しい | 入口(SSO ログイン)で必須にできる |
| 鍵の所在 | 誰がどの鍵を持つか追いにくい | 身分は SSO に集約され一元管理 |
| 退場・担当替え | 配った鍵を全部消して回る必要がある | SSO ユーザー停止かロール削除だけで完結 |
| コンソール | IAM ユーザーでログイン | SSO ログイン → サインイン URL を生成(8 章) |
並べてみると、従来方式の弱点はどれも 「無期限の鍵が PC に分散して存在する」ことに根があると分かります。便利さと引き換えに、漏れたときの被害範囲が大きく、しかも気づきにくい。SSO + スイッチロールは、その前提自体を取り除きます。具体的な仕組みは、次章で見ていきます。
3. SSO + AssumeRole の構造
考え方はシンプルです。MOOBON の SSO に 1 回だけログインして身分を得て、そこから各クライアントのアカウントへ AssumeRole(スイッチ)して操作します。
あなた(MOOBON の SSO アカウント・MFA 必須)
│ aws sso login(1 日 1 回くらい)
▼
[ MOOBON アカウント <MOOBON_ACCOUNT_ID> ]
│ AssumeRole(スイッチ)
├──────────────► [ クライアント A ] role: MoobonAdmin
├──────────────► [ クライアント B ] role: MoobonAdmin
└──────────────► [ クライアント C ] role: MoobonAdmin- 各クライアントのアカウントには、MOOBON を信頼する
MoobonAdminというロールを 1 つ用意します。 - そのロールは「MOOBON アカウントの人なら引き受けてよい」という信頼設定になっていて、鍵の受け渡しは不要です。
- クライアントのアカウントはそれぞれ独立(請求も各社のまま)。MOOBON の組織に取り込むわけではありません。
得られる認証情報は最長でも数時間で自動失効する一時キーです。PC に固定の鍵を残さず、必要なときだけその場で短命の鍵を得て使う ── これが全体像です。
設計の三本柱 ─ 一時キー / MFA / 信頼ポリシー
一時キー
スイッチで得る認証情報は数時間で自動失効。PC に長期シークレットを置かないので、漏れても影響が時間で切れます。
入口で MFA
MFA は SSO ログイン側で必須に。一度 MFA を通った身分からしかスイッチできないため、全アクセスが MFA 越しになります。
信頼ポリシー
クライアント側ロールの「誰に引き受けさせるか」を MOOBON アカウントに限定。鍵ではなく信頼関係でアクセスを成立させます。
ロールの信頼ポリシーに
aws:MultiFactorAuthPresent 条件を書く手もありますが、SSO セッション由来のスイッチでは期待どおりに効きません。そのため MFA は入口(SSO ログイン)で担保する設計にしています。4. 前提 ─ Organization と Identity Center で SSO ログイン
MOOBON では SSO ログイン設定を数年前に実装していたので、今回は詳細な設定方法は割愛させていただきますが、やることは大きく次の流れです。
- AWS Organizations を有効化 ── 複数アカウントを束ねる土台。すでに組織があればそのまま使えます。
- IAM Identity Center(旧 AWS SSO)を有効化 ── リージョンは普段使う
ap-northeast-1を選びます(後から変えにくいので注意)。 - アイデンティティソースを決める ── 最小構成なら Identity Center 内蔵ディレクトリで十分。既存の Google Workspace / Microsoft Entra ID などがあれば外部 IdP も選べます。
- ユーザー(必要ならグループ)を作成 ── 担当者ぶんを登録します。
- MFA を必須にする ── Identity Center の設定で「サインインごとに MFA を要求」に。本方式の安全性はここで担保するので、必須化は外せません。
- Permission Set を作成 ── 付与する権限の束。まずは
AdministratorAccessの Permission Set を 1 つ用意します(必要に応じて絞れます)。 - アカウントに割り当て ── 作った Permission Set を「どの担当者が、どのアカウントで使えるか」に結びつけます(これを割り当てと呼びます)。これで担当者が MOOBON アカウントにログインできるようになります。なお、割り当てた Permission Set の名前(例:
AdministratorAccess)が、次章の~/.aws/configに書くsso_role_nameの値になります。 - start URL を控える ── Identity Center のダッシュボードに出るアクセスポータルの URL(
https://d-xxxxxxxxxx.awsapps.com/start/)。次章のsso_start_urlに使います。
ここまでで、start URL(https://d-xxxxxxxxxx.awsapps.com/start/)から、2 段階認証(MFA)を経て AWS コンソールに Administrator 権限でログインできるようになります。ただしこれは AWS 側(コンソール)までの話です。AI に AWS CLI を使わせるには、次章で手元の設定を行います。
5. 手元の設定 ─ ~/.aws/config に集約する
初期セットアップは最初の 1 回だけです。まず AWS CLI v2 を入れます。
# macOS brew install awscli aws --version # aws-cli/2.x であること
設定はすべて ~/.aws/config に書きます。長期キーを置かないので、~/.aws/credentials にはもう何も書きません。
# ~/.aws/config [sso-session moobon-sso] sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start/ sso_region = ap-northeast-1 sso_registration_scopes = sso:account:access # MOOBON 本体(あなたの身分) [profile moobon] sso_session = moobon-sso sso_account_id = <MOOBON_ACCOUNT_ID> sso_role_name = AdministratorAccess region = ap-northeast-1
これで moobon プロファイルから自社アカウントを操作できます。クライアント(他社)アカウント用のプロファイルは、AssumeRole を説明する 7 章で追記します。
6. 日常の使い方 ─ sso login とプロファイル
ターミナルから SSO ログインする(トークンが切れた場合も)
aws sso login --profile moobon
ターミナルでコマンドを実行するとブラウザが開くので、IAM Identity Center で作成したアカウントでログインします。1 回ログインすれば数時間〜1 日有効です。期限が切れたらまた叩きます。

ログインしたプロファイルで AWS CLI が使えるか確認
コマンドにプロファイル名を付けて、実際に通るか試します。まずは自社アカウント(moobon)で、コマンドが返ってくるか確認します。
aws s3 ls --profile moobon aws ec2 describe-instances --profile moobon
複数のアカウントを管理しないのであれば、その設定を
[default] として書いておけば、--profile を指定する必要はありません。一方、本記事のように自社+クライアントを切り替える場合は、取り違え防止のため --profile で明示するのが安全です。AI 開発では、使うプロファイルを CLAUDE.md などの指示ファイルに書いておけば、AI が --profile を付けて実行してくれるので、手で打つ手間もほとんどありません。aws sso login まで済めば、Claude Code などの AI も自社の AWS CLI を使えるようになります。他社(クライアント)のアカウントも管理する場合に、次章の AssumeRole(スイッチロール)を足していきます。7. クライアント管理は AssumeRole で ─ 双方 Win-Win
ここからは、他社(クライアント)のアカウントを管理する場合の話です。クライアント側にも Organization と Identity Center を用意してもらい、そこに MOOBON 用の SSO ユーザーを作ってもらう方法もあります。ただ、クライアント全員にその構築・運用をお願いするのは現実的でなく、こちら側もクライアントの数だけ別のログインを抱えることになります。そこで使うのが AssumeRole(スイッチロール)です。次の利点があります。
- クライアント側の手間が最小:Identity Center の構築は不要。「MOOBON を信頼するロール」を 1 つ置いてもらうだけで済みます。
- 身分は 1 つのまま:ログイン済みの MOOBON の身分から、その場でスイッチするだけ。クライアントごとの別ログインは不要です。
この形は、クライアント側の負担が小さいだけでなく、弊社側の日々の運用も大きく楽になります。これまでのようにクライアントごとにユーザー名 × パスワード × 2 段階認証を管理する必要がなくなり、覚えるべき入口が 1 つに集約されるので、AWS CLI の利用も AWS コンソールへのログインも、ぐっとシンプルで扱いやすくなります。
それでは、設定の話に進みます。
① クライアント側に専用ロールを作る
クライアントの了承を得たうえで、そのアカウントに MoobonAdmin ロールを作ります。肝は信頼ポリシーです。「MOOBON アカウントからの引き受け(sts:AssumeRole)を許可する」と書くことで、鍵を渡さずにスイッチできるようになります。下記を trust-policy.json として保存します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::<MOOBON_ACCOUNT_ID>:root" },
"Action": "sts:AssumeRole"
}
]
}このポリシーでロールを作成し、権限(ここでは AdministratorAccess)を付与します。クライアントのアカウントで、一時的な管理権限を使って 1 回だけ実行します。
# クライアントのアカウントで(一時的な管理権限で)1 回だけ実行 aws iam create-role \ --role-name MoobonAdmin \ --assume-role-policy-document file://trust-policy.json aws iam attach-role-policy \ --role-name MoobonAdmin \ --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Principal に MOOBON アカウントの root を指定しているのは、「MOOBON アカウントの誰か」を信頼し、実際に誰が引き受けてよいかの判断を MOOBON 側の権限設定(SSO の Permission Set)に委ねる、という意味です。前提の Permission Set が sts:AssumeRole を許可していれば、これでスイッチが通ります。
ここでは分かりやすさのため
AdministratorAccess を付けていますが、実際の運用では担当範囲に必要なぶんだけに絞るのが望ましいです。信頼ポリシー(誰が引き受けるか)と権限ポリシー(何ができるか)は別物なので、後から権限だけ差し替えられます。② ~/.aws/config にクライアント用プロファイルを足す
作成したロールの ARN を、5 章の ~/.aws/config にスイッチ先のプロファイルとして追記します。
# ~/.aws/config に追記 # クライアントごとに 1 つずつ(スイッチ先)。role_arn の数字はそのクライアントのアカウント ID。 [profile clienta] role_arn = arn:aws:iam::<CLIENT_ACCOUNT_ID>:role/MoobonAdmin source_profile = moobon region = ap-northeast-1 # [profile clientb] ... 以降、担当クライアントを同様に追加
ポイントは source_profile = moobon です。これが「MOOBON の身分を使ってスイッチする」という意味になります。クライアントを増やすときは、同じブロックを足していくだけです。
③ スイッチして操作する
あとは CLI にクライアントのプロファイル名を付けるだけ。スイッチ先の一時キーが自動で使われます。
aws s3 ls --profile clienta aws ec2 describe-instances --profile clienta
8. AssumeRole を使用して AWS コンソールにログインする
AWS CLI だけでなく、クライアントのコンソールをブラウザ画面で開きたいこともあります。AssumeRole は Organization に所属する設定ではないので、SSO ログインページでクライアントの AWS アカウントが選択できるわけではありません。AWS コンソールへログインできないと思ってしまうのですが、実はこれも MOOBON の SSO にログインした状態から、スイッチしてコンソールを開くことができます。スイッチで得た一時キーからサインイン URL を生成するヘルパーを用意しておくと便利です。下記を ~/bin/aws-console として保存します。
#!/usr/bin/env bash
# 使い方: aws-console <プロファイル名> 例) aws-console clienta
set -euo pipefail
PROFILE="${1:?プロファイル名を指定}"
# トークンが切れていたら SSO ログインを促す
aws sts get-caller-identity --profile "$PROFILE" >/dev/null 2>&1 \
|| aws sso login --profile moobon
# スイッチ先の一時クレデンシャルを取り出し、federation 用のセッション JSON を組み立てる
# (--format process の中身は JSON。python3 一発でパース→URL エンコードまで行う)
CREDS=$(aws configure export-credentials --profile "$PROFILE" --format process)
SESSION=$(echo "$CREDS" | python3 -c '
import sys, json, urllib.parse
d = json.load(sys.stdin)
print(urllib.parse.quote(json.dumps({
"sessionId": d["AccessKeyId"],
"sessionKey": d["SecretAccessKey"],
"sessionToken": d["SessionToken"]
})))
')
# federation のサインイントークンを取得 → ログイン URL を組み立てて開く
TOKEN=$(curl -s "https://signin.aws.amazon.com/federation?Action=getSigninToken&Session=$SESSION" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["SigninToken"])')
DEST=$(python3 -c "import urllib.parse;print(urllib.parse.quote('https://ap-northeast-1.console.aws.amazon.com/'))")
URL="https://signin.aws.amazon.com/federation?Action=login&Issuer=moobon&Destination=$DEST&SigninToken=$TOKEN"
echo "$URL"; open "$URL" 2>/dev/null || truechmod +x ~/bin/aws-console aws-console clienta # → ブラウザでクライアント A のコンソールが開く(1 時間ほど有効)
これまではクライアントの AWS コンソールを見るたびに、いまのコンソールからログアウト(あるいはシークレットモードで開き直し)して、クライアントごとに違う IAM ログインページを開き、ユーザー名とパスワードを入力し、2 段階認証まで通して、ようやくそのアカウントのコンソールに切り替えられました。
それが、コマンドたった 1 つです。本当に aws-console clienta と打つだけで、ブラウザが自動で開き、対象クライアントの AWS アカウントにログイン済みの状態でコンソールが立ち上がります。
あとがき
もともとは、AI を前提にした開発現場としてセキュリティを見直すのが出発点でした。ところが進めるうちに、思わぬ形で、日々の運用そのものまで楽になる方法を取り入れることができました。この見直しの根っこにあるのは、「無期限の鍵をどこにも置かない」という一点です。AI に強い権限を持たせて開発・運用する現場では、PC 上の長期キーが意外な経路で抜かれたときの被害が大きく、しかも気づきにくい。しかも、こうしたリスクは一人ひとりの注意や運用ルールに委ねるだけでは防ぎきれません。エンジニアの使い方に任せるのではなく、仕組みそのもので解決するしかない──そう考えました。だからこそ、身分は 1 つに集約し、各アカウントへは数時間で失効する一時キーでスイッチする形に作り替えました。安全になったうえに、日常はむしろ楽になりました。クライアントのコンソールはコマンド 1 つで開き、漏れたときの被害範囲も、退場・担当替えの手間も小さくなります。
AI の活用とセキュリティは、相反するものではなく、足回りの設計で両立できると考えています。AWS の運用設計・アクセス管理・コストの見直しに関するご相談は、AWS コスト分析ツール から、または info@moobon.jp までお気軽にどうぞ。
よくある質問
QSSO + スイッチロールにすると、普段の操作は面倒になりませんか?
日常の手数はほとんど増えません。トークンが切れたら 1 日 1 回ほど `aws sso login --profile moobon` を叩くだけで、あとは CLI に `--profile <クライアント名>` を付ければ各アカウントを操作できます。むしろクライアントごとに鍵を発行・保管・廃棄する手間が消えるぶん、トータルでは管理が軽くなります。
QMFA はスイッチ先のロール側で強制できないのですか?
SSO セッション由来のスイッチでは、ロールの信頼ポリシーに `aws:MultiFactorAuthPresent` を書いても期待どおりには効きません。そのため MFA は入口(MOOBON の SSO ログイン)で必須にして担保します。一度 MFA を通った身分からしかスイッチできないので、結果として全アクセスが MFA 越しになります。
Qクライアントのアカウントを MOOBON の組織(Organizations)に取り込む必要がありますか?
いりません。各クライアントのアカウントは独立したまま(請求も各社のまま)です。やることは、そのアカウントに『MOOBON のアカウントからの引き受けを許可する』信頼設定を持つロール(例: MoobonAdmin)を 1 つ用意するだけ。鍵の受け渡しも、組織への編入も不要です。
Qコンソールで「ロールの切り替え」がエラーになります。設定ミスですか?
設定ミスではなく仕様です。コンソール右上の『ロールの切り替え』UI は、SSO でログインしたセッションからは使えません(入力が正しくても『フィールドが無効』になります)。SSO セッションの一時キーからサインイン URL を生成するヘルパーを用意し、そこからコンソールを開く方法に切り替えてください(本文 8 章)。
Q既存の長期アクセスキー(AKIA…)はどうすればいいですか?
新方式で各アカウントを操作できることを確認できたら、そのクライアントの長期 IAM キーは削除し、`~/.aws/credentials` からも消します。新規の長期キーは原則作りません。
