ניהול ואבטחה של מפתחות API

1. מבוא

בעבר, מפתחות Google API שימשו לגישה ל-Google APIs כששיטות אחרות לא היו זמינות או נחשבו ללא נוחות. תרחישי השימוש הפופולריים היו גישה ל-Google Maps API ולממשקי Google API שנחשפים על ידי Firebase. עם ההשקה של מודלים של AI, סוכני AI כמו Gemini, ו-frameworks לפיתוח סוכנים כמו ערכה לפיתוח סוכנים (ADK) ו-AI Studio, מפתחות API הפכו לשיטה העיקרית לגישה למודלים של שפה גדולה (LLM) של Google.

מפתחות API מספקים רמת הגנה נמוכה. למרות ש-Google Cloud מספקת כמה שיטות למניעת שימוש לרעה במפתחות, החזקה של מפתח API פעיל מאפשרת גישה לממשקי Google API ללא אימות או הרשאות נוספים. השיטות להגבלת השימוש במפתחות API מתוארות במסמכי התיעוד. בפוסט Securing Your Gemini and Google API keys בבלוג של Cloud יש המלצות נוספות לגבי תחזוקה של מפתחות API. ב-Codelab הזה תיישמו את ההמלצות האלה.

הפעולות שתבצעו:

  • בדיקת ההגבלות שנאכפות כשיוצרים מפתחות API חדשים ב-Google Cloud
  • קטלוג של כל מפתחות ה-API, ומציאת המפתחות ללא הגנה אבטחתית
  • אכיפת הגבלות על מפתחות API קיימים על סמך השימוש בהם
  • הגדרת פעולות אוטומטיות למחיקת המפתח במקרה של שימוש חריג

הדרישות

  • דפדפן אינטרנט מודרני (כמו Chrome).
  • חשבון Google

2. הגדרה

ההוראות ב-Codelab הזה מניחות שאתם מריצים פקודות ב-Cloud Shell במסוף Google Cloud. אם יש לכם ה-CLI של gcloud בסביבה המקומית, אתם יכולים להריץ את הפקודות שם.

אפשר לבצע את הפעולות בשלבים באמצעות ממשק המשתמש של מסוף Cloud, אבל השיטות שונות. בשיעור Codelab הזה נשתמש בממשק שורת הפקודה כדי לפשט את האינטראקציות ולאפשר שילוב קל יותר עם סוכני AI מודרניים (כמו Antigravity CLI).

הפעלת טרמינל Cloud Shell

  1. פותחים את מסוף Google Cloud באמצעות הכתובת https://console.cloud.google.com/ בחלון חדש בדפדפן. מומלץ להשתמש ב-Chrome כדי ליהנות מחוויית המשתמש הטובה ביותר.
  2. נכנסים לחשבון Google ב-Google Cloud.
  3. לוחצים על Activate Cloud Shell הסמל של Activate Cloud Shell בחלק העליון של מסוף Google Cloud.
    אם מוצגים חלונות, לוחצים על החלונות הבאים:
    • ממשיכים בחלון המידע של Cloud Shell.
    • מאשרים ל-Cloud Shell להשתמש בפרטי הכניסה שלכם כדי לבצע קריאות ל-Google Cloud API.

בחירת פרויקט ב-Google Cloud

אחרי שפותחים את מסוף Cloud, המערכת מאמתת אתכם, ובדרך כלל יש אפשרות לבחור פרויקט לעבודה. מזהה הפרויקט הוא רצף של 6 עד 30 תווים של אותיות קטנות, מספרים ומקפים, לדוגמה qwiklabs-gcp-04-3075fc9fd77f. הטרמינל של Cloud Shell מגדיר את gcloud CLI עם הפרויקט שנבחר. הפלט אמור להיראות כך:

Your Cloud Platform project in this session is set to qwiklabs-gcp-04-3075fc9fd77f

המשמעות היא שפקודות נוספות שתריצו ב-gcloud ישתמשו במזהה הפרויקט qwiklabs-gcp-04-3075fc9fd77f.

מגדירים את מזהה הפרויקט כמשתנה סביבה PROJECT_ID. כדי לראות את רשימת כל הפרויקטים, משתמשים בפקודה הבאה:

