איך מפעילים Cloud Functions מאומתים

1. מבוא

סקירה כללית

Cloud Functions הוא פתרון מחשוב קל שמאפשר למפתחים ליצור פונקציות עצמאיות למטרה יחידה, שניתן להפעיל באמצעות HTTPS או להשיב ל-CloudEvents בלי לנהל שרת או סביבת זמן ריצה.

יש שתי גישות עיקריות לשליטה בהפעלות של Cloud Functions: אבטחת הגישה על סמך זהות ואבטחת הגישה באמצעות בקרות גישה מבוססות-רשת. ה-Codelab הזה מתמקד בגישה הראשונה ומנחה אתכם ב-3 תרחישים לגבי אבטחת גישה מבוססת זהות להפעלת פונקציה:

  1. איך משתמשים באסימון הזהות של gcloud כדי להפעיל פונקציה לפיתוח מקומי למטרות בדיקה
  2. התחזות לחשבון שירות במהלך פיתוח ובדיקה מקומיים, לצורך שימוש באותם פרטי כניסה כמו בסביבת הייצור
  3. שימוש בספריות הלקוח של Google לצורך טיפול באימות באמצעות Google Cloud APIs, למשל. כששירות צריך להפעיל פונקציה

מה תלמדו

  • איך להגדיר אימות בפונקציה של Cloud Functions ולוודא שהאימות הוגדר כראוי
  • הפעלת פונקציה מאומתת מסביבת פיתוח מקומית באמצעות מתן האסימון לזהות שלכם ב-gcloud
  • איך יוצרים חשבון שירות ונותנים לו את התפקיד המתאים להפעלת פונקציה
  • איך מתחזים לשירות מסביבת פיתוח מקומית שיש לה את התפקידים המתאימים להפעלת פונקציה

2. הגדרה ודרישות

דרישות מוקדמות

  • אתם מחוברים למסוף Cloud
  • פרסתם בעבר פונקציה של Cloud Functions מדור שני שמופעלת ב-HTTP
  • (אופציונלי) בתרחיש השלישי, Codelab הזה משתמש כדוגמה ב-Node.js וב-npm, אבל אפשר להשתמש בכל סביבת זמן ריצה שנתמכת על ידי ספריות הלקוח של Google Auth.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים שמתאר מהו. אם הוצג לכם מסך ביניים, לוחצים על המשך.

9c92662c6a846a5c.png

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

9f0e51b578fecce5.png

במכונה הווירטואלית הזו נמצאים כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. אם לא את כולן, ניתן לבצע חלק גדול מהעבודה ב-Codelab הזה באמצעות דפדפן.

אחרי ההתחברות ל-Cloud Shell, אתם אמורים לראות שהפרויקט מאומת ושהפרויקט מוגדר לפי מזהה הפרויקט שלכם.

  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהאימות בוצע:
gcloud auth list

פלט הפקודה

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהפקודה ב-gcloud יודעת על הפרויקט שלכם:
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

אם הוא לא משויך, תוכלו להגדיר אותו באמצעות הפקודה הבאה:

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. יצירה ובדיקה של פונקציה מאומתת של Cloud Functions

ה-Codelab הזה פועל לפי אותן הוראות במדריך למתחילים של המסוף ל-Cloud Functions, למעט יוצא מן הכלל: הפונקציה תדרוש אימות.

דרישה לאימות פירושה שלעיקרון שמפעיל את הפונקציה חייב להיות תפקידים ב-Cloud Functions Invoker (ו-Cloud Run Invoker מדור שני), אחרת, הפונקציה תחזיר שגיאה מסוג '403 אסור'. ה-Codelab הזה יסביר איך להקצות את התפקידים המתאימים ב-Invoker לעיקרון.

יצירת הפונקציה המאומתת

כך משתמשים במסוף Cloud:

  1. נכנסים לדף Cloud Functions Overview (סקירה כללית של Cloud Functions) ולוחצים על Create Function (יצירת פונקציה).
  2. באפשרות סביבה, בוחרים באפשרות דור שני
  3. נותנים לפונקציה my-authenticated-function
  4. בשדה 'אימות', משאירים את ברירת המחדל בתור דרישת אימות.

