אימות בין שירותים
בנוסף לאימות בקשות של משתמשי קצה, יכול להיות שתרצו לאמת שירותים (משתמשים לא אנושיים) ששולחים בקשות ל-API שלכם. בדף הזה מוסבר איך להשתמש בחשבונות שירות כדי לספק אימות לבני אדם או לשירותים.
סקירה כללית
כדי לזהות שירות ששולח בקשות ל-API שלכם, אתם משתמשים בחשבון שירות. שירות הקריאה משתמש במפתח הפרטי של חשבון השירות כדי לחתום על אסימון אינטרנט מאובטח מסוג JSON (JWT) ושולח את ה-JWT החתום בבקשה ל-API שלכם.
כדי להטמיע אימות של חשבון שירות ב-API ובשירות שקורא ל-API:
- יוצרים חשבון שירות ומפתח לשימוש של השירות שקורא ל-API.
- מוסיפים תמיכה באימות בהגדרות ה-API של שירות API Gateway.
מוסיפים קוד לשירות השיחות ש:
- יוצרת JWT וחותמת עליו באמצעות המפתח הפרטי של חשבון השירות.
- שליחת ה-JWT החתום בבקשה ל-API.
API Gateway מאמת שההצהרות ב-JWT תואמות להגדרה בקובץ ההגדרות של ה-API לפני שהוא מעביר את הבקשה ל-API. API Gateway לא בודק את ההרשאות של Cloud Identity שנתתם בחשבון השירות.
דרישות מוקדמות
במאמר הזה אנחנו יוצאים מנקודת הנחה שכבר:
יצירת חשבון שירות עם מפתח
אתם צריכים חשבון שירות עם קובץ מפתח פרטי ששירות הקריאה משתמש בו כדי לחתום על ה-JWT. אם יש לכם יותר משירות אחד ששולח בקשות ל-API, אתם יכולים ליצור חשבון שירות אחד שייצג את כל השירותים ששולחים את הבקשות. אם אתם צריכים להבדיל בין השירותים – למשל, אם יש להם הרשאות שונות – אתם יכולים ליצור חשבון שירות ומפתח לכל שירות שקורא ל-API.
בקטע הזה מוסבר איך להשתמש במסוף Google Cloud ובכלי שורת הפקודה gcloud כדי ליצור את חשבון השירות ואת קובץ המפתח הפרטי, ולהקצות לחשבון השירות את התפקיד יוצר האסימונים של חשבון השירות. מידע על שימוש ב-API כדי לבצע את המשימה הזו זמין במאמר יצירה וניהול של חשבונות שירות.
כדי ליצור חשבון שירות עם מפתח:
מסוף Google Cloud
יוצרים חשבון שירות:
במסוף Google Cloud , נכנסים אל יצירת חשבון שירות.
בוחרים פרויקט.
כותבים שם בשדה Service account name. השדה Service account ID ימולא במסוףGoogle Cloud בהתאם לשם הזה.
אופציונלי: בשדה תיאור חשבון השירות, מזינים תיאור.
לוחצים על יצירה.
לוחצים על השדה בחירת תפקיד.
בקטע All roles (כל התפקידים), בוחרים באפשרות Service Accounts (חשבונות שירות) > Service Account Token Creator (יצירת אסימונים בחשבון שירות).
לוחצים על Continue.
לוחצים על Done כדי לסיים ליצור את חשבון השירות.
לא לסגור את חלון הדפדפן. תשתמשו בו גם בשלב הבא.
יוצרים מַפְתח לחשבון השירות:
- במסוף Google Cloud , לוחצים על כתובת האימייל של חשבון השירות שיצרתם.
- לוחצים על Keys.
- לוחצים על Add key ואז על Create new key.
- לוחצים על Create. למחשב שלכם תתבצע הורדה של קובץ JSON עם המפתח.
- לוחצים על Close.
gcloud
אפשר להריץ את הפקודות הבאות באמצעות Google Cloud CLI במחשב המקומי או ב-Cloud Shell.
הגדרת חשבון ברירת המחדל ל-
gcloud. אם יש לכם יותר מחשבון אחד, חשוב לבחור את החשבון שמשויך ל Google Cloud פרויקט שבו אתם רוצים להשתמש.gcloud auth login
הצגת מזהי הפרויקטים של Google Cloud הפרויקטים שלכם.
gcloud projects list
מגדירים את פרויקט ברירת המחדל. מחליפים את
PROJECT_IDבמזהה הפרויקט שרוצים להשתמש בו. Google Cloudgcloud config set project PROJECT_ID
יוצרים חשבון שירות. מחליפים את
SA_NAMEואתSA_DISPLAY_NAMEבשם ובשם לתצוגה שרוצים להשתמש בהם.gcloud iam service-accounts create SA_NAME \ --display-name "SA_DISPLAY_NAME"
מציגים את כתובת האימייל של חשבון השירות שיצרתם.
gcloud iam service-accounts list
מוסיפים את התפקיד יצירת אסימונים בחשבון שירות. מחליפים את
SA_EMAIL_ADDRESSבכתובת האימייל של חשבון השירות.gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:SA_EMAIL_ADDRESS \ --role roles/iam.serviceAccountTokenCreator
יוצרים קובץ מפתח של חשבון שירות בספריית העבודה הנוכחית. מחליפים את
FILE_NAMEבשם שרוצים לתת לקובץ המפתח. כברירת מחדל, הפקודהgcloudיוצרת קובץ JSON.gcloud iam service-accounts keys create FILE_NAME.json \ --iam-account SA_EMAIL_ADDRESS
מידע נוסף על הפקודות הקודמות מופיע בgcloudחומר העזר.
מידע על שמירה על המפתח הפרטי מופיע במאמר שיטות מומלצות לניהול פרטי כניסה.
הגדרת ה-API כך שיתמוך באימות
כשיוצרים הגדרת API לשער, מציינים חשבון שירות שהשער משתמש בו כדי ליצור אינטראקציה עם שירותים אחרים. כדי להפעיל אימות של חשבון שירות בשירותים שמבצעים קריאות לשער, צריך לשנות את אובייקטי האבטחה בהגדרות ה-API. השינויים יהיו שונים בהתאם לגרסה של מפרט OpenAPI שבה נעשה שימוש.
כדי להגדיר את API Gateway כך שיאמת את ההצהרות באסימון ה-JWT החתום שבו משתמשים שירותים ששולחים קריאות:
OpenAPI 2.0
- מוסיפים את חשבון השירות כגורם מנפיק בהגדרת ה-API:
securityDefinitions: DEFINITION_NAME: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "SA_EMAIL_ADDRESS" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS"
- מחליפים את
DEFINITION_NAMEבמחרוזת שמזהה את הגדרת האבטחה הזו. אפשר להחליף אותו בשם של חשבון השירות או בשם שמזהה את השירות שמבצע את הקריאה. - מחליפים את
SA_EMAIL_ADDRESSבכתובת האימייל של חשבון השירות. - אפשר להגדיר כמה הגדרות אבטחה בהגדרת ה-API, אבל לכל הגדרה צריך להיות
x-google-issuerשונה. אם יצרתם חשבונות שירות נפרדים לכל שירות שיחות, תוכלו ליצור הגדרת אבטחה לכל חשבון שירות, למשל:securityDefinitions: service-1: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-1@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com" service-2: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-2@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
- מחליפים את
- אפשר גם להוסיף
x-google-audiencesלקטעsecurityDefinitions. אם לא מוסיפים אתx-google-audiences, API Gateway דורש שההצהרה"aud"(קהל) באסימון ה-JWT תהיה בפורמטhttps://SERVICE_NAME, כאשר SERVICE_NAME הוא השם של שירות API Gateway שהגדרתם בשדהhostבמסמך OpenAPI. - מוסיפים קטע
securityברמה העליונה של הקובץ (לא מוזח או מקונן) כדי להחיל אותו על ה-API כולו, או ברמת השיטה כדי להחיל אותו על שיטה ספציפית. אם משתמשים בקטעיsecurityברמת ה-API וברמת השיטה, ההגדרות ברמת השיטה מבטלות את ההגדרות ברמת ה-API.security: - DEFINITION_NAME: []
- מחליפים את
DEFINITION_NAMEבשם שבו השתמשתם בקטעsecurityDefinitions. - אם יש יותר מהגדרה אחת בקטע
securityDefinitions, מוסיפים אותן בקטעsecurity. לדוגמה:security: - service-1: [] - service-2: []
- מחליפים את
- מבצעים פריסה של הגדרת ה-API המעודכנת. לפני ש-API Gateway מעביר בקשה ל-API שלכם, הוא בודק את הדברים הבאים:
- החתימה של ה-JWT באמצעות המפתח הציבורי, שנמצא ב-URI שצוין בשדה
x-google-jwks_uriבהגדרת ה-API. - התביעה
"iss"(המנפיק) ב-JWT תואמת לערך שצוין בשדהx-google-issuer. - ההצהרה
"aud"(קהל) ב-JWT מכילה את שם שירות ה-API Gateway או תואמת לאחד מהערכים שציינתם בשדהx-google-audiences. - שהתוקף של הטוקן לא פג באמצעות הטענה
"exp"(זמן התפוגה).
- החתימה של ה-JWT באמצעות המפתח הציבורי, שנמצא ב-URI שצוין בשדה
OpenAPI 3.x
- מוסיפים את חשבון השירות כגורם מנפיק בהגדרת ה-API:
components: securitySchemes: SCHEME_NAME: type: oauth2 flows: implicit: authorizationUrl: "" scopes: {} x-google-auth: issuer: SA_EMAIL_ADDRESS jwksUri: https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS security: - SCHEME_NAME: []
- מחליפים את
SCHEME_NAMEבמחרוזת שמזהה את תוכנית האבטחה הזו. אפשר להחליף אותו בשם של חשבון השירות או בשם שמזהה את השירות שמבצע את הקריאה. - מחליפים את
SA_EMAIL_ADDRESSבכתובת האימייל של חשבון השירות. - אפשר להגדיר כמה תוכניות אבטחה בהגדרות ה-API, אבל לכל הגדרה צריך להיות
issuerשונה. אם יצרתם חשבונות שירות נפרדים לכל שירות שיחות, תוכלו ליצור הגדרת אבטחה לכל חשבון שירות, למשל:components: securitySchemes: service-1: type: oauth2 flows: implicit: authorizationUrl: "" scopes: {} x-google-auth: issuer: "service-1@example-project-12345.iam.gserviceaccount.com" jwksUri: https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com jwtLocations: - header: Authorization valuePrefix: "Bearer " service-2: type: oauth2 flows: implicit: authorizationUrl: "" scopes: {} x-google-auth: issuer: "service-2@example-project-12345.iam.gserviceaccount.com" jwksUri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
- מחליפים את
- אפשר גם להוסיף
audiencesלקטעsecuritySchemes. אם לא מוסיפים אתaudiences, API Gateway דורש שההצהרה"aud"(קהל) באסימון ה-JWT תהיה בפורמטhttps://SERVICE_NAME, כאשר SERVICE_NAME הוא השם של שירות API Gateway שהגדרתם בשדהservers.urlבמסמך OpenAPI. - מוסיפים קטע
securityברמה העליונה של הקובץ (לא מוזח או מקונן) כדי להחיל אותו על ה-API כולו, או ברמת השיטה כדי להחיל אותו על שיטה ספציפית. אם משתמשים בקטעיsecurityברמת ה-API וברמת השיטה, ההגדרות ברמת השיטה מבטלות את ההגדרות ברמת ה-API.security: - SCHEME_NAME: []
- מחליפים את SCHEME_NAME בשם שבו השתמשתם בקטע
securitySchemes. - אם יש יותר מהגדרה אחת בקטע
securitySchemes, מוסיפים אותן בקטעsecurity. לדוגמה:security: - service-1: [] - service-2: []
- מחליפים את SCHEME_NAME בשם שבו השתמשתם בקטע
- פורסים את הגדרת ה-API המעודכנת. לפני ש-API Gateway מעביר בקשה ל-API שלכם, הוא בודק את הדברים הבאים:
- החתימה של ה-JWT באמצעות המפתח הציבורי, שנמצא ב-URI שצוין בשדה
jwksUriבהגדרת ה-API. - התביעה
"iss"(המנפיק) ב-JWT תואמת לערך שצוין בשדהissuer. - ההצהרה
"aud"(קהל) ב-JWT מכילה את שם שירות ה-API Gateway או תואמת לאחד מהערכים שציינתם בשדהaudiences. - שהתוקף של הטוקן לא פג באמצעות הטענה
"exp"(זמן התפוגה).
- החתימה של ה-JWT באמצעות המפתח הציבורי, שנמצא ב-URI שצוין בשדה
שליחת בקשה מאומתת ל-API של API Gateway
כדי לשלוח בקשה מאומתת, שירות הקורא שולח JWT שחתום על ידי חשבון השירות שציינתם בהגדרת ה-API. שירות השיחות צריך:
- יוצרים JWT וחותמים עליו באמצעות המפתח הפרטי של חשבון השירות.
- שולחים את ה-JWT החתום בבקשה ל-API.
בדוגמת הקוד הבאה מוצג התהליך הזה עבור שפות נבחרות. כדי לשלוח בקשה מאומתת בשפות אחרות, אפשר לעיין בjwt.io כדי לראות רשימה של ספריות נתמכות.
-
בשירות הקורא, מוסיפים את הפונקציה הבאה ומעבירים לה את הפרמטרים הבאים:
Java -
saKeyfile: הנתיב המלא לקובץ המפתח הפרטי של חשבון השירות. -
saEmail: כתובת האימייל של חשבון השירות. -
audience: אם הוספתם את השדהx-google-audiencesלהגדרת ה-API, צריך להגדיר אתaudienceלאחד מהערכים שציינתם עבורx-google-audiences. אחרת, מגדירים אתaudienceל-https://SERVICE_NAME, כאשרSERVICE_NAMEהוא שם השירות של API Gateway. -
expiryLength: זמן התפוגה של JWT, בשניות.
Python -
sa_keyfile: הנתיב המלא לקובץ המפתח הפרטי של חשבון השירות. -
sa_email: כתובת האימייל של חשבון השירות. -
audience: אם הוספתם את השדהx-google-audiencesלהגדרת ה-API, צריך להגדיר אתaudienceלאחד מהערכים שציינתם עבורx-google-audiences. אחרת, מגדירים אתaudienceל-https://SERVICE_NAME, כאשרSERVICE_NAMEהוא שם השירות של API Gateway. -
expiry_length: זמן התפוגה של JWT, בשניות.
Go -
saKeyfile: הנתיב המלא לקובץ המפתח הפרטי של חשבון השירות. -
saEmail: כתובת האימייל של חשבון השירות. -
audience: אם הוספתם את השדהx-google-audiencesלהגדרת ה-API, צריך להגדיר אתaudienceלאחד מהערכים שציינתם עבורx-google-audiences. אחרת, מגדירים אתaudienceל-https://SERVICE_NAME, כאשרSERVICE_NAMEהוא שם השירות של API Gateway. -
expiryLength: זמן התפוגה של JWT, בשניות.
הפונקציה יוצרת JWT, חותמת עליו באמצעות קובץ המפתח הפרטי ומחזירה את ה-JWT החתום.
Java Python Go -
-
בשירות שמבצע את הקריאה, מוסיפים את הפונקציה הבאה כדי לשלוח את ה-JWT החתום בכותרת
Authorization: Bearerבבקשה ל-API:Java Python Go
כששולחים בקשה באמצעות JWT, מטעמי אבטחה מומלץ להוסיף את אסימון האימות לכותרת Authorization: Bearer. לדוגמה:
curl --request POST \ --header "Authorization: Bearer TOKEN" \ "GATEWAY_URL/hello"
כאן, צריך להחליף את GATEWAY_URL ואת TOKEN בכתובת ה-URL של השער ובאסימון האימות שפרסתם, בהתאמה.
קבלת תוצאות מאומתות ב-API
בדרך כלל, API Gateway מעביר את כל הכותרות שהוא מקבל. עם זאת, הוא מחליף את הכותרת המקורית Authorization כשכתובת ה-backend מצוינת על ידי x-google-backend בהגדרת ה-API.
API Gateway ישלח את תוצאת האימות ב-X-Apigateway-Api-Userinfo אל ה-API של הבק-אנד. מומלץ להשתמש בכותרת הזו במקום בכותרת המקורית Authorization. הכותרת הזו היא base64url מקודדת ומכילה את המטען הייעודי של ה-JWT.