mcpField
A
adding-project-secret-api-key-auth

adding-project-secret-api-key-auth

github.com/posthogセキュリティ40.5k140 回インストール今日更新
リポジトリ

adding-project-secret-api-key-auth について

PostHog の API エンドポイントに Project Secret API Key(PSAK)認証を追加する開発者向けガイドです。スコープ認可、認証設定、レート制限、合成ユーザーの扱い、必要なテストを説明します。

主な機能

  1. 01プロジェクト単位のサービス資格情報の説明
  2. 02スコープ許可リストの設定
  3. 03エンドポイント認証と操作認可
  4. 04キー単位・チーム単位のレート制限
  5. 05合成ユーザーと権限の処理

活用シーン

  1. 01API 操作で PSAK 認証を有効化
  2. 02付与可能なキーのスコープを設定
  3. 03合成ユーザーの権限エラーを回避
  4. 04認可・チーム紐付け・制限をテスト

インストール

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

$npx skills add https://github.com/posthog/posthog --skill adding-project-secret-api-key-auth

インストール後、Claude Code で/adding-project-secret-api-key-authを入力して読み込まれたか確認します。

詳細

エンドポイントへのプロジェクトシークレット API キー(PSAK)認証の追加

PSAK とは

ProjectSecretAPIKey は、プロジェクトスコープでユーザーに紐づかないサービス認証情報です(posthog/models/project_secret_api_key.py)。個人用 API キーのように動作しますが、ユーザーがプロジェクトを離れても存続し、独自のスコープを持ち、実際の User 行ではなく合成ユーザーとして認証します。

  • トークン形式: phs_...(Bearer ヘッダーのみ — レガシートークンと異なりボディからのフォールバックはありません)。
  • スコープはリソースタイプ内でプロジェクト全体にわたり、オブジェクトレベルのアクセス制御(リソース単位の RBAC)を意図的に無視します。
  • TeamSecretTokenAuthentication と混同しないでください — こちらはレガシーなチーム単位の Team.secret_api_token(同じく phs_ プレフィックス)を検証するもので、フィーチャーフラグのローカル評価や同様の PSAK 以前のサーフェスにのみ使用されます。いずれ PSAK へ移行することが決まっています。

キーは POST /api/environments/:id/project_secret_api_keys で管理されます(ラベル + スコープ、平文の値は一度だけ返却、roll アクションでローテーション、プロジェクトごとに最大 50 個、ワイルドカード * スコープは不可)。

viewset アクションの配線 — チェックリスト

仕組みはすでに実装されていますが、まだ何も配線されていません — 最初の想定利用者は endpoints(プロダクト)の run アクションです。必要なのは以下の 4 点、すべて必須です:

1. スコープ/アクションのペアをホワイトリストに登録する

PSAK で割り当て可能なスコープは posthog/scopes.py にあるグローバルな許可リストです:

PROJECT_SECRET_API_KEY_ALLOWED_API_SCOPE_ACTION: list[tuple[APIScopeObject, APIScopeActions]] = [("endpoint", "read")]

プロダクトが記載されていない場合、認証が試みられる前にキー作成がスコープを拒否します。まずここに (scope_object, action) タプルを追加してください。

同じスコープを frontend/src/lib/scopes.tsx の PROJECT_SECRET_API_KEY_ALLOWED_API_SCOPE_ACTION にも追加してください。プロジェクト設定のスコープピッカーはそのリストからチェックボックスを生成するため、バックエンドのみの変更ではユーザーがスコープを付与する手段がなくなります。posthog/test/test_scopes.py が両方のリストを比較します。

2. オーセンティケータを追加し、アクションをオプトインする
class MyViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet):
    scope_object = "endpoint"
    authentication_classes = [ProjectSecretAPIKeyAuthentication]  # extends, TeamAndOrgViewSetMixin keeps session/PAK auth
    psak_allowed_actions = ["run"]

psak_allowed_actions はデフォルト拒否です: APIScopePermission はアクションが記載されていない PSAK リクエストを拒否します(「This action does not support project secret API key access」)。プログラムによるアクションのみを記載してください — 人間主導であるべき CRUD は決して含めないでください。

