AI Agent 時代のシークレット管理設計 — Vault・SSO・MCP の3層アーキテクチャ

AI Agent 時代のシークレット管理設計 — Vault・SSO・MCP の3層アーキテクチャ

AIエージェントが増えると秘密鍵の管理が破綻する。開発者個人・Agent・CI環境の3層に分けて設計する方法と、1Password/Vault/Doppler/AWS Secrets Managerのツール選定マトリクス、MCP×Vaultパターン、SSO+Token Lifecycle設計、監査ログ、鍵流出パターン3つを網羅した設計論。

エンジニアのゆとです。

Claude CodeのSubAgentを3本並列で動かしながら、ふと気づいた。

「今このエージェントたち、どのAPIキーを見ているんだろう」

プロジェクトルートに .env がある。SubAgentが自律的にファイルを読み書きする。そのとき、.env の中身がエージェントのコンテキストに乗っているかどうか、デフォルトでは制御できていない。しかも並列で3本動いているので、どれがどのキーに触ったかのログも残らない。

これが「AIエージェントが増えると秘密管理が破綻する」というやつだ。

1人のエンジニアが1台のマシンで1つのプロジェクトを動かすなら、.envで十分かもしれない。でも現実は違う。Claude Codeがバックグラウンドで動き続け、GitHub Actionsがデプロイを回し、複数のMCPサーバーがAPIを叩き、チームメンバーが同じインフラを共有している。そういう構成では「一か所に平文で書いておく」では絶対に破綻する。

この記事では、設計レイヤーの話をする。個別ツールのセットアップ手順ではなく、「誰が、どのシークレットに、どうアクセスするか」を整理する設計論だ。


エージェントが増えると何が起きるのか

まず問題を具体化しておく。

ローカルで開発している人間エンジニアなら、シークレット管理はこれで済む。

# .env
OPENAI_API_KEY=sk-xxxxx
GITHUB_TOKEN=ghp_xxxxx
STRIPE_SECRET_KEY=sk_test_xxxxx

source .env して作業する。.gitignore に入れてあれば(入れてなければ終わりだが)それなりに安全だ。

問題はAIエージェントが登場してからだ。

Claude Code が起動するとき、プロジェクトルートを丸ごとコンテキストに取り込もうとする。明示的に除外しない限り、.env の内容はLLMに渡る可能性がある。SubAgentsを使った並列実行では、子エージェントがどのファイルにアクセスしたか、デフォルトでは追跡できない。

CI/CDが加わると問題はさらに複雑になる。GitHub Actions のシークレットに30個のAPIキーが登録されていて、誰がいつ追加したかわからない。ローテーションのルールもない。開発者が退職したときに「あのキーは何に使ってたっけ」となる。

MCPサーバーを複数接続すれば、それぞれが別のサービスのAPIキーを要求する。設定ファイルに平文で書くか、環境変数に突っ込むか、という二択になりがちだ。

エージェント時代の秘密管理が壊れる5パターン

1. .envの平文コミット: .gitignoreを忘れた瞬間にGitHubに流出。AIエージェントがコンテキストに取り込む問題もある

2. SubAgentsの監査不能: 並列実行時にどのエージェントがどのキーに触ったか追跡できない

3. MFAバイパス: AIがMFAを通過できないため、エージェント用サービスアカウントのMFAを切ってしまう

4. キーの使い回し: 開発者個人・Agent・CIが同じAPIキーを共有して最小権限の原則が崩壊

5. ローテーションの放棄: 複数のAgent・CIにキーが散らばっていて更新コストが高くなりローテーションを諦める

これらを一気に解決しようとすると大掛かりになる。現実的なのは「3つのレイヤーに分けて考える」ことだ。


3層設計: 開発者個人 / Agent / CI環境

シークレット管理の設計で一番やりがちなミスは「全員が同じキーを使う」構成だ。

開発者、AIエージェント、CIパイプラインは、同じサービスにアクセスするとしても「別の主体」として扱う必要がある。それぞれに別のクレデンシャルを発行し、スコープも分けるのが原則だ。

Layer 1: 開発者個人

人間のエンジニアが使うシークレット。ローカル開発、スクリプト実行、管理系操作。

