JSON ウェブトークンの認証

ベクトル検索は、自己署名 JSON ウェブトークン(JWT)を使用して認証済みインデックス エンドポイントをサポートします。インデックス エンドポイントへのアクセスを制御するために、特別に承認された Google サービス アカウントによって発行された署名付き JWT のみを受け入れるように構成されています。つまり、指定されたアカウントを使用するクライアントのみが、エンドポイントと通信できます。

このページでは、JSON ウェブトークン(JWT)認証を使用してインデックス エンドポイントを設定し、それに対してクエリを実行するために必要な手順について説明します。

制限事項

  • JWT 認証は、VPC ピアリングまたは Private Service Connect(PSC)を使用するプライベート エンドポイントでのみサポートされます。
  • JWT 認証は、gRPC を使用して呼び出されるデータプレーン RPC API(MatchService など)でのみサポートされます。このページの RPC の例では、オープンソースの grpc_cli ツールを使用して、デプロイされたインデックス サーバーに gRPC リクエストを送信します。
  • インデックスの作成、デプロイ、管理用の Admin API は、事前定義された IAM ロールを使用して保護されています。

インデックスに対してクエリを実行する JWT の作成と使用

インデックス エンドポイントを作成し、自己署名 JWT を使用してクエリを実行する手順は次のとおりです。

インデックスを作成する

インデックスを作成するの手順に沿って、ベクトル検索インデックスを作成します。

プライベート エンドポイントを作成する

次のいずれかのドキュメント ページの手順に沿って、プライベート エンドポイントを作成します。

サービス アカウントを作成する

サービス アカウントを作成し、サービス アカウント トークン作成者の IAM ロールを付与します。

  1. IAM Service Account Credentials API を有効にして、サービス アカウントを作成します。

    gcloud services enable iamcredentials.googleapis.com --project="PROJECT_ID"
    gcloud iam service-accounts create SERVICE_ACCOUNT_ID --project="PROJECT_ID"
    

    次の値を置き換えます。

    • PROJECT_ID: サービス アカウントを作成するプロジェクト。
    • SERVICE_ACCOUNT_ID: サービス アカウントの ID。

    詳しくは、サービス アカウントの作成をご覧ください。

  2. 次のいずれかのコマンドを使用して、サービス アカウントに iam.serviceAccountTokenCreator IAM ロールを付与します。

    • 次のコマンドにより、サービス アカウントが接続されている Compute Engine VM からサービス アカウントを使用して JWT を作成する権限が付与されます。

      gcloud iam service-accounts add-iam-policy-binding \
         "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com" \
         --role "roles/iam.serviceAccountTokenCreator" \
         --member "serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com" \
         --project "PROJECT_ID"
      

      次の値を置き換えます。

      • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
      • PROJECT_ID: サービス アカウントを作成するプロジェクト。
    • 次のコマンドにより、自分の Google アカウント(ワークステーション上)からサービス アカウントを使用して JWT を作成する権限が付与されます。

      gcloud iam service-accounts add-iam-policy-binding \
         "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com" \
         --role "roles/iam.serviceAccountTokenCreator" \
         --member "user:EMAIL_ADDRESS" \
         --project PROJECT_ID
      

      次の値を置き換えます。

      • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
      • PROJECT_ID: サービス アカウントを作成するプロジェクト。
      • EMAIL_ADDRESS: メールアドレス。

JWT 認証構成を使用してインデックスをエンドポイントにデプロイする

  1. 次の例に示すとおり、インデックスをプライベート エンドポイントにデプロイします。

    gcloud ai index-endpoints deploy-index INDEX_ENDPOINT_ID \
       --index=INDEX_ID \
       --deployed-index-id=DEPLOYED_INDEX_ID \
       --display-name=DEPLOYED_INDEX_NAME \
       --audiences=AUDIENCES \
       --allowed-issuers="SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com" \
       --project=PROJECT_ID \
       --region=LOCATION
    

    次の値を置き換えます。

    • INDEX_ENDPOINT_ID: インデックス エンドポイントの ID。
    • INDEX_ID: インデックスの ID。
    • DEPLOYED_INDEX_ID: デプロイされたインデックスを一意に識別するユーザー指定の文字列。先頭は英字にします。英字、数字、アンダースコアのみ使用できます。形式のガイドラインについては、DeployedIndex.id をご覧ください。
    • DEPLOYED_INDEX_NAME: デプロイされたインデックスの表示名。
    • AUDIENCES: サービス、ワークロード、またはアプリの想定オーディエンスを識別するわかりやすい文字列(例: "123456-my-app")。
    • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
    • PROJECT_ID: Google Cloud プロジェクト ID
    • LOCATION: Vertex AI を使用するリージョン。

自己署名 JWT を使用してインデックスに対しクエリを実行する

大まかに言うと、必要な手順は次のとおりです。

  1. JWT ペイロードを作成します。
  2. 先に作成したサービス アカウントを使用してトークンに署名します。
  3. gRPC 呼び出しを使用してインデックスをクエリし、トークンを認証ヘッダーで渡します。

JWT ペイロードを作成する