gcloud projects list
  • מחליפים את your-project-id ומריצים את הפקודה אם רוצים להשתמש במזהה פרויקט ששונה מזה שהוגדר ב-gcloud.
    export PROJECT_ID="your-project-id"
    
    לדוגמה:
    export PROJECT_ID="qwiklabs-gcp-04-3075fc9fd77f"
    
  • מריצים את הפקודה הבאה אם רוצים להשתמש במזהה הפרויקט שנבחר:
    export PROJECT_ID=$(gcloud config get project)
    

3. הגבלת מפתח API חדש

בעבר, משתמשים יכלו ליצור מפתחות API ללא הגבלות. אפשר להשתמש במפתחות לא מוגבלים כדי לקרוא לכל Google API שמופעל בפרויקט שבו נוצר המפתח. במסוף Google Cloud, המשתמשים לא יכולים ליצור מפתחות ללא הגבלות, אבל הם יכולים לעשות זאת באמצעות gcloud CLI או באמצעות קריאות ישירות ל-API.

בשלבים הבאים מוסבר איך ליצור מפתח API מוגבל שמגביל את השימוש לממשק API ספציפי ולאתר ספציפי.

  1. כדי ליצור מפתח API חדש שמוגבל לשימוש רק עם Google Map geolocation API, מריצים את הפקודה הבאה במסוף של מעטפת הפקודות:
    gcloud services api-keys create --key-id=restricted-api-key \
      --display-name="restricted api key" \
      --api-target=service=geolocation.googleapis.com \
      --project=${PROJECT_ID}
    
    הפקודה הזו יוצרת מפתח API חדש שאפשר להשתמש בו רק כדי לקרוא לשירות המיקום הגיאוגרפי של מפות Google.
  2. כדי להגביר את אבטחת המפתח, מוסיפים הגבלה על האפליקציה. הגבלת השימוש במפתח לכל הנתיבים באתר example.com בלבד. מריצים את הפקודה הבאה כדי להוסיף את ההגבלה על האפליקציה למפתח:
    gcloud services api-keys update restricted-api-key \
      --location=global \
      --allowed-referrers="example.com/*" \
      --project=${PROJECT_ID}
    
    במקום לאפשר שימוש במפתח באתרים ספציפיים, אפשר להשתמש ב---allowed-application כדי להגדיר אפליקציות מורשות ל-Android או ב-allowed-ips כדי להגדיר כתובות IP מורשות. לעיון בכל האפשרויות, אפשר לעיין במאמרי העזרה המלאים.

הסרת המשאבים

מוחקים את מפתח ה-API שיצרתם, אלא אם אתם מתכוונים להשתמש בו:

gcloud services api-keys delete --key-id=restricted-api-key \
  --project=${PROJECT_ID}

4. קטלוג של מפתחות API

בשלב הזה משתמשים ב-gcloud CLI כדי לקבל רשימה של מפתחות ה-API. ברשימה שמתקבלת מוצגים כל מפתחות ה-API הפעילים (שלא נמחקו) שיש לכם גישה אליהם.

  1. מריצים את הפקודה הבאה כדי לראות את כל שמות המפתחות, המזהים ותאריכי היצירה:
    gcloud services api-keys list --project=${PROJECT_ID} \
      --format='value(displayName,name.basename(),createTime.date())'
    
    בפלט יופיע השם של המפתח שקל לקרוא, מזהה המפתח והתאריך שבו המפתח נוצר. הוא אמור להיראות כך:
    api key 1	api-key-1	2024-05-10T07:53:24
    api key 2	api-key-2	2025-06-12T14:47:57
    
  2. בוחרים אחד ממזהי המפתחות ומדביקים את הפקודה הבאה כדי לבדוק אם יש הגבלות על המפתח. מחליפים את your-key-id בערך של מזהה המפתח שנבחר:
    gcloud services api-keys describe "your-key-id" --project=${PROJECT_ID}
    

הפלט (ב-YAML) יכיל רשימה של הגבלות בקטע restrictions.

createTime: '2024-05-10T07:53:24.986528Z'
displayName: api key 1
etag: W/"u1WuY41K2tPKUZd7cfLoKg=="
name: projects/123456789012/locations/global/keys/api-key-1
restrictions:
  apiTargets:
  - service: geolocation.googleapis.com
  browserKeyRestrictions:
    allowedReferrers:
    - https://example.com/*
uid: 1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6
updateTime: '2024-05-10T07:53:24.071228Z'