特性:

  • MFAが使える(むしろ必須)
  • キーの数は多い(全サービスのAPIを試したりする)
  • ローテーション頻度は低くていい
  • 個人のマシンに閉じている

推奨ツール: 1Password または Bitwarden

1Password の op run を使うと、.envop://Vault/Item/field という参照パスを書いて、実行時に実値に展開できる。.env ファイルをGitにコミットしても平文キーが含まれなくなる。

# .env(参照パス版)
OPENAI_API_KEY=op://Personal/OpenAI API Key/credential
GITHUB_TOKEN=op://Personal/GitHub CLI Token/credential

# 実行時
op run --env-file=".env" -- python3 my_script.py

Claude Code で MCP サーバーのキーを管理する場合も同じアプローチが使える。claude_desktop_config.jsonenv フィールドに op:// 参照を書けば、config に平文が残らない。

Layer 2: Agent(自律実行する非人間主体)

Claude Code SubAgent、Devin、GitHub Copilot Workspace など、人間の代わりに自律的に動くもの。

特性:

  • MFAが使えない(インタラクティブ操作が困難)
  • アクセスは最小権限で十分(全APIが必要なわけじゃない)
  • Just-in-Time アクセスが望ましい(タスク中だけ有効)
  • 監査ログが必要(いつ、何にアクセスしたか)

推奨ツール: 1Password Service Account または HashiCorp Vault

1Password の Service Account を使う場合:

from onepassword import Client

# Service Account トークンで初期化(トークン自体は環境変数から)
client = await Client.authenticate(
    auth=os.environ["OP_SERVICE_ACCOUNT_TOKEN"],
    integration_name="claude-code-subagent",
    integration_version="1.0.0",
)

# Vault から必要なキーだけ取得
stripe_key = await client.secrets.resolve("op://Agent Vault/Stripe Key/credential")

Service Account には特定のVaultだけへのアクセス権を付与する。「全Vaultに読み書きできるトークン」は発行しない。

HashiCorp Vault を使う場合は後述するMCPパターンで詳しく説明する。

Layer 3: CI/CD環境

GitHub Actions、CircleCI、Vercel Deploy Hooks など。

特性:

  • 実行環境が使い捨て(コンテナが毎回新規起動)
  • キーの有効期限を短くできる
  • 環境ごとに分離が必要(dev/staging/prod)
  • GitOpsとの相性を考える必要がある

推奨ツール: AWS Secrets Manager / GitHub Actions Secrets / Doppler

環境ごとに明示的にスコープを切る。

# GitHub Actions の例
jobs:
  deploy:
    environment: production  # 環境名でシークレットを分離
    steps:
      - name: Deploy
        env:
          STRIPE_SECRET: ${{ secrets.STRIPE_SECRET_PROD }}  # prodのみ参照
          DB_URL: ${{ secrets.DATABASE_URL_PROD }}

environment: production を指定することで、stagingのシークレットをprodのジョブが誤って参照するリスクを減らせる。


ツール選定マトリクス

4つの主要ツールを3レイヤーごとに整理する。

ツールLayer 1(個人)Layer 2(Agent)Layer 3(CI)価格感
1Password◎ UX最高、op run便利◯ Service Account△ 使えるがCI向けではない個人$3/月〜
HashiCorp Vault△ 個人には重い◎ 動的シークレット、監査ログ◎ AppRole認証、環境分離OSS無料(運用コスト有)
Doppler◯ シンプル、UI良い◯ Service Token◎ CI/CD統合が強い無料〜$6/ユーザー/月
AWS Secrets Manager△ 個人には過剰◯ IAMロールと組み合わせ◎ AWS環境なら最適$0.40/シークレット/月〜

個人エンジニア + Claude Code のローカル開発: 1Password 一択。UXが最も良く、MCP統合も進んでいる。

スタートアップでAgent + CIも使う: Doppler が導入コストとコストのバランスが良い。CI/CDとの統合が素直で、チームスケールしても破綻しにくい。

エンタープライズ or AWS依存が強いプロダクト: HashiCorp Vault + AWS Secrets Manager の組み合わせ。運用は重いがコントロールが最大。動的シークレット(短命なキーの自動発行)が使えるのはVaultだけ。


MCP × Vault パターン: AgentがVault経由で動的に秘匿情報を取得する