APIScopePermission はチームのバインディングも自動的に強制します: PSAK は view.team == key.team に対してのみ機能するため、PSAK 認証はプロジェクトスコープのルート(/api/environments/:id/...)でのみ意味を持ちます。

3. PSAK 対応のスロットルを使用する

PersonalApiKeyRateThrottle のサブクラスは PSAK リクエストを暗黙的にバイパスします(個人キーがなければスロットリングもなし)。posthog/rate_limit.py の PSAK 対応ペアを使用してください:

  • PersonalOrProjectSecretApiKeyRateThrottle — キー単位のバジェット(psak:{key_id} をキーとする)、個人キーも引き続きスロットリングします。
  • ProjectSecretApiKeyTeamRateThrottle — チーム単位の集計(psak-team:{team_id} をキーとする)、プロジェクトがいくつのキーを発行しても PSAK の総負荷に上限を設けます。キー単位のスロットルと並べてスタックしてください。

これらをサブクラス化してプロダクト固有の scope/rate を設定してください。各スロットルは scope 文字列ごとに独自のキャッシュバケットを保持することに注意してください。

4. 合成ユーザーを処理する

request.user は User ではなく ProjectSecretAPIKeyUser(SyntheticUser、posthog/synthetic_user.py)です:

  • user.id は None です — 外部キーとして絶対に使用しないでください。user.current_team_id を使用してください。

  • has_perm() は常に False を返します — Django のパーミッションチェックは暗黙的に拒否します。

  • これに対するオブジェクト単位のアクセス制御チェックはスキップしてください(PSAK スコープは設計上プロジェクト全体に及びます):

    if is_authenticated_via_project_secret_api_key(request):
        return  # PSAK bypasses object-level RBAC deliberately
    

    isinstance(user, ProjectSecretAPIKeyUser) は、リクエストがスコープ内に存在しない場合にのみ使用してください。

  • report_user_action は合成ユーザーを破棄します — PSAK で認証された呼び出しの分析が必要な場合は、posthoganalytics.capture(distinct_id=user.distinct_id, ...) で明示的にキャプチャし、auth_method プロパティを含めて、両方のパスが同じイベント形状を出力するようにしてください。

  • HogQL システムテーブル:Database.create_for は、キーのスコープがカバーしていない RBAC スコープ付きシステムテーブルを非表示にします(readable_system_table_access_scopes() を経由)。

分岐が必要な場合に posthog/permissions.py にあるヘルパー:is_authenticated_via_project_secret_api_key(request) および is_service_auth(request)(PSAK + レガシーチームトークンをカバー)。

無料で得られるもの

  • クエリタグ付け:オーセンティケーターが tag_authentication(access_method=AccessMethod.PROJECT_SECRET_API_KEY, api_key_mask=..., api_key_label=...) を呼び出すため、ClickHouse の query_log による帰属がエンドポイントごとのコードなしで機能します。新しいオーセンティケーターを追加する場合は、tag_authentication(posthog/clickhouse/query_tagging.py 内の単一のファネル)を通じてタグ付けしてください — アドホックな tag_queries 呼び出しでは行わないでください。
  • last_used_at トラッキング:.update() を経由して最大 1 時間ごとに更新されます(ModelActivityMixin をバイパスするため、定期的な認証がアクティビティログをスパムしません)。
  • アクティビティログ:キーの作成/更新/ロール/削除時。

PSAK でゲートされたエンドポイントを呼び出す

curl -s https://us.posthog.com/api/environments/<project_id>/<your_action_path>/ \
  -H "Authorization: Bearer phs_<key>" \
  -H "Content-Type: application/json" \
  -d '{...}'

テスト

posthog/api/test/test_authentication.py、posthog/test/test_permissions.py、posthog/test/test_rate_limit.py の PSAK セクションを踏襲してください。最低限以下をカバーしてください:

  • 正しいスコープでの許可されたアクション → 200
  • psak_allowed_actions に含まれないアクション → 403
  • スコープの欠落/誤り → 403
  • 別のチームのプロジェクトのキー → 403
  • 同じアクションに対する非 PSAK 認証は引き続き機能する

コメント