Autenticación con JSON Web Token

La búsqueda vectorial admite endpoints de índice autenticados mediante tokens web JSON (JWTs) autofirmados. Para controlar el acceso al endpoint de índice, se configura para que solo acepte JWTs firmados emitidos por cuentas de servicio de Google específicamente autorizadas. Esto significa que solo los clientes que usen esas cuentas designadas podrán interactuar con el endpoint.

En esta página se describen los pasos necesarios para configurar un endpoint de índice con autenticación de token web JSON (JWT) y ejecutar consultas en él.

Limitaciones

  • La autenticación JWT solo se admite en los endpoints privados con emparejamiento de VPC o Private Service Connect (PSC).
  • La autenticación JWT solo se admite en las APIs RPC del plano de datos (como MatchService) que se invocan mediante gRPC. En los ejemplos de RPC de esta página se usa la herramienta de código abierto grpc_cli para enviar solicitudes gRPC al servidor de índice implementado.
  • Las APIs de administrador para la creación, la implementación y la gestión de índices están protegidas mediante roles de gestión de identidades y accesos predefinidos.

Crear y usar un JWT para consultar un índice

Sigue estos pasos para crear un endpoint de índice y consultarlo con un JWT autofirmado.

Crear un índice

Crea un índice de búsqueda vectorial siguiendo las instrucciones de Crear un índice.

Crear un endpoint privado

Crea un endpoint privado siguiendo las instrucciones de una de las siguientes páginas de documentación:

Crear una cuenta de servicio

Crea una cuenta de servicio y asígnale el rol de IAM Creador de tokens de cuenta de servicio.

  1. Habilita la API de credenciales de cuenta de servicio de gestión de identidades y accesos y crea una cuenta de servicio:

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

    Sustituye los siguientes valores:

    • PROJECT_ID: el proyecto en el que quieres crear la cuenta de servicio.
    • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.

    Consulta más información sobre cómo crear una cuenta de servicio.

  2. Usa uno de los siguientes comandos para conceder el rol de gestión de identidades y accesos iam.serviceAccountTokenCreator a tu cuenta de servicio:

    • El siguiente comando te da permiso para crear JWTs usando la cuenta de servicio de una VM de Compute Engine que tenga la cuenta de servicio asociada:

      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"
      

      Sustituye los siguientes valores:

      • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
      • PROJECT_ID: el proyecto en el que quieres crear la cuenta de servicio.
    • El siguiente comando otorga permiso para crear JWTs mediante la cuenta de servicio de tu cuenta de Google (en tu estación de trabajo):

      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
      

      Sustituye los siguientes valores:

      • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
      • PROJECT_ID: el proyecto en el que quieres crear la cuenta de servicio.
      • EMAIL_ADDRESS: tu dirección de correo.

Desplegar el índice en el endpoint con la configuración de autenticación JWT

  1. Implementa el índice en el endpoint privado, tal como se muestra en el siguiente ejemplo:

    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
    

    Sustituye los siguientes valores:

    • INDEX_ENDPOINT_ID: ID del endpoint de índice.
    • INDEX_ID: ID del índice.
    • DEPLOYED_INDEX_ID: cadena especificada por el usuario para identificar de forma única el índice implementado. Debe empezar por una letra y solo puede contener letras, números o guiones bajos. Consulta las directrices de formato de DeployedIndex.id.
    • DEPLOYED_INDEX_NAME: nombre visible del índice implementado.
    • AUDIENCES: cadena descriptiva que identifica la audiencia esperada de tu servicio, carga de trabajo o aplicación. Por ejemplo, "123456-my-app".
    • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
    • PROJECT_ID: tu Google Cloud ID de proyecto.
    • LOCATION: la región en la que usas Vertex AI.

Consultar el índice con un JWT autofirmado

A grandes rasgos, estos son los pasos que debe seguir:

  1. Crea una carga útil de JWT.
  2. Firma el token con la cuenta de servicio que has creado antes.
  3. Consulta el índice mediante una llamada gRPC y pasa el token en el encabezado de autorización.

Python

Crear y firmar la carga útil del JWT

En este ejemplo se usa el método sign_jwt de la biblioteca de credenciales de la API IAM de Python para obtener un token firmado. Para obtener más información sobre cómo instalar y usar esta biblioteca, consulta la documentación de las bibliotecas de cliente de la API IAM.

   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")

Línea de comandos

Crear la carga útil del JWT