ここが設計の核心だ。

従来の発想: 「エージェントに環境変数でキーを渡す」 Vault思想: 「エージェントが必要なときに、必要なキーだけVaultに取りに行く」

この違いは大きい。環境変数は「起動時に全部渡してしまう」ので、エージェントは起動中ずっと全キーにアクセスできる状態になる。Vault経由なら「このタスクに必要なキーだけ、このタスクの間だけ」という制御が可能だ。

HashiCorp Vault + MCP Server パターン

HashiCorp Vault をMCPサーバーとして Claude Code に接続する構成。

まず Vault を起動する(開発環境では dev モードが手軽)。

vault server -dev -dev-root-token-id="dev-token"
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='dev-token'

# シークレットを登録
vault kv put secret/myapp/stripe secret_key=sk_test_xxxx publishable_key=pk_test_xxxx
vault kv put secret/myapp/openai api_key=sk-xxxx

Vault のアクセスポリシーを Agent 用に制限する。

# agent-policy.hcl
path "secret/data/myapp/stripe" {
  capabilities = ["read"]
}

path "secret/data/myapp/openai" {
  capabilities = ["read"]
}

# stripe や openai 以外へのアクセスは拒否(明示しないパスはデフォルト deny)
vault policy write agent-policy agent-policy.hcl
vault token create -policy=agent-policy -ttl=1h  # 1時間で自動失効

Claude Code の claude_desktop_config.json に Vault MCP サーバーを追加する。

{
  "mcpServers": {
    "vault": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-vault"],
      "env": {
        "VAULT_ADDR": "http://127.0.0.1:8200",
        "VAULT_TOKEN": "op://Dev/Vault Agent Token/credential"
      }
    }
  }
}

VAULT_TOKEN は1Passwordの参照パスにしておく。Vault のトークン自体を1Passwordで管理する二重構造だ。

Claude Code(またはSubAgent)は、Vault MCPを通じてシークレットを取得する。

# Claude Code のプロンプト例
vault にある secret/myapp/stripe の secret_key を使って Stripe の残高を確認して

エージェントは vault://secret/myapp/stripe にアクセスし、secret_key の値を取得して Stripe API を叩く。キーの値はエージェントのコンテキストに一瞬乗るが、Vault の監査ログに「誰が、いつ、どのパスにアクセスしたか」が記録される。

動的シークレット(Vault の本領)

Vault の最も強力な機能が「動的シークレット」だ。

通常のシークレット管理は「キーを保存しておいて必要なときに渡す」。Vault の動的シークレットは「必要なときにキーを生成して、一定時間後に自動削除する」。

AWS IAM の一時クレデンシャルを例にすると:

# Vault の AWS Secrets Engine を有効化
vault secrets enable aws

# AWS 接続設定
vault write aws/config/root \
  access_key=$AWS_ACCESS_KEY_ID \
  secret_key=$AWS_SECRET_ACCESS_KEY \
  region=ap-northeast-1

# Claude Code Agent 用のロールを定義(S3読み取りのみ)
vault write aws/roles/claude-agent \
  credential_type=iam_user \
  policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:GetObject", "s3:ListBucket"],
    "Resource": ["arn:aws:s3:::my-project-bucket/*"]
  }]
}
EOF

このロールに対してシークレットを要求すると:

vault read aws/creds/claude-agent
# => access_key: AKIA...(新規発行)
# => secret_key: xxxxxxx(新規発行)
# => lease_duration: 1h(1時間後に自動削除)

Claude Code のSubAgentがタスクを受け取るたびに、新鮮な一時クレデンシャルが発行され、タスク完了から1時間後には自動で無効化される。常設のAPIキーは存在しない。


SSO + Token Lifecycle 設計

SSO(Single Sign-On)とシークレット管理の統合は、チーム運用になると必須になる。

OpenID Connect (OIDC) でCIを無人化する

GitHub Actions では、OIDC を使って「マシンに長期シークレットを渡さない」構成が作れる。

# GitHub Actions の OIDC 設定
jobs:
  deploy:
    permissions:
      id-token: write  # OIDC トークン発行を許可
      contents: read
    steps:
      - name: Configure AWS credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
          aws-region: ap-northeast-1
          # access_key / secret_key は一切不要

