JSON Web Token 驗證

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

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

限制

建立及使用 JWT 查詢索引

請按照下列步驟建立索引端點,並使用自簽署的 JWT 查詢該端點。

建立索引

按照「建立索引」中的操作說明建立 Vector Search 索引。

建立私人端點

請按照下列其中一個說明文件頁面的說明建立私人端點:

建立服務帳戶

建立服務帳戶,並授予「服務帳戶符記建立者」身分與存取權管理角色。

  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." \
         --role "roles/iam.serviceAccountTokenCreator" \
         --member "serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID." \
         --project "PROJECT_ID"
      

      替換下列值:

      • SERVICE_ACCOUNT_ID:服務帳戶的 ID。
      • PROJECT_ID:要在其中建立服務帳戶的專案。
    • 下列指令會授予權限,允許使用您 Google 帳戶 (工作站) 中的服務帳戶建立 JWT:

      gcloud iam service-accounts add-iam-policy-binding \
         "SERVICE_ACCOUNT_ID@PROJECT_ID." \
         --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." \
       --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 呼叫查詢索引,並在授權標頭中傳遞權杖。

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.",
            "AUDIENCES")

指令列

建立 JWT 酬載

Vector Search 驗證作業會接受以預先授權的服務帳戶簽署的 JWT,適用於預先定義的對象。將索引部署至私有端點時,呼叫方必須指定服務帳戶和目標對象。使用這些設定部署索引後,傳送至該端點的所有 gRPC API 要求都必須包含授權標頭,其中含有由核發者 (服務帳戶) 簽署的 JWT,且目標對象為提供的目標對象。簽署的 JWT 會在 gRPC 要求的 authorization 標頭中,以不記名權杖的形式傳遞。除了由服務帳戶簽署外,JWT 也必須包含下列憑證附加資訊:

  • iss (允許的簽發者) 聲明應為服務帳戶電子郵件地址,例如:

    "iss": "SERVICE_ACCOUNT_ID@PROJECT_ID."
    
  • 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.",
   "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."
    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."
    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.

替換下列值:

  • SERVICE_ACCOUNT_ID:服務帳戶的 ID。
  • PROJECT_ID:您的 Google Cloud 專案 ID

簽署的 JWT 會在 jwt_out 輸出檔案中傳回。將其儲存在名為 signedJwt 的環境變數中。

將已簽署的 JWT 傳送至索引端點

Python

如要瞭解如何安裝或更新 Python 適用的 Vertex AI SDK,請參閱「安裝 Python 適用的 Vertex AI SDK」。 詳情請參閱 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 目標對象中

後續步驟