mcpField
I
infisical-sync-skill

infisical-sync-skill

github.com/rightnow-aiセキュリティ18.2k78 回インストール24 週間前に更新
リポジトリ

infisical-sync-skill について

Infisical とシークレットを同期するエージェント向けのリファレンススキルです。API 操作に加え、認証、セキュリティ確認、同期状態の追跡、ローカルの暗号化 vault 操作を扱います。

主な機能

  1. 01Universal Auth による認証手順
  2. 02シークレットの一覧・作成・更新・削除
  3. 03同期状態とハッシュの追跡
  4. 04暗号化 vault 操作のリファレンス
  5. 05セキュリティ確認とトラブルシューティング

活用シーン

  1. 01Infisical のシークレットをローカル vault に同期
  2. 02プロジェクトや環境ごとのシークレット管理
  3. 03認証・権限・接続エラーの調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rightnow-ai/openfang --skill infisical-sync-skill

インストール後、Claude Code で/infisical-sync-skillを入力して読み込まれたか確認します。

同梱ファイルHAND.toml

詳細

Infisical 同期に関する専門知識

1. Infisical API リファレンス

ベース URL

すべてのリクエストの送信先は $INFISICAL_URL です。これはセルフホストインスタンスのベース URL です。例:https://infisical.example.com。

認証 — Universal Auth

Infisical は、エージェント間通信に Universal Auth を使用するマシン ID を使用します。

エンドポイント:POST /api/v1/auth/universal-auth/login

リクエスト:

{
  "clientId": "<INFISICAL_CLIENT_ID>",
  "clientSecret": "<INFISICAL_CLIENT_SECRET>"
}

レスポンス(成功時):

{
  "accessToken": "eyJ...",
  "expiresIn": 7200,
  "accessTokenMaxTTL": 43200,
  "tokenType": "Bearer"
}

curl の例:

RESPONSE=$(curl -s -X POST "$INFISICAL_URL/api/v1/auth/universal-auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"clientId\":\"$INFISICAL_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CLIENT_SECRET\"}")

ACCESS_TOKEN=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")

トークンの有効期間は expiresIn 秒です(通常は 7200 秒=2 時間)。有効期限が切れたら再認証してください。


シークレットの一覧表示

エンドポイント:GET /api/v4/secrets

クエリパラメーター:

パラメーター必須説明
projectIdはいInfisical プロジェクト ID
environmentはい環境スラッグ(例:prod、staging、dev)
secretPathいいえパスのプレフィックス。デフォルトは /
includeImportsいいえインポートされたシークレットを含めるかどうか。デフォルトは false
recursiveいいえサブパス内のシークレットを含めるかどうか。デフォルトは false

curl の例:

curl -s -X GET \
  "$INFISICAL_URL/api/v4/secrets?projectId=$PROJECT_ID&environment=$ENVIRONMENT&secretPath=/" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

レスポンスの形式:

{
  "secrets": [
    {
      "id": "uuid",
      "version": 1,
      "secretKey": "DATABASE_URL",
      "secretValue": "postgres://...",
      "secretComment": "",
      "environment": "prod",
      "workspace": "uuid"
    }
  ],
  "imports": []
}

次のように解析します:

echo "$RESPONSE" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for s in data.get('secrets', []):
    print(s['secretKey'])
"

シークレットの作成または更新

API に単一の upsert エンドポイントはありません。POST は作成のみを行い(シークレットがすでに存在する場合は 409 を返します)、PATCH は更新のみを行います(シークレットが存在しない場合は 404 を返します)。作成してから更新するパターンを使用してください。

ステップ 1 — 作成を試みる(POST)
エンドポイント:POST /api/v4/secrets/{secretName}

リクエストボディ:

{
  "projectId": "<PROJECT_ID>",
  "environment": "<ENV>",
  "secretValue": "<VALUE>",
  "secretPath": "/"
}
HTTP_STATUS=$(curl -s -o /tmp/infisical_response.json -w "%{http_code}" \
  -X POST "$INFISICAL_URL/api/v4/secrets/$SECRET_NAME" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"projectId\":\"$PROJECT_ID\",\"environment\":\"$ENVIRONMENT\",\"secretValue\":\"$SECRET_VALUE\",\"secretPath\":\"/\"}")

成功すると 201 を返します。

ステップ 2 — 409 の場合は PATCH で更新する
エンドポイント:PATCH /api/v4/secrets/{secretName}

if [ "$HTTP_STATUS" = "409" ]; then
  HTTP_STATUS=$(curl -s -o /tmp/infisical_response.json -w "%{http_code}" \
    -X PATCH "$INFISICAL_URL/api/v4/secrets/$SECRET_NAME" \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"projectId\":\"$PROJECT_ID\",\"environment\":\"$ENVIRONMENT\",\"secretValue\":\"$SECRET_VALUE\",\"secretPath\":\"/\"}")
fi

成功すると 200 を返します。それ以外のステータスコードはエラーです。

重要:シークレット名に特殊文字が含まれている場合は、URL エンコードしてください。


シークレットの削除

エンドポイント:DELETE /api/v4/secrets/{secretName}

クエリパラメーター:projectId、environment、secretPath(デフォルトは /)

curl の例:

curl -s -X DELETE \
  "$INFISICAL_URL/api/v4/secrets/$SECRET_NAME?projectId=$PROJECT_ID&environment=$ENVIRONMENT&secretPath=/" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

