Vector Search supports authenticated index endpoints using self-signed JSON Web Tokens (JWTs). To control access to the index endpoint, it's configured to accept only signed JWTs issued by specifically authorized Google service accounts. This means only clients using those designated accounts can interact with the endpoint.
This page outlines the required steps for setting up an index endpoint with JSON Web Token (JWT) authentication and running queries against it.
Limitations
- JWT authentication is supported only for private endpoints with VPC peering or Private Service Connect (PSC).
- JWT authentication is supported only for data plane RPC APIs (such as
MatchService) that are invoked by using gRPC. The RPC examples in this
page use the open source
grpc_cli
tool to send gRPC requests to the deployed index server. - Admin APIs for creation, deployment, and management of indexes are secured by using predefined IAM roles.
Creating and using a JWT to query an index
Follow these steps to create an index endpoint and query it with a self-signed JWT.
Create an index
Create a Vector Search index by following the instructions in Create an index.
Create a private endpoint
Create a private endpoint by following the instructions in one of the following documentation pages:
Create a service account
Create a service account and grant it the Service Account Token Creator IAM role.
Enable the IAM Service Account Credentials API and create a service account:
gcloud services enable iamcredentials.googleapis.com --project="PROJECT_ID" gcloud iam service-accounts create SERVICE_ACCOUNT_ID --project="PROJECT_ID"
Replace the following values:
- PROJECT_ID: The project to create your service account in.
- SERVICE_ACCOUNT_ID: The ID for the service account.
Learn more about creating a service account.
Use one of the following commands to grant the
iam.serviceAccountTokenCreator
IAM role to your service account:The following command gives you permission to create JWTs by using the service account from a Compute Engine VM that has the service account attached to it:
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"
Replace the following values:
- SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: The project to create your service account in.
The following command grants permission to create JWTs by using the service account from your own Google Account (on your workstation):
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
Replace the following values:
- SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: The project to create your service account in.
- EMAIL_ADDRESS: Your email address.
Deploy the index to the endpoint with JWT auth config
Deploy the index to the private endpoint as shown in the following example:
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
Replace the following values:
- INDEX_ENDPOINT_ID: The ID of the index endpoint.
- INDEX_ID: The ID of the index.
- DEPLOYED_INDEX_ID: A user specified string to uniquely identify the deployed index. It must start with a letter and contain only letters, numbers or underscores. See DeployedIndex.id for format guidelines.
- DEPLOYED_INDEX_NAME: Display name of the deployed index.
- AUDIENCES: A descriptive string that identifies the expected
audience for your service, workload or app, for example,
"123456-my-app"
. - SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: Your Google Cloud project ID.
- LOCATION: The region where you are using Vertex AI.
Query the index with a self-signed JWT
At a high level, the required steps are as follows:
- Create a JWT payload.
- Sign the token by using the service account created earlier.
- Query the index by using a gRPC call, passing the token in the authorization header.
Python
Create and Sign the JWT payload
This example uses the Python IAM API Credentials library's sign_jwt
method
to obtain a signed token. To learn more about how to install and use this
library, see the IAM API Client Libraries documentation.
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")
Command-line
Create the JWT payload
Vector Search authentication accepts JWTs that are signed with a
pre-authorized service account, for a predefined audience. The service account
and audience must be specified by the caller when an index is deployed to a
private endpoint.
Once an index is deployed with these settings, all
gRPC API requests to that endpoint are required to include an
authorization header containing a JWT that's signed by the issuer
(a service account) and targeted at the
provided audience. The signed JWT is passed as a bearer token in the
authorization
header of the gRPC request. In addition to being signed by
the service account, the JWT must include the following claims:
The
iss
(allowed issuer) claim should be the service account email address, for example:"iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com"
The
aud
(audience) andsub
(subject) claims should both be set to the same value. This is a descriptive string that identifies the expected audience for your service, workload or app, for example:"aud": "123456-my-app", "sub": "123456-my-app"
This value must match the
--audiences
argument that was passed at index deployment time.The
iat
(issued at) claim should be set to the time the token is issued. Theexp
(expiration time) claim should be set to a short time later (about an hour). These values are expressed in Unix epoch time, for example:"iat": 1698966927, // unix time since epoch eg via date +%s "exp": 1698967527 // iat + a few mins (eg 600 seconds)
The following example shows these claims in a single JWT payload:
{
"iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com",
"aud": "123456-my-app",
"sub": "123456-my-app",
"iat": 1698956084,
"exp": 1698960084
}
The JWT payload is signed by using the service account specified in the
iss
claim.
Create the JWT
Make sure that you (the caller) can use the
roles/iam.serviceAccountTokenCreator
role on the service account.Create a JSON file named
jwt_in.json
that contains the raw 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
Replace the following values:
- SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: Your Google Cloud project ID.
- AUDIENCES: A descriptive string that identifies the expected
audience for your service, workload or app, for example,
"123456-my-app"
.
Sign the JWT (REST API)
Using the
jq
tool, create thecurl
request payload by encoding the JWT into a string:cat jwt_in.json | jq -Rsa >request.json
Sign the token by passing the request payload to the signJwt REST API method.
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"
Replace the following values:
- SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: Your Google Cloud project ID.
Store the returned
signedJwt
value into an environment variable calledsignedJwt
.
Sign the JWT (gcloud CLI)
Alternatively, you can sign the JWT by passing the jwt_in.json
file directly
to the gcloud CLI
sign-jwt
method.
gcloud iam service-accounts sign-jwt jwt_in.json jwt_out \
--iam-account=SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com
Replace the following values:
- SERVICE_ACCOUNT_ID: The ID for the service account.
- PROJECT_ID: Your Google Cloud project ID.
The signed JWT is returned in the jwt_out
output file. Store it into an
environment variable called signedJwt
.
Send the signed JWT to the index endpoint
Python
To learn how to install or update the Vertex AI SDK for Python, see Install the Vertex AI SDK for Python. For more information, see the Python API reference documentation.
Command-line
From a Compute Engine VM in the same VPC network, call the MatchService
gRPC
endpoint, passing the signedJwt
token in the authorization
header,
as shown in the following example:
./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"
To run this command, you'll need the following environment variables to be set:
- TARGET_IP is the IP address for your deployed index server. To learn how to retrieve this value, see Query indexes to get nearest neighbors.
- DEPLOYED_INDEX_ID: A user specified string to uniquely identify the deployed index. It must start with a letter and contain only letters, numbers or underscores. See DeployedIndex.id for format guidelines.
signedJwt
is the environment variable containing your signed JWT.
Troubleshooting
The following table lists some common gRPC
error messages.
gRPC Error Message | Reason |
---|---|
Authorization header not found for index 'INDEX_ID' | The gRPC metadata doesn't contain an authorization header |
JWT is invalid format | The token is malformed and can't be parsed correctly |
JWT authentication failed | The token is expired or isn't signed by the correct service account |
JWT issuer should be in the allowed issuers list | The token iss isn't in auth_config allowed issuers |
Permission check fail for index 'INDEX_ID' | The token aud or sub claim isn't in auth_config audiences |
What's next
- To learn more about JWT and token claim structure, see RFC 7519.
- Learn more about how to Create a self-signed JSON Web Token (JWT)
- Learn how to Update and rebuild your index
- Learn how to Monitor an index