0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IAM Identity CenterもIdPもない環境で、CloudWatchをAI(MCP)から安全に操作する — IAM Roles Anywhere実装記

0
Last updated at Posted at 2026-07-16

CloudWatchをAIエージェント経由で使いたい。でも「Identity Center も IdP もない、長期アクセスキーは使いたくない、また費用もかけたくない」——こんな時のソリューションです。

構成図

TL;DR

  • ローカル Mac で動く AI エージェント(Claude Code / Claude Desktop)から、awslabs の CloudWatch MCP Server を使って CloudWatch のログ・メトリクス・アラームを分析したい。
  • 前提: IAM Identity Center なし / OIDC・SAML の IdP なし / 長期アクセスキーは使いたくない
  • 結論は IAM Roles Anywhere + 自己署名ルート CA。追加費用 $0 で、AWS 公式が推奨する「一時クレデンシャル」の原則に則ることができる。
  • AI 専用の IAM ロールを人間用と分離する。MCP 経由のアクセスを CloudTrail で切り分けられ、権限も最小化できる。

背景 — Amazon CloudWatchをMCP経由で操作して楽をしたい

CloudWatch のログを Logs Insights で分析する、メトリクスをグラフ化する、発火中のアラームを一覧する。こういった運用の定型作業は、AI エージェントに MCP(Model Context Protocol)サーバー経由で操作できれば便利です。awslabs が公式に出している awslabs.cloudwatch-mcp-server を使えば、ログ検索・Logs Insights クエリ・メトリクス取得・アクティブアラーム取得といったツールがそのままエージェントの手足になります。

本記事はそのエージェントに対して AWS クレデンシャルをどう供給するかに焦点を当てています。

  • IAM Identity Center(旧 AWS SSO)が未導入 — 組織判断が必要で、すぐには入れられない
  • OIDC / SAML の IdP がない — フェデレーションのタネがない
  • 長期アクセスキーは避けたい — AWS 公式が明確に非推奨としている
  • 実行環境はローカル Mac — EC2/ECS のインスタンスロールが使えない

「ローカル Mac」「Identity Center なし」「IdP なし」は多くの個人開発者・小規模チームが直面する構成です。ここで長期アクセスキーを ~/.aws/credentials に置いてしまうのが最も安易ですが、それは避けたい。


なぜ IAM Roles Anywhere なのか

候補を並べて消去法で残ったのが IAM Roles Anywhere でした。

方式 判定
IAM Identity Center ✗ 未導入。導入は組織判断
OIDC / SAML フェデレーション ✗ 対応 IdP がない
自前 OIDC Provider(Cognito 等) △ Issuer の公開 HTTPS・トークン取得フロー自作など手数が多い
EC2 / ECS インスタンスロール ✗ ローカル Mac 用途に不適
長期アクセスキー継続 ✗ AWSが公式に非推奨
IAM Roles Anywhere + 自己署名 CA 採用

Roles Anywhere は、X.509 クライアント証明書を提示して STS の一時クレデンシャルを受け取る仕組みです。

  • Identity Center / 外部 IdP がない環境で AWS が公式に推奨するルートの 1 つ
  • 自己署名ルート CA が Trust Anchor の "External certificate bundle" として公式サポートされている(Private CA 不要)
  • 費用 $0 — Roles Anywhere 本体・STS 発行・CloudTrail 管理イベントのいずれも無料

補足: macOS ローカル機では SSM Hybrid Activation は使えません(AWS 公式ドキュメントで Hybrid 対応 OS は Linux / Windows Server のみと明記、macOS は "Amazon EC2 instances only")。Parameter Store は「呼ぶのに先にクレデンシャルが要る」鶏と卵、DHMC は EC2 専用。非 EC2・非 Identity Center の macOS では、AWS 公式のクレデンシャル供給手段は実質 Roles Anywhere 一択です。

参考までに、2025 年 11 月発表の マネージド "AWS MCP Server" も選択肢ですが、us-east-1 限定 + マネージド提供のみのため、東京リージョン・ローカル PoC 用途では awslabs 版を使いました。


アーキテクチャ

冒頭の図の通り、信頼の起点は 自分で作った自己署名ルート CA です。この CA で署名したクライアント証明書だけが Trust Anchor を通過し、STS から MCP 専用ロールの一時クレデンシャルを受け取れます。


実装手順

0. 前提確認

uname -m   # arm64 → Aarch64 バイナリ、x86_64 → X86_64 バイナリ

1. 自己署名ルート CA を作る

mkdir -p ~/.iam-roles-anywhere && cd ~/.iam-roles-anywhere
umask 077

# ルート CA 秘密鍵(4096 bit)
openssl genrsa -out rootCA.key 4096