שימו לב: אם המפתח לא עודכן אף פעם, בשדות createTime ו-updateTime תופיע אותה חותמת זמן.

  1. מורידים ומריצים את הסקריפט שסורק את כל הפרויקטים ומדפיס את כל מפתחות ה-API שלא חלות עליהם הגבלות:
    curl -fsSL -o unrestricted_api_keys.sh \
      "https://github.com/GoogleCloudPlatform/devrel-demos/blob/main/security/api-key-audit/unrestricted_api_keys.sh"
    chmod +x unrestricted_api_keys.sh
    ./unrestricted_api_keys.sh
    
    אחרי שמריצים את הסקריפט, מוצגת פלט מהסוג הבא:
    DISPLAY NAME    KEY ID    PROJECT ID    CREATION DATE
    Key 1    1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6    my-project-1    2024-05-10T07:53:24.071228Z
    
    אפשר למצוא את כל הסקריפטים שנעשה בהם שימוש ב-CodeLab הזה בתיקיית האבטחה במאגר devrel-demos ב-GitHub.

5. איך בודקים את השימוש במפתח API

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

  1. משתמשים באותו מזהה מפתח שבו השתמשתם בשלב הקודם או בוחרים מזהה מפתח אחר. מחליפים את your-key-id במזהה המפתח שנבחר בפקודה הבאה:
    export KEY_UID=$(
       gcloud services api-keys describe "your-key-id" \
       --format='value(uid)' \
       --project=${PROJECT_ID})
    
  2. מגדירים את החיפוש כך שיציג את היסטוריית השימוש בשנה האחרונה. אם רוצים לחפש תקופה ארוכה או קצרה יותר, מחליפים את 365 (מספר הימים) במספר חיובי אחר.
    export DAYS=365
    
  3. רענון של Application Default Credentials ‏ (ADC) כדי לאפשר קריאה ישירה ל-Cloud Monitoring API. מריצים את הפקודה הבאה ופועלים לפי ההוראות במסוף:
    gcloud auth application-default login
    
  4. מריצים את הפקודה הבאה כדי לשלוח בקשה לנתוני מדדים של שימוש בשירות ל-Cloud Monitoring API:
curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  --data-urlencode "filter=metric.type=\"serviceruntime.googleapis.com/api/request_count\" AND resource.labels.credential_id=\"apikey:${KEY_UID}\"" \
  --data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)" \
  --data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  "https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries" \
  | jq -r '.timeSeries[]?.resource.labels.service' | sort -u

הפקודה שולחת שאילתה למדד המובנה serviceruntime/api/request_count כדי לקבל נקודות נתונים עם התווית credential_id שתואמות למזהה הייחודי של מפתח ה-API שנבחר. לאחר מכן, היא מאחזרת את הערכים של התווית service ומדפיסה את הערכים בלי חזרות.

הקשחת מפתח API

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

תשתמשו באותו מפתח API שבו השתמשתם בשלב הקודם. אם צריך, מריצים מחדש את ההוראות מהשלבים הקודמים כדי לוודא שמשתני הסביבה PROJECT_ID, ‏ KEY_UID ו-DAYS מוגדרים.

  1. מריצים את הפקודה הבאה כדי לאחזר את רשימת ממשקי Google API שמתבצעת אליהם קריאה באמצעות מפתח ה-API:

SERVICES=$(curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)"
–data-urlencode "filter=metric.type="serviceruntime.googleapis.com/api/request_count" AND resource.labels.credential_id="apikey:${KEY_UID}""
–data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)"
–data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
"https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
| jq -r ‘.timeSeries[]?.resource.labels.service' | sort -u)

1. Build the list of arguments to restrict the API usage for the API key based
on the retrieved list.