GitHub が発行するOIDCトークンをAWSが検証し、一時クレデンシャルを返す。secrets.AWS_ACCESS_KEY_ID のような長期キーは GitHub Actions のシークレット設定に登録すら不要になる。

HashiCorp Vault でも同様のパターンが使える。

# Vault の JWT Auth Method を有効化
vault auth enable jwt

# GitHub Actions の OIDC と紐付け
vault write auth/jwt/config \
  oidc_discovery_url="https://token.actions.githubusercontent.com" \
  bound_issuer="https://token.actions.githubusercontent.com"

# リポジトリ単位でポリシーを割り当て
vault write auth/jwt/role/github-ci \
  role_type="jwt" \
  bound_audiences="https://github.com/my-org" \
  bound_claims='{"repository": "my-org/my-repo"}' \
  user_claim="repository" \
  policies="ci-deploy-policy" \
  ttl="1h"

Token Lifecycle の設計原則

発行時:  最小スコープ・最短TTLで発行
利用時:  使用ログを記録
更新時:  自動ローテーション(Vault で自動化可能)
失効時:  TTL超過または手動revoke
漏洩時:  Vault なら vault token revoke で即時無効化

TTL の目安:

用途推奨 TTL
人間のローカル開発セッション単位(8〜24h)
CI/CD ジョブジョブ時間 + バッファ(1〜2h)
Agent サービスアカウントタスク単位(15min〜1h)
長期バッチ処理最長でも24h、完了時に revoke

「永続するトークン」を発行するのは、バックドアを開けっぱなしにするのと同じだ。


監査ログとアクセス制御

「誰が、いつ、何にアクセスしたか」を記録することは、セキュリティの事後対応に必須だ。

HashiCorp Vault の監査ログ

Vault は監査バックエンドを設定することで、全アクセスを syslog や JSON ファイルに記録できる。

vault audit enable file file_path=/var/log/vault/audit.log

出力されるログのイメージ:

{
  "time": "2026-05-01T14:23:01.123Z",
  "type": "request",
  "auth": {
    "token_type": "service",
    "entity_id": "agent-subagent-01",
    "policies": ["agent-policy"]
  },
  "request": {
    "operation": "read",
    "path": "secret/data/myapp/stripe"
  }
}

entity_id でどのAgentが何のパスを読んだか、タイムスタンプで紐付けできる。

1Password のアクセスログ(Business プラン)

1Password Business では、Vaultへのアクセス、アイテムの閲覧・変更がすべてイベントログに記録される。

Service Account ごとに別のアクセスログが残るので、「どのAgentが何時にどのキーを取得したか」が追跡できる。SOC 2 監査のエビデンスとしても使える。

アクセス制御の実装

Vault のポリシーは HCL で記述し、最小権限を明示する。

# production-agent-policy.hcl

# 本番Stripeキーは読み取りのみ
path "secret/data/production/stripe" {
  capabilities = ["read"]
}

# 本番DBは完全拒否(Agentがデータを直接読む必要はない)
path "secret/data/production/database" {
  capabilities = ["deny"]
}

# メタデータ(キーの存在確認)は許可
path "secret/metadata/production/*" {
  capabilities = ["read", "list"]
}

「何でも書けるポリシー」を発行しない。キーを追加・変更できるのは人間の管理者のみ。Agentは「読む」だけ。書けない。


ハマりどころ — 鍵流出パターン3つ

設計レベルで気をつけるべきパターンを、実際に起きやすいものに絞って紹介する。

パターン1: LLMコンテキスト経由の流出

何が起きるか: Claude Code が自律的にデバッグを進めるとき、エラーメッセージや環境変数をログに吐き出す。そのログに APIキーが含まれていると、プロンプトの context やチャット履歴に乗る。

なぜ起きるか: print(os.environ) 系のデバッグコードをAgentが自動生成したとき。subprocess.run(["env"], capture_output=True) の出力を Claude Code が読んだとき。

対策: .env に平文を書かない。CLAUDE.md の denylist*.env**/.env* を明示する。Claude Code の /permissions.env の読み取りをブロックする。

<!-- CLAUDE.md -->
## 読み取り禁止ファイル