# ルート CA 自己署名証明書(10 年、v3 拡張付き)
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 \
  -out rootCA.crt \
  -subj "/C=JP/O=MyOrg/CN=MyOrg-Root-CA" \
  -addext "basicConstraints=critical,CA:TRUE" \
  -addext "keyUsage=critical,keyCertSign,cRLSign"

rootCA.key は MCP 実行マシンに常駐させない。 パスワードマネージャー等に退避し、クライアント証明書を発行するときだけ取り出します。ルート CA 鍵が漏れれば、任意のクライアント証明書を偽造できてしまうためです。

2. クライアント証明書を作る

openssl genrsa -out client.key 2048

# CN は Trust Policy の Condition に使えるので、端末を識別できる名前に
openssl req -new -key client.key -out client.csr \
  -subj "/C=JP/O=MyOrg/CN=my-macbook"

cat > client.ext <<EOF
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = clientAuth
EOF

# ルート CA で署名(1 年、年次ローテ想定)
openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key \
  -CAcreateserial -out client.crt -days 365 -sha256 \
  -extfile client.ext

chmod 600 client.key

3. AWS 側リソース(開発アカウント)

3-1. Trust Anchor — IAM Roles Anywhere コンソール → Create a trust anchor

  • Certificate authority source: External certificate bundle
  • rootCA.crt の中身を貼り付け
  • 生成された ARN を控える: arn:aws:rolesanywhere:ap-northeast-1:<ACCOUNT_ID>:trust-anchor/<TA_ID>

3-2. IAM Role(例: mcp-cloudwatch-readonly

信頼ポリシー:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "rolesanywhere.amazonaws.com" },
    "Action": ["sts:AssumeRole", "sts:TagSession", "sts:SetSourceIdentity"],
    "Condition": {
      "ArnEquals": {
        "aws:SourceArn": "arn:aws:rolesanywhere:ap-northeast-1:<ACCOUNT_ID>:trust-anchor/<TA_ID>"
      },
      "StringEquals": {
        "aws:PrincipalTag/x509Subject/CN": "my-macbook",
        "aws:PrincipalTag/x509Issuer/CN": "MyOrg-Root-CA"
      }
    }
  }]
}

切り分けのコツ: 最初は Condition を ArnEquals(SourceArn)だけにして疎通を確認し、通ったら CN / Issuer 条件を足す。最初から 3 条件を全部盛ると、落ちたときに原因が特定しにくいです。

権限ポリシー(初期・最小):

  • CloudWatchReadOnlyAccess
  • CloudWatchLogsReadOnlyAccess

権限昇格の明示 Deny(MCP 用ロール全般に推奨):

{
  "Version": "2012-10-17",
  "Statement": [{ "Effect": "Deny", "Action": "iam:*", "Resource": "*" }]
}

落とし穴: IAM ポリシーの Action は service 部分を * にできません*:Delete* は Validation エラー)。全サービスの破壊操作を横断禁止したい場合はサービスを列挙する必要があります。ただし Managed の *ReadOnly* ポリシーには Delete 系が含まれないので、実効的な追加防御は「IAM 経由の権限昇格禁止」で十分です。

