התכונה 'חיפוש וקטורי' תומכת בנקודות קצה מאומתות של אינדקס באמצעות אסימוני JWT (JSON Web Tokens) בחתימה עצמית. כדי לשלוט בגישה לנקודת הקצה של האינדקס, היא מוגדרת לקבל רק אסימוני JWT חתומים שהונפקו על ידי חשבונות שירות ספציפיים של Google עם הרשאה. המשמעות היא שרק לקוחות שמשתמשים בחשבונות המיועדים האלה יכולים ליצור אינטראקציה עם נקודת הקצה.
בדף הזה מפורטים השלבים הנדרשים להגדרת נקודת קצה של אינדקס עם אימות באמצעות JSON Web Token (JWT) ולהרצת שאילתות מול נקודת הקצה הזו.
מגבלות
- אימות JWT נתמך רק בנקודות קצה פרטיות עם קישור בין רשתות VPC שכנות (peering) או Private Service Connect (PSC).
- אימות JWT נתמך רק בממשקי API של RPC במישור הנתונים (כמו MatchService) שמופעלים באמצעות gRPC. בדוגמאות ל-RPC בדף הזה נעשה שימוש בכלי
grpc_cliבקוד פתוח כדי לשלוח בקשות gRPC לשרת האינדקס שפרסנו. - ממשקי ה-API לאדמינים ליצירה, לפריסה ולניהול של אינדקסים מאובטחים באמצעות תפקידי IAM מוגדרים מראש.
יצירה של JWT ושימוש בו כדי לשלוח שאילתה לאינדקס
כדי ליצור נקודת קצה של אינדקס ולשאול אותה באמצעות JWT בחתימה עצמית, מבצעים את השלבים הבאים.
יצירת אינדקס
יוצרים אינדקס חיפוש וקטורי לפי ההוראות במאמר יצירת אינדקס.
יצירת נקודת קצה פרטית
כדי ליצור נקודת קצה פרטית, פועלים לפי ההוראות באחד מדפי התיעוד הבאים:
יצירה של חשבון שירות
יוצרים חשבון שירות ומקצים לו את תפקיד ה-IAM יצירת אסימונים בחשבון שירות.
מפעילים את 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: המזהה של חשבון השירות.
משתמשים באחת מהפקודות הבאות כדי להקצות את התפקיד
iam.serviceAccountTokenCreatorב-IAM לחשבון השירות:הפקודה הבאה מאפשרת ליצור אסימוני JWT באמצעות חשבון השירות ממכונה וירטואלית (VM) של Compute Engine שחשבון השירות מצורף אליה:
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: המזהה של חשבון השירות.
- PROJECT_ID: הפרויקט שבו רוצים ליצור את חשבון השירות.
הפקודה הבאה מעניקה הרשאה ליצור אסימוני JWT באמצעות חשבון השירות מחשבון Google שלכם (בתחנת העבודה):
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: המזהה של חשבון השירות.
- PROJECT_ID: הפרויקט שבו רוצים ליצור את חשבון השירות.
- EMAIL_ADDRESS: כתובת האימייל שלכם.
פריסת האינדקס לנקודת הקצה עם הגדרת אימות JWT
פורסים את האינדקס לנקודת הקצה הפרטית כמו בדוגמה הבאה:
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: המזהה של נקודת הקצה של האינדקס.
- INDEX_ID: מזהה האינדקס.
- DEPLOYED_INDEX_ID: מחרוזת שצוינה על ידי המשתמש כדי לזהות באופן ייחודי את האינדקס שנפרס. הוא צריך להתחיל באות ולהכיל רק אותיות, מספרים או קווים תחתונים. הנחיות לגבי הפורמט מופיעות במאמר DeployedIndex.id.
- DEPLOYED_INDEX_NAME: השם המוצג של האינדקס שנפרס.
- AUDIENCES: מחרוזת תיאורית שמזהה את קהל היעד הצפוי של השירות, עומס העבודה או האפליקציה, לדוגמה,
"123456-my-app". - SERVICE_ACCOUNT_ID: המזהה של חשבון השירות.
- PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
- LOCATION: האזור שבו משתמשים ב-Agent Platform.
שליחת שאילתה לאינדקס באמצעות JWT בחתימה עצמית
באופן כללי, השלבים הנדרשים הם:
- יוצרים מטען ייעודי (payload) של JWT.
- חותמים על האסימון באמצעות חשבון השירות שנוצר קודם.
- שולחים שאילתה לאינדקס באמצעות קריאת gRPC, ומעבירים את הטוקן בכותרת ההרשאה.
Python
יצירה וחתימה של מטען ה-JWT
בדוגמה הזו נעשה שימוש ב-method sign_jwt של ספריית פרטי הכניסה של IAM API ב-Python כדי לקבל אסימון חתום. מידע נוסף על התקנה ושימוש בספרייה הזו זמין במסמכי התיעוד של ספריות הלקוח של 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")
שורת פקודה
יצירת מטען ייעודי (payload) של JWT
אימות של חיפוש וקטורי מקבל אסימוני JWT שחתומים על ידי חשבון שירות שאושר מראש, עבור קהל מוגדר מראש. כשפורסים אינדקס לנקודת קצה פרטית, מבצע הקריאה צריך לציין את חשבון השירות ואת הקהל.
אחרי שמפעילים אינדקס עם ההגדרות האלה, כל בקשות ה-API של gRPC לנקודת הקצה הזו צריכות לכלול כותרת הרשאה שמכילה JWT שנחתם על ידי המנפיק (חשבון שירות) ומיועד לקהל שצוין. ה-JWT החתום מועבר כטוקן bearer בכותרת authorization של בקשת gRPC. בנוסף לחתימה של חשבון השירות, ה-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 epoch, לדוגמה:"iat": 1698966927, // unix time since epoch eg via date +%s "exp": 1698967527 // iat + a few mins (eg 600 seconds)
בדוגמה הבאה מוצגות ההצהרות האלה במטען ייעודי (payload) יחיד של JWT:
{
"iss": "SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com",
"aud": "123456-my-app",
"sub": "123456-my-app",
"iat": 1698956084,
"exp": 1698960084
}
המטען הייעודי (payload) של ה-JWT חתום באמצעות חשבון השירות שצוין בטענה iss.
יצירת ה-JWT
מוודאים שיש לכם (מבצע הקריאה) את התפקיד
roles/iam.serviceAccountTokenCreatorבחשבון השירות.יוצרים קובץ JSON בשם
jwt_in.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: המזהה של חשבון השירות.
- PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
- AUDIENCES: מחרוזת תיאורית שמזהה את קהל היעד הצפוי של השירות, עומס העבודה או האפליקציה, לדוגמה,
"123456-my-app".
חתימה על ה-JWT (API בארכיטקטורת REST)
בעזרת
jq, יוצרים את ה-payload של הבקשהcurlעל ידי קידוד ה-JWT למחרוזת:cat jwt_in.json | jq -Rsa >request.jsonחותמים על האסימון על ידי העברת מטען הייעודי (payload) של הבקשה אל ה-method signJwt ב-API בארכיטקטורת REST.
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: המזהה של חשבון השירות.
- PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
מאחסנים את הערך
signedJwtשמוחזר במשתנה סביבה שנקראsignedJwt.
חתימה על ה-JWT (CLI של gcloud)
לחלופין, אפשר לחתום על ה-JWT על ידי העברת הקובץ jwt_in.json ישירות לשיטה sign-jwt של ה-CLI של gcloud.
gcloud iam service-accounts sign-jwt jwt_in.json jwt_out \
--iam-account=SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com
מחליפים את הערכים הבאים:
- SERVICE_ACCOUNT_ID: המזהה של חשבון השירות.
- PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
ה-JWT החתום מוחזר בקובץ הפלט jwt_out. מאחסנים אותו במשתנה סביבה שנקרא signedJwt.
שליחת ה-JWT החתום לנקודת הקצה של האינדקס
Python
במאמר התקנת Vertex AI SDK ל-Python מוסבר איך להתקין או לעדכן את Vertex AI SDK ל-Python. מידע נוסף מופיע ב מאמרי העזרה של Python API.
שורת פקודה
ממכונה וירטואלית ב-Compute Engine באותה רשת VPC, קוראים לנקודת הקצה MatchService
gRPC, ומעבירים את אסימון signedJwt בכותרת authorization, כמו בדוגמה הבאה:
./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' | האסימון aud או הטענה sub לא נמצאים בקהלים auth_config |
המאמרים הבאים
- מידע נוסף על JWT ועל מבנה טענות האסימון זמין ב-RFC 7519.
- מידע נוסף על יצירת JSON Web Token (JWT) בחתימה עצמית
- איך מעדכנים ובונים מחדש את האינדקס
- איך עוקבים אחרי אינדקס