JSON Web Token 驗證

向量搜尋支援使用自行簽署的 JSON Web Token (JWT) 驗證索引端點。為控管對索引端點的存取權,系統會設定為僅接受由特定授權 Google 服務帳戶核發的已簽署 JWT。也就是說,只有使用這些指定帳戶的用戶端才能與端點互動。

本頁說明設定索引端點的必要步驟,包括使用 JSON Web Token (JWT) 驗證,以及對索引端點執行查詢。

限制

  • 只有透過 VPC 對等互連Private Service Connect (PSC) 建立的私人端點,才支援 JWT 驗證。
  • JWT 驗證僅適用於使用 gRPC 叫用的資料層 RPC API (例如 MatchService)。本頁面的 RPC 範例使用開放原始碼 grpc_cli 工具,將 gRPC 要求傳送至已部署的索引伺服器。
  • 建立、部署及管理索引的管理 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,前提是該 VM 已附加服務帳戶:

      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:您使用 Agent Platform 的區域。

使用自行簽署的 JWT 查詢索引

大致來說,必要步驟如下:

  1. 建立 JWT 酬載。
  2. 使用先前建立的服務帳戶簽署權杖。
  3. 使用 gRPC 呼叫查詢索引,並在授權標頭中傳遞權杖。

Python

建立並簽署 JWT 酬載

本範例使用 Python IAM API 憑證程式庫的 sign_jwt 方法取得已簽署的權杖。如要進一步瞭解如何安裝及使用這個程式庫,請參閱 IAM API 用戶端程式庫說明文件

   from google.cloud import iam_credentials_v1
   from datetime import datetime, timezone
   import json

   def sign_jwt(issuer: str, audience: str):
      client = iam_credentials_v1.IAMCredentialsClient()
      payload = {
            'aud': audience,
            'sub': audience,
            'iss': issuer,
            'iat': int(datetime.now(timezone.utc).timestamp()),
            'exp': int(datetime.now(timezone.utc).timestamp()) + 600,
      }
      response = client.sign_jwt(name="projects/-/serviceAccounts/" + issuer,
                                 payload=json.dumps(payload))
      return response.signed_jwt

   sign_jwt("SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com",
            "AUDIENCES")

指令列

建立 JWT 酬載

Vector Search 驗證作業會接受以預先授權的服務帳戶簽署的 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 (到期時間) 聲明應設為稍晚的時間 (約一小時後)。這些值以 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 憑證中指定的服務帳戶簽署。

建立 JWT

  1. 確認您 (呼叫者) 可以在服務帳戶中使用 roles/iam.serviceAccountTokenCreator 角色。

  2. 建立名為 jwt_in.json 的 JSON 檔案,其中包含原始 JWT:

    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 傳送至索引端點

Python

如要瞭解如何安裝或更新 Vertex AI SDK for Python,請參閱「安裝 Vertex AI SDK for Python」。 詳情請參閱 Python API 參考文件

def vector_search_match_jwt(
    project: str,
    location: str,
    index_endpoint_name: str,
    deployed_index_id: str,
    queries: List[List[float]],
    num_neighbors: int,
    signed_jwt: str,
) -> List[List[aiplatform.matching_engine.matching_engine_index_endpoint.MatchNeighbor]]:
    """Query the vector search index.

    Args:
        project (str): Required. Project ID
        location (str): Required. The region name
        index_endpoint_name (str): Required. Index endpoint to run the query
        against. The endpoint must be a private endpoint.
        deployed_index_id (str): Required. The ID of the DeployedIndex to run
        the queries against.
        queries (List[List[float]]): Required. A list of queries. Each query is
        a list of floats, representing a single embedding.
        num_neighbors (int): Required. The number of neighbors to return.
        signed_jwt (str): Required. The signed JWT token for the private
        endpoint. The endpoint must be configured to accept tokens from JWT's
        issuer and encoded audience.

    Returns:
        List[List[aiplatform.matching_engine.matching_engine_index_endpoint.MatchNeighbor]] - A list of nearest neighbors for each query.
    """
    # Initialize the Vertex AI client
    aiplatform.init(project=project, location=location)

    # Create the index endpoint instance from an existing endpoint.
    my_index_endpoint = aiplatform.MatchingEngineIndexEndpoint(
        index_endpoint_name=index_endpoint_name
    )

    # Query the index endpoint for matches.
    resp = my_index_endpoint.match(
        deployed_index_id=deployed_index_id,
        queries=queries,
        num_neighbors=num_neighbors,
        signed_jwt=signed_jwt,
    )
    return resp

指令列

從相同虛擬私有雲網路中的 Compute Engine VM,呼叫 MatchService gRPC 端點,並在 authorization 標頭中傳遞 signedJwt 權杖,如下列範例所示:

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

如要執行這項指令,您必須設定下列環境變數:

  • TARGET_IP 是已部署索引伺服器的 IP 位址。如要瞭解如何擷取這個值,請參閱「查詢索引以取得最鄰近的項目」。
  • DEPLOYED_INDEX_ID:使用者指定的字串,用來識別已部署的索引。開頭須為英文字母,且只能由英文字母、數字或底線組成。 如需格式規範,請參閱 DeployedIndex.id

signedJwt 是包含已簽署 JWT 的環境變數。

疑難排解

下表列出一些常見的 gRPC 錯誤訊息。

gRPC 錯誤訊息 原因
找不到索引「INDEX_ID」的授權標頭 gRPC 中繼資料不含授權標頭
JWT 格式無效 權杖格式錯誤,無法正確剖析
JWT 驗證失敗 權杖已過期或未由正確的服務帳戶簽署
JWT 核發者應位於允許的核發者清單中 權杖 iss 不在auth_config允許的簽發者中
索引「INDEX_ID」的權限檢查失敗 權杖 audsub 聲明不在 auth_config 目標對象中

後續步驟