936eee0d5930d12b.png

  1. לוחצים על הבא.
  2. ב-Codelab הזה, אפשר לבחור כל שפה
  3. לאחר מכן לוחצים על Deploy

פריסת הפונקציה אורכת כדקה.

הגדרה של משתני סביבה מקומיים לפקודות פשוטות ב-gcloud

קודם כול צריך ליצור כמה משתני סביבה כדי לשפר את הקריאות של פקודות gcloud שנמצאות בשימוש ב-Codelab הזה.

צריך לציין את האזור בשביל הפונקציה. בדוגמה הזו נעשה שימוש ב-us-central1.

REGION="us-central1"

ואז אפשר לשמור את כתובת ה-URL של הפונקציה כמשתנה סביבה כדי להשתמש בה מאוחר יותר.

PROJECT_ID=$(gcloud config get-value project)
FUNCTION_URL="$(gcloud functions describe my-authenticated-function --gen2 --region us-central1 --format='get(serviceConfig.uri)')"

כדי לוודא שהפונקציה מחייבת אימות על ידי ניסיון להפעיל קריאה אנונימית

כדי לוודא שאתם מקבלים שגיאה צפויה מסוג 403, יש להפעיל את הפונקציה ללא אימות.

מריצים את הפקודה הבאה של curl משורת הפקודה:

curl $FUNCTION_URL

תופיע התוצאה הבאה:

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Your client does not have permission to get URL <code>/</code> from this server.</h2>
<h2></h2>
</body></html>

עכשיו אתם מוכנים לעבור בין 3 תרחישים שבהם אתם יכולים להפעיל את הפונקציה באמצעות אימות.

4. תרחיש 1: שימוש באסימון הזהות של gcloud

בתור מפתחים, חשוב שתהיה לכם דרך לבדוק את הפונקציה שלכם תוך כדי הפיתוח שלה באופן מקומי. בקטע הזה תבצעו בדיקה מהירה כדי לאמת שהפונקציה מאומתת בצורה תקינה באמצעות הזהות שלכם.

כדי לוודא שהאימות בוצע באמצעות gcloud, מריצים את הפקודה הבאה:

gcloud auth list

אמורה להופיע כוכבית לצד הזהות הפעילה, לדוגמה:

Credentialed Accounts
ACTIVE  ACCOUNT

*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

אחרי שתוודאו שאתם משתמשים בזהות הנכונה, תשמרו את כתובת האימייל של החשבון במשתנה סביבה.

ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

במסמכי התיעוד אפשר למצוא מידע נוסף על הגדרת gcloud init ועל התחברות auth של gcloud.

לאחר מכן, מפעילים את הפונקציה ומעבירים אליה את אסימון הזהות.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"

עכשיו אמורה להופיע התוצאה:

Hello World!

פתרון בעיות

אם קיבלתם שגיאה מסוג '403 אסור', צריך לוודא שלזהות שלכם יש תפקיד Cloud Functions Invoker או תפקיד Cloud Run Invoker לפונקציות של דור שני. אפשר להשתמש במסוף IAM כדי לאמת תפקידים שהוקצו לחשבון משתמש.

השימוש באסימון הזהות שלכם הוא דרך מהירה לבדוק את הפונקציה במהלך הפיתוח, אבל מבצע הקריאה החוזרת של הפונקציה המאומתת יצטרך את התפקידים המתאימים; אחרת, המתקשר יקבל שגיאה מסוג '403 אסור'.

כדאי לשמור על העיקרון של הרשאות מינימליות על ידי הגבלת מספר הזהויות וחשבונות השירות שיש להם תפקידים להפעלת הפונקציה.

יצירת חשבון שירות חדש והקצאת התפקידים הנדרשים,

5. תרחיש 2: התחזות לחשבון שירות

בתרחיש הזה, אתם צריכים להתחזות (כלומר להניח שיש לכם את ההרשאות של) חשבון שירות כדי להפעיל פונקציה כשמפתחים ובודקים באופן מקומי. התחזות לחשבון שירות מאפשרת לבדוק את הפונקציה באותם פרטי כניסה כמו בסביבת הייצור.