La autenticación de búsqueda vectorial acepta JWTs firmados con una cuenta de servicio preautorizada para una audiencia predefinida. El llamante debe especificar la cuenta de servicio y la audiencia cuando se implementa un índice en un endpoint privado. Una vez que se haya implementado un índice con estos ajustes, todas las solicitudes de la API gRPC a ese endpoint deberán incluir un encabezado de autorización que contenga un JWT firmado por el emisor (una cuenta de servicio) y dirigido a la audiencia proporcionada. El JWT firmado se transfiere como token de portador en el encabezado authorization de la solicitud gRPC. Además de estar firmado por la cuenta de servicio, el JWT debe incluir las siguientes reclamaciones:

  • La reclamación iss (emisor permitido) debe ser la dirección de correo de la cuenta de servicio. Por ejemplo:

    "iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com"
    
  • Las reclamaciones aud (audiencia) y sub (sujeto) deben tener el mismo valor. Se trata de una cadena descriptiva que identifica la audiencia esperada de tu servicio, carga de trabajo o aplicación. Por ejemplo:

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

    Este valor debe coincidir con el argumento --audiences que se ha transferido en el momento de la implementación del índice.

  • La reclamación iat (emitida a las) debe establecerse en el momento en que se emite el token. La reclamación exp (hora de vencimiento) debe configurarse para que venza poco después (aproximadamente una hora). Estos valores se expresan en tiempo de época de Unix. Por ejemplo:

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

En el siguiente ejemplo se muestran estas reclamaciones en una sola carga útil JWT:

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

La carga útil del JWT se firma con la cuenta de servicio especificada en la reclamación iss.

Crear el JWT

  1. Asegúrate de que tú (el llamante) puedas usar el rol roles/iam.serviceAccountTokenCreator en la cuenta de servicio.

  2. Crea un archivo JSON llamado jwt_in.json que contenga el JWT sin procesar:

    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
    

    Sustituye los siguientes valores:

    • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
    • PROJECT_ID: tu Google Cloud ID de proyecto.
    • AUDIENCES: cadena descriptiva que identifica la audiencia esperada de tu servicio, carga de trabajo o aplicación. Por ejemplo, "123456-my-app".

Firmar el JWT (API REST)

  1. Con la herramienta jq, crea la carga útil de la solicitud curl codificando el JWT en una cadena:

    cat jwt_in.json | jq -Rsa >request.json
    
  2. Firma el token transfiriendo la carga útil de la solicitud al método de la API REST signJwt.

    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"
    

    Sustituye los siguientes valores:

    • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
    • PROJECT_ID: tu Google Cloud ID de proyecto.

    Almacena el valor signedJwt devuelto en una variable de entorno llamada signedJwt.

Firmar el JWT (CLI de gcloud)

También puedes firmar el JWT pasando el archivo jwt_in.json directamente al método sign-jwt de la CLI de gcloud.

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

Sustituye los siguientes valores:

  • SERVICE_ACCOUNT_ID: ID de la cuenta de servicio.
  • PROJECT_ID: tu Google Cloud ID de proyecto.

El JWT firmado se devuelve en el archivo de salida jwt_out. Almacénalo en una variable de entorno llamada signedJwt.

Envía el JWT firmado al endpoint de índice

Python

Para saber cómo instalar o actualizar el SDK de Vertex AI para Python, consulta Instalar el SDK de Vertex AI para Python. Para obtener más información, consulta la documentación de referencia de la API Python.

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

Línea de comandos

Desde una VM de Compute Engine en la misma red de VPC, llama al endpoint MatchService gRPC y pasa el token signedJwt en el encabezado authorization, como se muestra en el siguiente ejemplo:

./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"

Para ejecutar este comando, debes definir las siguientes variables de entorno:

  • TARGET_IP es la dirección IP de tu servidor de índice implementado. Para saber cómo obtener este valor, consulta Consultar índices para obtener los elementos más cercanos.
  • DEPLOYED_INDEX_ID: cadena especificada por el usuario para identificar de forma única el índice implementado. Debe empezar por una letra y solo puede contener letras, números o guiones bajos. Consulta las directrices de formato de DeployedIndex.id.

signedJwt es la variable de entorno que contiene tu JWT firmado.

Solución de problemas

En la siguiente tabla se muestran algunos mensajes de error de gRPC habituales.

Mensaje de error de gRPC Motivo
No se ha encontrado el encabezado de autorización del índice "INDEX_ID" Los metadatos de gRPC no contienen un encabezado de autorización
El formato de JWT no es válido El token tiene un formato incorrecto y no se puede analizar correctamente
Error de autenticación JWT El token ha caducado o no está firmado por la cuenta de servicio correcta
El emisor del JWT debe estar en la lista de emisores permitidos El token iss no está en los emisores permitidos de auth_config
Error al comprobar el permiso del índice "INDEX_ID" La reclamación aud o sub del token no está en las audiencias auth_config

Siguientes pasos