アクセス可能なプロジェクト(ワークスペース)の一覧表示

エンドポイント:GET /api/v1/workspace

curl -s -X GET "$INFISICAL_URL/api/v1/workspace" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

レスポンス:{ "workspaces": [{ "id": "uuid", "name": "...", "environments": [...] }] }


2. HTTP エラーコード

コード意味対応
200/201成功続行する
400不正なリクエストレスポンスボディをログに記録します。JSON の形式が不正、またはフィールドが不足している可能性があります
401認証されていない再認証します。トークンの有効期限が切れている可能性があります
403禁止マシン ID に権限がありません。Infisical のアクセス制御を確認してください
404見つからないシークレットまたはプロジェクトが存在しません
429レート制限60 秒待ってから 1 回再試行します
500/503サーバーエラーログに記録し、30 秒後に 1 回再試行します。それでも失敗する場合は通知してください

レスポンスボディを信頼する前に、必ず HTTP ステータスを確認してください:

HTTP_STATUS=$(curl -s -o /tmp/infisical_response.json -w "%{http_code}" ...)
if [ "$HTTP_STATUS" != "200" ] && [ "$HTTP_STATUS" != "201" ]; then
  # handle error
fi
RESPONSE=$(cat /tmp/infisical_response.json)

3. 同期状態ファイルの形式

infisical_sync_state.json に保存します:

{
  "last_sync": "2025-01-15T10:30:00Z",
  "project_ids": ["uuid1", "uuid2"],
  "environment": "prod",
  "secrets": {
    "DATABASE_URL": {
      "hash": "sha256_of_key_plus_value",
      "version": 3,
      "last_synced": "2025-01-15T10:30:00Z"
    }
  },
  "error_count": 0,
  "push_count": 12,
  "pull_count": 47
}

ハッシュの計算(値を保存せずに変更を検出するため):

echo -n "DATABASE_URL:postgres://..." | sha256sum | awk '{print $1}'

または Python を使用します:

import hashlib
h = hashlib.sha256(f"{key}:{value}".encode()).hexdigest()

4. Vault 操作リファレンス

ローカル Vault は、暗号化されたキーと値のストレージを提供します。Infisical から同期されたすべてのシークレットはここに保存します。

操作説明
vault_set key=K value=Vシークレット K を書き込む、または上書きする
vault_get key=Kシークレット K を読み取る
vault_listすべてのキーを一覧表示する(値は返されません)
vault_delete key=Kシークレット K を削除する

一括同期のパターン:

// Pull from Infisical → vault
for each (key, value) in infisical_secrets:
    vault_set key=<key> value=<value>

// Optionally remove orphans
vault_list → local_keys
infisical_keys = set of keys returned by Infisical
for key in local_keys - infisical_keys:
    vault_delete key=<key>

5. セキュリティチェックリスト

同期のたびに、次の項目を確認してください:

  • INFISICAL_URL が設定され、空でない
  • INFISICAL_CLIENT_ID が設定され、空でない
  • INFISICAL_CLIENT_SECRET が設定され、空でない
  • アクセストークンがこのサイクルで新たに取得されている(サイクルをまたいで再利用しない)
  • curl コマンドのエコー出力にシークレット値が表示されない(値を直接記述せず、変数を使用する)
  • レスポンスボディをそのままログに記録しない(ログ記録の前に secretValue フィールドを除去する)

6. よくある失敗パターン

「Failed to fetch secrets: 403 Forbidden」

Machine Identity は存在しますが、権限がありません。Infisical で以下を行ってください。

  1. Access Control → Machine Identities に移動します
  2. このエージェントの Identity を探します
  3. プロジェクトで member ロール(読み取り専用の場合は viewer)を割り当てます
「Connection refused / Could not connect to server」

INFISICAL_URL が間違っているか、インスタンスが停止しています。URL にアクセスできることを確認してください。

curl -s "$INFISICAL_URL/api/status" | python3 -c "import sys,json; print(json.load(sys.stdin))"
「invalid character in secret name」

Infisical のシークレット名は [A-Z0-9_] に一致する必要があります。Vault に大文字と小文字が混在するキーがある場合は、プッシュする前に正規化してください。

echo "my_secret_key" | tr '[:lower:]' '[:upper:]'
「accessToken undefined in response」

認証に失敗しました。レスポンス本文にエラーメッセージが含まれています。以下を確認してください。

  1. INFISICAL_CLIENT_ID と INFISICAL_CLIENT_SECRET が正しいこと
  2. Infisical で Machine Identity が無効化されていないこと
  3. Machine Identity のトークン TTL が 0 に設定されていないこと

7. ナレッジグラフのエンティティ

値を公開せずに、フリート全体のシークレットのメタデータを追跡します。

エンティティの種類
  • service — Infisical インスタンス自体
  • secret_project — Infisical のワークスペース/プロジェクト
  • secret — 名前付きシークレット(キーのみ。値は含みません)
関係の種類
  • secret → belongs_to → secret_project
  • secret_project → hosted_by → service
  • secret → synced_to → agent_vault
クエリの例
knowledge_query type=secret                  // list all known secrets
knowledge_query type=secret_project          // list all projects
knowledge_query relation=belongs_to target=<project_id>  // secrets in a project

コメント