כך תוכלו לא רק לאמת תפקידים, אלא גם לפעול בהתאם לעיקרון של הרשאות מינימליות – כלומר, אין צורך להקצות את התפקיד Cloud Functions Invoker לזהויות אחרות רק למטרות בדיקה מקומיות.

בשביל ה-Codelab הזה, יוצרים חשבון שירות חדש שיש לו תפקידים רק להפעלת הפונקציה שיצרתם ב-Codelab הזה.

יצירה של חשבון שירות חדש

קודם כול, יוצרים כמה משתני סביבה נוספים שמייצגים את חשבונות השירות שמשמשים את הפקודות של gcloud.

SERVICE_ACCOUNT_NAME="invoke-functions-codelab"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com

בשלב הבא יוצרים את חשבון השירות.

gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
  --display-name="Cloud Function Authentication codelab"

ומקצים את תפקיד ההפעלה של הפונקציה של Cloud Functions בחשבון השירות

gcloud functions add-iam-policy-binding my-authenticated-function \
  --region=us-central1 --gen2 \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/cloudfunctions.invoker'

כדי להפעיל את הפונקציה, אפשר להתחזות לחשבון השירות

לשם כך, תהיה לך התחזות לחשבון השירות החדש שנוצר על ידי קבלת האסימון המזהה שלו.

הוספת התפקידים הנדרשים להתחזות

כדי להתחזות לחשבון שירות, לחשבון המשתמש שלכם צריך להיות התפקיד 'יצירת אסימונים בחשבון שירות' (roles/iam.serviceAccountTokenCreator) כדי ליצור אסימון מזהה לחשבון השירות.

gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS  \
  --member user:$ACCOUNT_EMAIL \
  --role='roles/iam.serviceAccountTokenCreator'

שימוש באסימון המזהה של חשבון השירות

עכשיו אפשר להפעיל את הפונקציה על ידי העברה של האסימון המזהה של חשבון השירות.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)" 

ואז יופיעו הפרטים הבאים:

WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com].
Hello World!

6. תרחיש 3: שימוש בספריות הלקוח של Google

בחלק האחרון של השיעור ב-Codelab, מריצים שירות קטן באופן מקומי כדי ליצור אסימון מזהה לחשבון שירות, ואז מפעילים באופן פרוגרמטי את הפונקציה באמצעות ספריות הלקוח של Google Auth ו-Application Default Credentials (ADC). מידע נוסף על ספריות הלקוח של Google זמין בקטע 'הסבר על ספריות לקוח' במסמכים.

השימוש ב-ADC חשוב במיוחד כשרוצים לכתוב ולבדוק את הפונקציה באופן מקומי (למשל, במחשב נייד, ב-Cloud Shell וכו') במהלך אינטראקציה עם משאבים אחרים של Google Cloud (כמו Cloud Storage , Vision API וכו'). בדוגמה הזו נסביר איך להפעיל פונקציה אחרת שמחייבת אימות. מידע נוסף על ADC ועל פיתוח מקומי זמין בפוסט בבלוג איך לפתח ולבדוק את Cloud Functions באופן מקומי | הבלוג של Google Cloud

הרצת הפקודה ב-gcloud כדי להתחזות לחשבון שירות

שירות ADC מוצא פרטי כניסה באופן אוטומטי על סמך סביבת האפליקציה, ומשתמש בהם כדי לבצע אימות ל-Google Cloud APIs. הדגל -התחזות-service-account מאפשר להתחזות לחשבון שירות על ידי שימוש בזהות שלו לצורך אימות מול Google Cloud APIs.

כדי להתחזות לחשבון שירות, מריצים את הפקודה הבאה:

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

עכשיו מריצים פקודות של gcloud בתור חשבון השירות הזה, במקום הזהות שלכם.

יצירה והפעלה של שירות להפעלת פונקציה מאומתת

לכל סביבת זמן ריצה יש ספריית לקוח של Google Auth שאפשר להתקין. ה-Codelab הזה ידריך אותך איך ליצור ולהפעיל אפליקציית Node.js באופן מקומי.

אלה השלבים שצריך לבצע ב-Node.js:

  1. יצירה של אפליקציית Node.js חדשה