ベクトル検索認証は、事前定義されたオーディエンスについて、事前承認されたサービス アカウントで署名された JWT を受け入れます。インデックスをプライベート エンドポイントにデプロイするときに、サービス アカウントとオーディエンスを呼び出し元が指定する必要があります。この設定でインデックスがデプロイされると、そのエンドポイントへのすべての gRPC API リクエストには、発行元(サービス アカウント)によって署名され、指定のオーディエンスを対象とした JWT を含む認証ヘッダーを含める必要があります。署名付き JWT は、gRPC リクエストの authorization ヘッダーで署名なしトークンとして渡されます。JWT には、サービス アカウントで署名されるだけでなく、次のクレームが含まれている必要があります。

  • iss(許可されている発行者)クレームは、サービス アカウントのメールアドレスにする必要があります。次に例を示します。

    "iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com"
    
  • aud(オーディエンス)クレームと sub(サブジェクト)クレームを、どちらも同じ値に設定する必要があります。これは、サービス、ワークロード、アプリの想定オーディエンスを識別するわかりやすい文字列です。次に例を示します。

    "aud": "123456-my-app",
    "sub": "123456-my-app"
    

    この値は、インデックスのデプロイ時に渡された --audiences 引数と一致する必要があります。

  • iat(発行時)クレームは、トークンが発行された時刻に設定する必要があります。exp(有効期限)クレームは少し後(約 1 時間)に設定する必要があります。これらの値は、次のように Unix エポックタイムで表されます。

    "iat": 1698966927, // unix time since epoch eg via date +%s
    "exp": 1698967527 // iat + a few mins (eg 600 seconds)
    

次の例は、単一の JWT ペイロード内のこれらのクレームを示しています。

{
   "iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com",
   "aud": "123456-my-app",
   "sub": "123456-my-app",
   "iat": 1698956084,
   "exp": 1698960084
}

JWT ペイロードは、iss クレームで指定されたサービス アカウントを使用して署名されます。次の例に示すとおり、gRPC メタデータを使用して署名なしトークンとして転送するために Base64 でエンコードされています。ここで、signedJwt は署名付き JWT を含む環境変数を示します。

./grpc_cli call ... --metadata "authorization: Bearer $signedJwt"

JWT を作成する

  1. 呼び出し元が、サービス アカウントに対する roles/iam.serviceAccountTokenCreator ロールを使用できることを確認します。

  2. 未加工の JWT を含む jwt_in.json という名前の JSON ファイルを作成します。

    SA="serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com"
    cat << EOF > jwt_in.json
    {
      "aud": "AUDIENCES",
      "sub": "AUDIENCES",
      "iss": "${SA}",
      "iat": $(date +%s),
      "exp": $(expr $(date +%s) + 600)
    }
    EOF
    

    次の値を置き換えます。

    • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
    • PROJECT_ID: Google Cloud プロジェクト ID
    • AUDIENCES: サービス、ワークロード、またはアプリの想定オーディエンスを識別するわかりやすい文字列(例: "123456-my-app")。

JWT に署名する(REST API)

  1. jq ツールを使用して、JWT を文字列にエンコードし、curl リクエスト ペイロードを作成します。

    cat jwt_in.json | jq -Rsa >request.json
    
  2. リクエスト ペイロードを signJwt REST API メソッドに渡して、トークンに署名します。

    SA="serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com"
    curl -X POST \
       -H "Authorization: Bearer $(gcloud auth print-access-token)" \
       -H "Content-Type: application/json; charset=utf-8" \
       -d @request.json \
       "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$SA:signJwt"
    

    次の値を置き換えます。

    • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
    • PROJECT_ID: Google Cloud プロジェクト ID

    返された signedJwt 値を signedJwt という環境変数に格納します。

JWT に署名する(gcloud CLI)

また、jwt_in.json ファイルを gcloud CLI の sign-jwt メソッドに直接渡すことで、JWT に署名することもできます。

gcloud iam service-accounts sign-jwt jwt_in.json jwt_out \
   --iam-account=SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com

次の値を置き換えます。

  • SERVICE_ACCOUNT_ID: サービス アカウントの ID。
  • PROJECT_ID: Google Cloud プロジェクト ID

署名付き JWT は jwt_out 出力ファイルに返されます。これを signedJwt という環境変数に格納します。

署名付き JWT をインデックス エンドポイントに送信する

同じ VPC ネットワーク内の Compute Engine VM から、次の例に示すように、MatchService gRPC エンドポイントを呼び出し、authorization ヘッダーで signedJwt トークンを渡します。

./grpc_cli call ${DEPLOYED_INDEX_SERVER_IP}:10000 google.cloud.aiplatform.container.v1.MatchService.Match \
   '{deployed_index_id: "${DEPLOYED_INDEX_ID}", float_val: [-0.1,..]}' \
   --metadata "authorization: Bearer $signedJwt"

このコマンドを実行するには、次の環境変数を設定する必要があります。

  • DEPLOYED_INDEX_SERVER_IP は、デプロイしたインデックス サーバーの IP アドレスです。この値を取得する方法については、インデックスをクエリして最近傍を取得するをご覧ください。
  • DEPLOYED_INDEX_ID: デプロイされたインデックスを一意に識別するユーザー指定の文字列。先頭は英字にします。英字、数字、アンダースコアのみ使用できます。形式のガイドラインについては、DeployedIndex.id をご覧ください。

signedJwt は、署名付き JWT を含む環境変数です。

トラブルシューティング

次の表に、一般的な gRPC エラー メッセージを示します。

gRPC エラー メッセージ 理由
インデックス「INDEX_ID」の Authorization ヘッダーが見つかりません gRPC メタデータに認証ヘッダーが含まれていません
JWT の形式が無効です トークンが不正な形式で、正しく解析できません
JWT 認証に失敗しました トークンの有効期限が切れているか、正しいサービス アカウントによって署名されていません
JWT 発行者が、許可された発行者のリストに含まれている必要があります トークン iss は、許可された発行元 auth_config にありません
インデックス「INDEX_ID」の権限チェックが失敗しました トークン aud または sub クレームが auth_config オーディエンスにありません。

次のステップ