setup-security-agent について
後続の AWS Security Agent によるスキャンやペンテストに必要な AWS リソースを準備するセットアップスキルです。AgentSpace、IAM サービスロール、S3 バケットを設定し、ワークスペースの情報をローカルに保存します。
主な機能
- 01AgentSpace の確認・選択・作成
- 02IAM サービスロールの作成と設定
- 03S3 バケットの作成と保護
- 04ロールとバケットを AgentSpace に登録
- 05ワークスペース設定のローカル保存
活用シーン
- 01AWS Security Agent ワークスペースの初期設定
- 02セキュリティスキャン用 AWS リソースの準備
- 03ペンテスト用 AgentSpace の準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill setup-security-agentインストール後、Claude Code で/setup-security-agentを入力して読み込まれたか確認します。
詳細
AWS Security Agent — セットアップ
このスキルが扱うのは、ワークスペースに動作するエージェントスペース、IAM サービスロール、S3 バケットが連携した状態を確保することだけです。スキャンとペネトレーションテストは別のスキルで実行され、ここでの設定が完了していることを前提とします。
ローカル状態の規約
すべての Security Agent スキルは、ワークスペース内の .security-agent/ に状態を共有します。
config.json—{ "agent_space_id": "as-...", "region": "us-east-1", "code_reviews": { "<abs_path>": "cr-..." } }。アカウント ID、ロール ARN、バケット名は規約に基づいて導出されます。code_reviewsマップを使うと、スキャンでワークスペース用の同じ CodeReview を再利用できます。scans.json—{ scan_id, code_review_id, job_id, agent_space_id, scan_type, title, started_at, status, path }の配列(直近 50 件を保持)pentests.json— ペネトレーションテストジョブ用の同じ形式.gitignore— 内容は*で、このディレクトリが追跡対象にならないようにしますfindings-{scan_id}.md— 各スキャンの完了後にスキャンスキルが書き込みます
このスキルの役割は、config.json に値を設定し、.gitignore を作成することです。
導出される値(設定より規約を優先)
ほかのスキルは、config.json から読み取るのではなく、呼び出しのたびに次の値を計算します。
| 値 | 規約 |
|---|---|
ACCOUNT | aws sts get-caller-identity --query Account --output text |
REGION | config.region(デフォルトは us-east-1) |
service_role_arn | arn:aws:iam::${ACCOUNT}:role/SecurityAgentScanRole |
s3_bucket | security-agent-scans-${ACCOUNT}-${REGION} |
設定を最小限にする理由:ロール名とバケット名は決定的に導出できるため、保存すると設定のずれが生じるリスクがあります(ユーザーがロールを手動で再作成すると、古いパスが気づかれないまま使われる可能性があります)。ユーザーが複数のエージェントスペースを持つ場合があり、セッションごとにどれを使うか尋ねたくないため、agent_space_id だけを保存します。
ワークフロー
-
既存の状態を確認:
.security-agent/config.jsonが存在する場合は読み取ります。 -
呼び出し元の ID とリージョン:
export ACCOUNT=$(aws sts get-caller-identity --query Account --output text) export REGION="${AWS_REGION:-us-east-1}" -
エージェントスペース:
-
config.agent_space_idが設定されている場合は、次のコマンドで確認します。aws securityagent batch-get-agent-spaces --agent-space-ids <id>応答で存在しないことが示された場合は、未設定として扱います。
-
未設定の場合は、既存のものを一覧表示します。
aws securityagent list-agent-spaces-
既存のものがある場合 → 名前と ID をユーザーに提示し、「これらのいずれかを再利用しますか。それとも新しく作成しますか?」と尋ねます。回答を待ちます。自動選択してはいけません。
-
ユーザーが選んだ場合は、その
agentSpaceIdを使用します。 -
ユーザーが新規作成を希望する場合、または既存のものがない場合:
aws securityagent create-agent-space --name security-scans返された
agentSpaceIdを取得します。
-
-
-
サービスロール(
SecurityAgentScanRole、ARN はarn:aws:iam::$ACCOUNT:role/SecurityAgentScanRole):-
次のコマンドで確認します。
aws iam get-role --role-name SecurityAgentScanRole -
NoSuchEntityが返された場合は、ロールを作成します。冪等性に関する注意: ロールがすでに存在すると、create-roleはEntityAlreadyExistsで失敗します。その場合は、信頼ポリシーが正しいことを確認するため、update-assume-role-policyに進みます。# 信頼ポリシー — aws:SourceAccount による混乱した代理人の防止策を含む cat > /tmp/sa-trust.json <<EOF {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"securityagent.amazonaws.com"},"Action":"sts:AssumeRole","Condition":{"StringEquals":{"aws:SourceAccount":"${ACCOUNT}"}}}]} EOF # 権限ポリシー(S3 + CloudWatch Logs) cat > /tmp/sa-perms.json <<EOF {"Version":"2012-10-17","Statement":[ {"Effect":"Allow","Action":["s3:GetObject","s3:GetObjectVersion","s3:ListBucket"],"Resource":["arn:aws:s3:::security-agent-scans-${ACCOUNT}-${REGION}","arn:aws:s3:::security-agent-scans-${ACCOUNT}-${REGION}/*"]}, {"Effect":"Allow","Action":["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],"Resource":"arn:aws:logs:*:${ACCOUNT}:log-group:/aws/securityagent/*"} ]} EOF aws iam create-role --role-name SecurityAgentScanRole --assume-role-policy-document file:///tmp/sa-trust.json # EntityAlreadyExists の場合: aws iam update-assume-role-policy --role-name SecurityAgentScanRole --policy-document file:///tmp/sa-trust.json # 権限は常に再適用します: aws iam put-role-policy --role-name SecurityAgentScanRole --policy-name SecurityAgentCodeReviewAccess --policy-document file:///tmp/sa-perms.json
-
-
S3 バケット(
security-agent-scans-$ACCOUNT-$REGION):バケット所有権の強制(必須)。 バケット名は呼び出し元の AWS アカウント ID とリージョンから導出されます。どちらも秘密情報ではなく、ARN や ECR URI から公開情報として導出できます。そのため、第三者が自身のアカウントで予測可能な名前を先に登録(「占有」)できてしまいます。すべての S3 呼び出しで
--expected-bucket-owner "$ACCOUNT"を指定する必要があります。これにより、バケットが別の所有者のものである場合、操作は安全側に失敗します。存在するものの他者が所有するバケットで403 Forbiddenが発生した場合は、致命的です。セットアップを中止し、アップロードは絶対に行わないでください。-
プローブ(所有権を確認します):
BUCKET="security-agent-scans-${ACCOUNT}-${REGION}" NEED_CREATE=0 if aws s3api head-bucket --bucket "$BUCKET" --expected-bucket-owner "$ACCOUNT" 2>/tmp/sa-head.err; then : # バケットが存在し、このアカウントが所有しています。安全に再利用できます elif grep -q '404' /tmp/sa-head.err; then NEED_CREATE=1 elif grep -Eq '403|Forbidden' /tmp/sa-head.err; then echo "致命的エラー:バケット $BUCKET は存在しますが、別のアカウントが所有しています(403)。バケットの占有の可能性があるため、処理を中止します。何もアップロードされていません。" >&2 exit 1 else cat /tmp/sa-head.err >&2; exit 1 fi -
見つからない場合は作成します。
BucketAlreadyExistsエラーは、別のアカウントがすでにグローバル名を所有していることを意味します。致命的なエラーとして扱い、問題のない処理として扱えるBucketAlreadyOwnedByYouとは明確に区別してください。以降の処理に進む前に、作成後の所有権を再確認してください。if [ "$NEED_CREATE" = "1" ]; then if [ "$REGION" = "us-east-1" ]; then # us-east-1:LocationConstraint は指定しません aws s3api create-bucket --bucket "$BUCKET" 2>/tmp/sa-create.err || true else # その他のリージョン: aws s3api create-bucket --bucket "$BUCKET" \ --create-bucket-configuration LocationConstraint="$REGION" 2>/tmp/sa-create.err || true fi if grep -q 'BucketAlreadyExists' /tmp/sa-create.err; then echo "致命的エラー:バケット名 $BUCKET はすでに別のアカウントが所有しています(BucketAlreadyExists)。バケットの占有の可能性があるため、処理を中止します。" >&2 exit 1 elif [ -s /tmp/sa-create.err ] && ! grep -q 'BucketAlreadyOwnedByYou' /tmp/sa-create.err; then cat /tmp/sa-create.err >&2; exit 1 fi # 新しく作成したバケットを使用する前に、所有権を確認します。 aws s3api head-bucket --bucket "$BUCKET" --expected-bucket-owner "$ACCOUNT" fi -
パブリックアクセスブロックと 30 日間のライフサイクルを常に適用(再適用)します。
aws s3api put-public-access-block --bucket "$BUCKET" \ --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true cat > /tmp/sa-lifecycle.json <<'EOF' {"Rules":[{"ID":"AutoDeleteUploads","Status":"Enabled","Filter":{"Prefix":""},"Expiration":{"Days":30}}]} EOF aws s3api put-bucket-lifecycle-configuration --bucket "$BUCKET" --lifecycle-configuration file:///tmp/sa-lifecycle.json
-
-
エージェントスペースにロールとバケットを登録します(冪等):
-
既存のリソースを読み取ります。
aws securityagent batch-get-agent-spaces --agent-space-ids <id>agentSpaces[0].awsResources.iamRolesとawsResources.s3Bucketsを確認します。 -
これらのリストにロール ARN またはバケット名がない場合は、マージして更新します。
aws securityagent update-agent-space --agent-space-id <id> --name <existing-name> \ --aws-resources iamRoles=[<arn1>,<arn2>...],s3Buckets=[<bucket1>,<bucket2>...]
-
-
.security-agent/config.jsonに永続化します(最小限 — アカウント/ロール/バケットは導出されます)。{ "agent_space_id": "as-xxxxx", "region": "us-east-1" } -
存在しない場合は gitignore を作成します。
mkdir -p .security-agent echo '*' > .security-agent/.gitignore -
ユーザーに確認します:「セットアップが完了しました。セキュリティスキャンやペネトレーションテストを今すぐ実行できます。」
ルール
- エージェントスペースが複数存在する場合、決して自動選択しない — 必ずユーザーに尋ねる
- 安全保護を決して無効にしない(パブリックアクセスブロックはオンのままにする)
- 導出されたバケットに対するすべての S3 呼び出しは
--expected-bucket-owner "$ACCOUNT"を必ず渡す必要があります。バケット名は秘密ではないアカウント ID から導出されるため、第三者が先に登録できます。他者所有のバケットでの403/BucketAlreadyExistsは致命的です — 中止し、決してアップロードしないでください。 - 信頼ポリシーは
securityagent.amazonaws.com(本番サービスプリンシパル)を許可し、aws:SourceAccountの混乱した代理ガードを含める必要があります - ユーザーが独自のロール名またはバケット名(従来のデフォルトとは異なるもの)を指定した場合、次のように伝えてください。このプラグインは慣例ベースのデフォルト(
SecurityAgentScanRole/security-agent-scans-${ACCOUNT}-${REGION})を使用します。これらのデフォルトを受け入れるか、スキルを拡張するかのいずれかです — 他のスキルはこれらの名前を設定から読み取るのではなく導出します。 config.jsonが存在しない場合、スキャンおよびペネトレーションテストのスキルはこのスキルをインラインで呼び出すことができます — 初めてのユーザーはセットアップを別途実行する必要はありません。
トラブルシューティング
iam:CreateRoleの呼び出しでAccessDenied→ ユーザーに IAM 権限がありません。自身のロール ARN でセットアップを実行するか、iam:CreateRole+iam:PutRolePolicyを付与するよう依頼してください。s3api create-bucketでAccessDenied→ バケット名がグローバルに使用されているか、ユーザーにs3:CreateBucketがありません。自身が所有する既存のバケットを使用し、それを明示的に渡すよう提案してください。- 導出されたバケットで
403 Forbidden/BucketAlreadyExists→ 予測可能な名前が別のアカウントに所有されています(バケットスクワッティング)。これは設計上致命的です — アップロードしないでください。ユーザーに自身が所有するバケット名を選んでもらい(または想定されるアカウント/リージョンから実行してもらい)、セットアップを再実行してください。 - ロールは存在するが信頼ポリシーが誤っている →
update-assume-role-policy(ステップ 4 のフォールバック)。そのロールを更新したくない場合は、別のロール ARN をユーザーに尋ねてください。 - エージェントスペースは存在するが別のリージョンにある → ユーザーに伝えてください。正しいリージョンを使用するか、現在のリージョンに新しいスペースを作成することを提案してください。