npm init
  1. התקנת ספריית הלקוח של Google Auth
npm install google-auth-library
  1. יצירת קובץ index.js
  2. מאחזרים את כתובת ה-URL של הפונקציה של Cloud Functions, שאותה תוסיפו לקוד בשלב הבא.
echo $FUNCTION_URL
  1. צריך להוסיף את הקוד הבא ל-index.js. חשוב לשנות את המשתנה targetAudience לכתובת ה-URL של הפונקציה של Cloud Functions.

index.js

// Cloud Functions uses your function's url as the `targetAudience` value

const targetAudience = '<YOUR-CLOUD-FUNCTION-URL>';

// For Cloud Functions, endpoint(`url`) and `targetAudience` should be equal

const url = targetAudience;

const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
    console.info(`request ${url} with target audience ${targetAudience}`);

    // this call retrieves the ID token for the impersonated service account
    const client = await auth.getIdTokenClient(targetAudience);

    const res = await client.request({ url });
    console.info(res.data);
}

request().catch(err => {
    console.error(err.message);
    process.exitCode = 1;
});
  1. הפעלת האפליקציה
node index.js

אתם אמורים לראות את ההודעה 'Hello World! '

פתרון בעיות

אם מופיעה שגיאה בהרשאה 'iam.serviceAccounts.getOpenIdToken' נדחתה במשאב (או יכול להיות שהוא לא קיים). יש להמתין כמה דקות עד שהתפקיד 'יצירת אסימונים בחשבון שירות' יופץ.

אם מופיעה השגיאה "לא ניתן לאחזר את האסימון המזהה בסביבה הזו, משתמשים ב-GCE או מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS לקובץ JSON עם פרטי הכניסה של חשבון השירות, ייתכן ששכחתם להריץ את הפקודה".

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

7. מעולה!

מזל טוב, השלמת את Codelab!

מומלץ לעיין במסמכי התיעוד בנושא אבטחת Cloud Functions.

מומלץ גם לקרוא את הפוסט בבלוג על פיתוח מקומי באמצעות Cloud Functions כדי ללמוד איך לפתח ולבדוק פונקציה של Cloud Functions בסביבת הפיתוח המקומית שלכם.

אילו נושאים דיברנו?

  • איך להגדיר אימות בפונקציה של Cloud Functions ולוודא שהאימות הוגדר כראוי
  • הפעלת פונקציה מאומתת מסביבת פיתוח מקומית באמצעות מתן האסימון לזהות שלכם ב-gcloud
  • איך יוצרים חשבון שירות ונותנים לו את התפקיד המתאים להפעלת פונקציה
  • איך מתחזים לשירות מסביבת פיתוח מקומית שיש לה את התפקידים המתאימים להפעלת פונקציה

8. הסרת המשאבים

כדי להימנע מחיובים לא מכוונים (לדוגמה, הפונקציה של Cloud Functions הופעלה בטעות יותר פעמים מההקצאה החודשית של הפונקציה של Cloud Functions בתוכנית ללא תשלום), אפשר למחוק את הפונקציה של Cloud Functions או למחוק את הפרויקט שיצרתם בשלב 2.

כדי להפסיק את ההתחזות לחשבון השירות, תוכלו להתחבר מחדש באמצעות הזהות שלכם:

gcloud auth application-default login

כדי למחוק את הפונקציה של Cloud Functions, נכנסים אל מסוף הפונקציה של Cloud Functions בכתובת https://console.cloud.google.com/functions/. מוודאים שהפרויקט שיצרתם בשלב 2 הוא הפרויקט הנוכחי שנבחר.

בוחרים את הפונקציה המאומתת שלי שפרסתם קודם. לאחר מכן לוחצים על מחיקה.

אם בוחרים למחוק את הפרויקט כולו, נכנסים לכתובת https://console.cloud.google.com/cloud-resource-manager, בוחרים את הפרויקט שיצרתם בשלב 2 ובוחרים באפשרות 'מחיקה'. אם מוחקים את הפרויקט, צריך לבצע שינויים בפרויקטים ב-Cloud SDK. כדי להציג את הרשימה של כל הפרויקטים הזמינים, אפשר להריץ את הפקודה gcloud projects list.