.env, .env.local, .env.production, .env.secrets は絶対に読まない。
環境変数を確認する必要があるときは `op run` 経由で実行する。

パターン2: SubAgent 間のシークレット漏洩

何が起きるか: 親Agentが持っているコンテキスト(APIキーを含む)を、子SubAgentにそのまま引き渡してしまう。

なぜ起きるか: Claude Code のSubAgent はデフォルトで親のコンテキストを継承する。親が .env を読んでいた場合、そのキーの情報が子にも渡る可能性がある。

対策: SubAgent に渡すコンテキストを明示的に絞る。CLAUDE.md の SubAgent セクションで「環境変数を引き渡さない」ことを明示する。

# claude-code-settings.json のイメージ
{
  "subagents": {
    "inherit_env": false,  # 環境変数を継承させない
    "allowed_tools": ["read", "write", "bash"]  # 最小ツールセット
  }
}

パターン3: CI シークレットの使い回しによるスコープ爆発

何が起きるか: ひとつの GITHUB_TOKEN を全 GitHub Actions ジョブで使い回す。そのトークンが repo スコープ全体を持っていると、どのジョブからも全リポジトリに書けてしまう。

なぜ起きるか: 「とりあえず全部許可で発行しておけば動く」という運用のまま放置されるから。

対策: GitHub Actions の permissions を明示的に絞る。

jobs:
  test:
    permissions:
      contents: read  # テストジョブは読み取りのみ
    steps: ...

  deploy:
    permissions:
      contents: read
      deployments: write  # デプロイジョブは deployments の書き込みのみ
      id-token: write     # OIDC トークン発行のみ
    steps: ...

permissions を書かないと GitHub がデフォルトで広めのスコープを付与するので、書かないよりも書いて絞る方が安全だ。


まとめ — 「誰が、いつ、何を使えるか」を設計する

AIエージェントが増えた世界では、シークレット管理は「保存場所」の問題ではなく「アクセス設計」の問題だ。

どこに保存するかよりも、「誰が(主体)」「いつ(TTL)」「何に(スコープ)」「どのようにアクセスするか(プロトコル)」を先に決める。その答えを実装するツールを選ぶ順序が正しい。

個人のローカル開発から始めるなら 1Password の op run が最小コストで一番の改善になる。.env 平文をなくすだけで、Claude Code が .env を読むリスクが消える。

Agentが本番データに触れる構成になったら、Vault の動的シークレットを検討する。常設キーを持たないことで、漏洩してもダメージを最小化できる。

CI/CD は OIDC で長期シークレットを消す。「GitHubに保存するシークレットを増やさない」方向に設計する。

全部いきなりやらなくていい。まず Layer 1(個人)から手をつけて、Agentが増えたらLayer 2、CIを本番化するタイミングで Layer 3、という順で整備するのが現実的だ。


関連記事

1PasswordがAIエージェントの「鍵管理」に本気を出した — MCP対応・SDK連携を開発者目線で解説
1PasswordがAIエージェントの「鍵管理」に本気を出した — MCP対応・SDK連携を開発者目線で解説AIエージェントがAPIキーを扱う時代の鍵管理を1Passwordで解決する方法を解説。Agentic AI Security機能・MCPサーバー対応・Claude Codeやデプロイパイプラインへのシークレット注入の仕組みを開発者目線で整理。Bitwardenとの機能・料金比較も掲載。読む →
1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン
1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン.envファイルの平文管理から脱却するための実践ガイド。1Password CLIを使ったop runによる実行時注入・fish/zshシェル統合・MCPサーバー経由の3パターンを解説。Claude Code SubAgentsとの組み合わせ、Doppler/Infisicalとの比較まで網羅。読む →
Claude Code MCP設定ガイド — サーバーの追加から実用5選まで【2026年版】
Claude Code MCP設定ガイド — サーバーの追加から実用5選まで【2026年版】Claude Code MCPの設定方法をゼロから解説。MCPサーバーの追加・削除・スコープ管理、Filesystem・GitHub・Brave Search・Puppeteer・自作サーバーの実用5選、よくあるエラーと対処法まで網羅。読む →

この記事の情報は2026年4月時点のものです。各ツールの最新機能・料金は公式ドキュメントをご確認ください。

← 記事一覧に戻る