3-3. Profile(例: mcp-profile

  • 紐付け Role: 上記の MCP 専用ロール
  • セッションポリシー: 付けない(Role ポリシーがそのまま効く)
  • セッション期間: 3600 秒(1 時間デフォルトを維持。延ばさない)
  • 生成された ARN を控える: arn:aws:rolesanywhere:ap-northeast-1:<ACCOUNT_ID>:profile/<PROFILE_ID>

4. aws_signing_helper を入れる

# Apple Silicon の例
curl -L -o ~/.iam-roles-anywhere/aws_signing_helper \
  https://rolesanywhere.amazonaws.com/releases/1.8.2/Aarch64/MacOS/Sonoma/aws_signing_helper
chmod +x ~/.iam-roles-anywhere/aws_signing_helper

# 公式ハッシュと照合(改ざん検知)
shasum -a 256 ~/.iam-roles-anywhere/aws_signing_helper

5. ~/.aws/config

[profile ra-dev]
region = ap-northeast-1
credential_process = /Users/<you>/.iam-roles-anywhere/aws_signing_helper credential-process --certificate /Users/<you>/.iam-roles-anywhere/client.crt --private-key /Users/<you>/.iam-roles-anywhere/client.key --trust-anchor-arn arn:aws:rolesanywhere:ap-northeast-1:<ACCOUNT_ID>:trust-anchor/<TA_ID> --profile-arn arn:aws:rolesanywhere:ap-northeast-1:<ACCOUNT_ID>:profile/<PROFILE_ID> --role-arn arn:aws:iam::<ACCOUNT_ID>:role/mcp-cloudwatch-readonly

6. 疎通確認

AWS_PROFILE=ra-dev aws sts get-caller-identity
# → assumed-role の ARN が返れば成功

AWS_PROFILE=ra-dev aws cloudwatch list-metrics --namespace AWS/EC2 --max-items 1
# → メトリクスが返れば read 権限も OK

AWS_PROFILE=ra-dev aws iam list-users
# → explicit deny で弾かれれば、権限昇格 Deny も効いている

7. CloudWatch MCP を登録

{
  "mcpServers": {
    "cloudwatch": {
      "command": "uvx",
      "args": ["awslabs.cloudwatch-mcp-server@latest"],
      "env": { "AWS_PROFILE": "ra-dev", "AWS_REGION": "ap-northeast-1" }
    }
  }
}

実運用で効いた知見・ハマりどころ

MCP を実タスク(アラーム一覧・Logs Insights・メトリクスのグラフ化)で回して分かった実践的なコツです。

  • get_active_alarms は 50 件を超えると context window を溢れさせる。 件数が多いアカウントでは、いったんファイルに落として jq で集計する方が速くて安全。
  • Logs Insights の正規表現で (?i) インラインフラグが効かない。 大文字小文字を無視したいときは [Ee][Rr][Rr][Oo][Rr] のように書き下すか、like /pattern/ を併用する。
  • ロググループ検索は prefix 一致のみ。 部分一致がほしいときは filter クエリ側で絞る。
  • グラフ生成は MCP の外で。 メトリクスは MCP で取得し、可視化は uv run --script で matplotlib を ephemeral 実行して PNG 保存、という分業が扱いやすい。
  • 権限不足で当初できなかったことcloudtrail:LookupEvents(ユーザー行動ログ)、cloudwatch:PutDashboard(ダッシュボード作成)、EC2 の Name タグ参照。read-only を貫くなら、これらは意図的に落としたままにするか、必要になった時点で最小限だけ足す。

セキュリティ設計

AI経路を人間経路から分離する

MCP 用ロールは、人間が直接使うロールとは別に作る理由は 2 つ。

  1. CloudTrail の切り分け — 「この API 呼び出しは AI が投げたのか、人間が投げたのか」をロールで判別できる。
  2. 権限の最小化 — AI には read-only + 権限昇格 Deny を割り当て、人間ロールとはブラスト半径を分けられる。

補足: aws:ViaAWSMCPService / aws:CalledViaAWSMCP というコンテキストキーは マネージドの AWS MCP Server 経由でのみ付与されます。awslabsをローカル起動する本構成ではロール分離で識別する設計で代替しています。

鍵保護ロードマップ

守るべきは証明書ではなく 秘密鍵 です。証明書(公開鍵)は Git に入れても Slack で送っても攻撃は成立しません。攻撃が成立するのは client.key が漏れたときだけ。段階的に固めていきます。

段階 方式 耐える脅威
初期 ファイル + chmod 600 + FileVault カジュアルな窃取
次段 macOS Keychain 化、--cert-selector 経由 ディスク上に平文 .key を残さない
強固 YubiKey / TPM に鍵格納、PKCS#11 経由 ハードウェア MFA 相当(SAML + MFA と同等水準)

Keychain 化の例:

openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -name "ra-dev"
security create-keychain -p "PASSWORD" ra.keychain
security unlock-keychain -p "PASSWORD" ra.keychain
security import client.p12 -T ~/.iam-roles-anywhere/aws_signing_helper -P "P12_PASSWORD" -k ra.keychain

この場合 --private-key を外し、--cert-selector "Key=CN,Value=my-macbook" に切り替えます。


費用

項目 費用
自己署名 CA + OpenSSL $0
IAM Roles Anywhere(Trust Anchor / Profile / CreateSession) $0
STS 発行 $0
CloudTrail 管理イベント $0(デフォルト)
aws_signing_helper $0(AWS 配布)
合計 $0

対比として、AWS Private CA は general-purpose で約 $400 / 月 short-lived mode で $50 / 月


まとめ

  • Identity Center も IdP もない環境でも、AI(MCP)に安全に AWS にアクセスする方法としてIAM Roles Anywhere + 自己署名ルート CAを利用でる、追加費用は $0。
  • 長期アクセスキーを捨て、X.509 証明書 → STS 一時クレデンシャルに置き換えることで、AWS 公式のベストプラクティスに則ることができる。
  • AI 専用ロールの分離(CloudTrail 切り分け + 最小権限 + 権限昇格 Deny)と、秘密鍵の段階的なハードウェア化
  • 同じ仕組みは CloudWatch に限らず、他の read-only な awslabs MCP サーバーにもそのまま横展開できる。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?