```shell
API_TARGET_ARGS=()
for SERVICE in $SERVICES; do
  API_TARGET_ARGS+=("--api-target=service=${SERVICE}")
done
  1. להחליף את רשימת ממשקי ה-API המוגבלים ברשימה לא ריקה:
    if [ ${#API_TARGET_ARGS[@]} -gt 0 ]; then
        gcloud services api-keys update "projects/${PROJECT_ID}/locations/global/keys/${KEY_UID}" \
        ${API_TARGET_ARGS}
    fi
    

6. הגדרת זיהוי של שימוש חריג

בשלבים הקודמים הראינו איך לבדוק מפתחות API ולחזק אותם. בשלב הזה מוסבר איך להפוך את התגובה לעלייה בלתי צפויה בשימוש במפתח לאוטומטית בעזרת התראות ב-Monitoring.

ההוראות הבאות יוצרות התראה שמופעלת כששיעור הקריאות ל-API שמשתמשות במפתח API עולה ביותר מ-10% במהלך 5 הדקות האחרונות. ההתראה מוגדרת להפעלת סקריפט של Cloud Build שמוחק את מפתח ה-API כדי למנוע שימוש נוסף. אפשר לשחזר את המפתח במהלך 30 הימים הבאים. כך מבטלים את המחיקה של המפתח.

ההוראות משתמשות שוב במשתנים PROJECT_ID ו-KEY_UID שבהם השתמשתם בשלבים הקודמים. כדי לבחור מפתח או פרויקט אחרים, צריך להגדיר את הערכים החדשים של המשתנים האלה כמו שמתואר בשלבים להגדרה ולגילוי השימוש במפתח API.

  1. מריצים את הסקריפט הבא כדי ליצור קובץ של מדיניות התראות:
    cat <<EOF > alert_policy.json
    {
      "displayName": "Credential API Request Count Increase Alert (Project: ${PROJECT_ID})",
      "combiner": "OR",
      "conditions": [
        {
          "displayName": "API Request Count Increase > 10% in 5m with Min Volume",
          "conditionPrometheusQueryLanguage": {
            "query": "(sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) / (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m] offset 5m)) or on() vector(1)) > 1.10) and (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) > 50)",
            "duration": "0s",
            "evaluationInterval": "60s"
          }
        }
      ],
      "enabled": true
    }
    EOF
    
    מדיניות ההתראות משתמשת במסנן PromQL הבא כדי להפעיל את ההתראה:
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m])
     ) /
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m] offset 5m)
     ) or on() vector(1)) > 1.10)
    and
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\"YOUR_CREDENTIAL_ID_HERE\"}[5m])) > 50)
    
    המערכת מחשבת את שיעור העלייה ומשווה אותו לשיעור העלייה בחלון זמן קודם. ההתראה מופעלת רק אם הערך גבוה ב-10% או יותר. כדי למנוע הפעלה של ההתראה כשמספר השיחות הכולל זניח, ההפעלה מותנית בביצוע של יותר מ-50 קריאות ל-API בחלון. כדי למנוע חישוב של NaN (מחיקה לפי אפס) כששיעור ההמרה הקודם ל-5 דקות היה 0, המערכת מחליפה את המכנה ב-1 אם שיעור ההמרה הקודם היה אפס.אפשר לשנות את פרמטרי ההתראה, כמו אורך חלון הזמן (5m), הסף המינימלי (50) או סף העלייה של 10% (1.10).פרמטרים נוספים של המדיניות מגדירים שאחרי שהתנאי מתקיים, ההתראה צריכה להישלח (duration), ושהמערכת צריכה לבדוק את התנאי כל 60 שניות (evaluationInterval).
  2. מריצים את הפקודה הבאה כדי ליצור נושא PubSub שישמש לפרסום התראות:
    gcloud pubsub topics create api-key-alert-notifications --project=$PROJECT_ID
    
  3. מריצים את הפקודה הבאה כדי ליצור ערוץ התראות להתראות שמשתמש ב-PubSub.
    CHANNEL_NAME=$(gcloud beta monitoring channels create \
      --display-name="Pub/Sub Alert Channel" \
      --type="pubsub" \
      --channel-labels="topic=projects/$PROJECT_ID/topics/api-key-alert-notifications" \
      --format='value(name)' \
      --project=$PROJECT_ID)
    
    תשתמשו במשתנה הסביבה CHANNEL_NAME בשלב הניקוי.
  4. מריצים את הפקודה הבאה כדי ליצור התראה חדשה למעקב:
    gcloud monitoring policies create --policy-from-file=alert_policy.json \
      --project=$PROJECT_ID
    
  5. מריצים את הפקודה הבאה כדי לתת לחשבון השירות של Cloud Build הרשאות למחיקת מפתחות ה-API בפרויקט.
    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
      --role="roles/apikeys.admin"
    
    אפשר להגביל את התפקיד apikeys.admin כך שיוכל לבצע שינויים רק במקרים ספציפיים של מפתחות API. לפרטים נוספים, ראו תנאים ב-IAM.
  6. מריצים את הסקריפט הבא כדי ליצור טריגר לפיתוח גרסת Build שמוחק את מפתח ה-API.
    cat <<EOF > trigger_config.yaml
    name: "delete-compromised-api-key"
    description: "Triggered by Pub/Sub alert to automatically delete the leaking API Key"
    pubsubConfig:
      topic: "projects/${PROJECT_ID}/topics/api-key-alert-notifications"
    build:
      steps:
      - name: "gcr.io/google.com/cloudsdktool/cloud-sdk:slim"
        args:
        - "gcloud"
        - "services"
        - "api-keys"
        - "delete"
        - "${KEY_UID}"
        - "--quiet"
    EOF
    
  7. מריצים את הפקודה הבאה כדי ליצור טריגר חדש להתראה ב-Monitoring:
    gcloud builds triggers create pubsub \
      --trigger-config=trigger_config.yaml \
      --project=$PROJECT_ID
    

עכשיו אפשר למחוק את קובצי ההגדרות של מדיניות ההתראות והטריגר לפיתוח גרסת Build של Cloud Build:

rm alert_policy.json trigger_config.yaml

אפשרות אחרת היא להגדיר את האוטומציה הזו באמצעות תוכנית Terraform. מורידים את קובצי Terraform מהתיקייה abnormal-usage-detection במאגר Google Cloud DevRel. התוכנית מקבלת מזהה פרויקט ומזהה ייחודי של מפתח API כפרמטרים של קלט, ומגדירה את המשאבים וההגדרות שראיתם בשלב הזה.

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

כדי למנוע חיובים לא צפויים בחשבון Google Cloud, חשוב למחוק את נושא Pub/Sub, את טריגר לפיתוח גרסת Build ואת מדיניות ההתראות שנוצרו במהלך התרגיל הזה.

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

gcloud builds triggers delete delete-compromised-api-key \
  --project=$PROJECT_ID
gcloud beta monitoring channels delete $CHANNEL_NAME \
  --project=$PROJECT_ID \
  --quiet
gcloud pubsub topics delete api-key-alert-notifications \
  --project=$PROJECT_ID
gcloud projects remove-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/apikeys.admin"

8. סיכום

ב-Codelab הזה הטמעתם מסגרת חזקה של אבטחה ואוטומציה מקצה לקצה למפתחות API של Google Cloud:

  1. הגדרות ברירת מחדל מחוזקות: יצרתם מפתחות API והגבלתם אותם כדי להגביל את הגישה רק לממשקי API נחוצים ולפלטפורמות מהימנות (כמו גורמים מפנים ספציפיים מסוג HTTP).
  2. ביצעת ביקורת על מלאי המפתחות: סרקת את סביבות הפרויקט כדי לזהות ולבודד מפתחות לא מוגבלים שמציבים סיכון אבטחה מיידי.
  3. נתוני שימוש שעברו ניתוח: ביצעתם שאילתות תוכנתיות על נתוני מדדים של Cloud Monitoring כדי ליצור פרופיל של היסטוריית השימוש במפתחות, וכך יכולתם להגביל את המפתחות על סמך טביעות רגל מאומתות של השימוש.
  4. הפחתת איומים אוטומטית: יצרתם "מפסק" תגובתי על ידי קישור של מדיניות התראות ב-Cloud Monitoring לנושא Pub/Sub ולטריגר של Cloud Build, וכך אתם יכולים למחוק באופן אוטומטי מפתחות שנפרצו במהלך עליות חריגות בתנועת הגולשים.

השלבים הבאים

  • החלת הגבלות על כל מפתחות ה-API: משתמשים במה שלמדתם במעבדה הזו כדי לזהות את כל מפתחות ה-API המוגבלים באופן חלקי או לא מוגבלים, ומחילים הגבלות על API ועל לקוחות.
  • הגדרת 'מפסק זרם' במפתחות API: כדי להגן על מפתחות ה-API מפני שימוש לא צפוי, אפשר להגדיר מחיקה אוטומטית של המפתחות במקרה של עלייה פתאומית בצריכה. משתמשים בפקודות gcloud או ב-Terraform שמוצגות במעבדה. כדאי להשתמש בתנאי IAM כדי להגביל את ההרשאות
  • מידע נוסף על התראות ב-Monitoring: אפשר לקרוא על הגדרת התראות באמצעות שירות Google Cloud Monitoring.
  • מידע נוסף על בקרת הגישה שזמינה ב-Google Cloud: כדאי לעיין במאמרים בנושא מדיניות של גבולות גישה והפצת שינויים בגישה.