בדף הזה מפורטות בעיות שונות שאפשר להיתקל בהן כשמגדירים את VPC Service Controls.
התנהגות לא צפויה של מדיניות בהיקף מסוים
יכול להיות שתזהו הפרות לא צפויות של VPC Service Controls, שאמורות להיות מותרות על ידי מדיניות ההיקף שלכם. זו בעיה מוכרת: אם אין לכם מדיניות גישה ברמת הארגון, יכול להיות שתיתקלו בבעיות לא צפויות במדיניות הגישה המוגבלת שלכם.
כדי לפתור את הבעיה הזו, יוצרים מדיניות גישה ברמת הארגון באמצעות הפקודה הבאה:
gcloud access-context-manager policies create --organization <var>ORGANIZATION_ID</var> --title <var>POLICY_TITLE</var>
מחליפים את מה שכתוב בשדות הבאים:
- ORGANIZATION_ID: מזהה הארגון.
- POLICY_TITLE: שם קריא לאנשים של מדיניות הגישה.
מידע נוסף זמין במאמר יצירת מדיניות גישה.
VPC משותף
כשמשתמשים ב-VPC משותף, גבולות גזרה לשירות שכוללים פרויקטים ששייכים לרשת VPC משותפת צריכים לכלול גם את הפרויקט שמארח את הרשת. אם פרויקטים ששייכים לרשת VPC משותפת לא נמצאים באותו היקף כמו פרויקט המארח, יכול להיות שהשירותים לא יפעלו כמו שצריך או שהם ייחסמו לחלוטין.
חשוב לוודא שהמארח של רשת ה-VPC המשותפת נמצא באותו היקף שירות כמו הפרויקטים שמחוברים לרשת.
אי אפשר להוסיף רשת VPC
השגיאה הבאה יכולה להתרחש כשמנסים להוסיף רשת VPC לגבולות של שירות:
ERROR: (gcloud.access-context-manager.perimeters.update) PERMISSION_DENIED: Permission 'compute.networks.get' denied on resource '//compute.googleapis.com/projects/PROJECT_NAME/global/networks/VPC_NETWORK_NAME' (or it may not exist)
השגיאה הזו מתרחשת בגלל אחת מהסיבות הבאות:
- רשת ה-VPC לא קיימת.
- רשת ה-VPC קיימת, אבל אין לה רשת משנה.
- למתקשר אין את ההרשאה הנדרשת.
כדי לפתור את הבעיה, מבצעים את השלבים הבאים:
בודקים אם רשת ה-VPC שצוינה בהודעת השגיאה קיימת על ידי הצגת הרשתות בפרויקט.
לפני שמאמתים את רשת ה-VPC, צריך לוודא ש-Compute Engine API מופעל בפרויקט שמשויך לקריאה ל-API. לשם כך, מבצעים את השלבים הבאים:
במסוף Google Cloud , נכנסים לדף APIs & Services.
כניסה אל APIs & Servicesבדף APIs & Services, בודקים אם API של Compute Engine מופיע ברשימה.
אם Compute Engine API לא מופיע, צריך להפעיל אותו.
הפעלת ה-API
כדי לבדוק אם קיימת לפחות רשת משנה אחת ברשת ה-VPC, צריך להציג את רשתות המשנה. אם אין תת-רשתות, מוסיפים תת-רשת לרשת ה-VPC.
בודקים אם למבצע הקריאה החוזרת יש את ההרשאה הבאה בפרויקט המארח של רשת ה-VPC:
compute.networks.get. ההרשאה הזו מאפשרת לכם לראות רשתות VPC בפרויקט.מבקשים מהאדמין של הארגון שבבעלותו הפרויקט המארח של רשת ה-VPC להקצות לקורא תפקיד IAM עם הרשאה
compute.networks.getבפרויקט המארח. לדוגמה, התפקיד 'צפייה ברשת של Compute'.מידע נוסף על מתן תפקידים זמין במאמר ניהול הגישה.
חשוב לקרוא את המגבלות שקשורות לשימוש ברשתות VPC ב-service perimeters.
בקשות בין היקפים
בדרך כלל, רמות גישה משמשות כדי לאפשר בקשות ממחוץ לגבולות גזרה של שירות למשאבים מוגנים בתוך גבולות הגזרה.
עם זאת, בקשה מפרויקט בהיקף מוגדר למשאב מוגן בהיקף מוגדר אחר נדחית, גם אם רמת הגישה מאפשרת את הבקשה בדרך כלל.
לדוגמה, נניח שבפרויקט א' בגבול גזרה 1 מתבצעת בקשה למשאב מפרויקט ב'. המשאב בפרויקט ב' מוגן על ידי גבולות גזרה 2. מכיוון שפרויקט א' נמצא בהיקף, גם אם רמת הגישה להיקף 2 מאפשרת בדרך כלל את הבקשה למשאב המוגן, הבקשה נדחית.
כדי לאפשר בקשות בין היקפים, אפשר להשתמש באחת מהגישות הבאות:
שימוש במדיניות יציאה ומדיניות כניסה. כדי לאפשר בקשות ממתחם אחר למשאבים מוגנים במתחם שלכם, המתחם האחר צריך להשתמש במדיניות יציאה, ואתם צריכים להגדיר מדיניות כניסה במתחם שלכם.
שימוש בגבולות גזרה מגושרים. גשרים מאפשרים לשני פרויקטים או יותר שנמצאים בהיקפים שונים לשלוח בקשות לכל השירותים בפרויקטים האלה. הבקשות האלה מותרות גם אם השירותים מוגנים על ידי ההיקפים המתאימים.
מוודאים שגם השירות ששולח את הבקשה וגם משאב היעד לא מוגנים על ידי גבולות הגזרה. במקרה כזה, הפעולה תצליח כי השירותים לא מוגנים.
כתובת האימייל לא תקינה או לא קיימת
כשמעדכנים היקף שמכיל חשבון משתמש שנמחק, יכול להיות שתיתקלו בשגיאה The email address is invalid or non-existent.
כדי לפתור את הבעיה, צריך להסיר את כתובת האימייל הלא תקינה מכל ההיקפים:
ייצוא כל ההיקפים. הפקודה לדוגמה הבאה מייצאת רשימה של גבולות שירות בפורמט JSON:
gcloud access-context-manager perimeters list \ --policy=POLICY_NAME \ --format="json(name,title,description,perimeterType,status,\ spec,useExplicitDryRunSpec)" \ > my-perimeters.json
מסירים את כתובת האימייל הלא תקינה מהקובץ
my-perimeters.jsonושומרים אותו בשםmy-perimeters-updated.json.
הפרות של כללים לתעבורת נתונים נכנסת (ingress) ויוצאת (egress)
יומן הביקורת מכיל מידע על הפרות של כללי הכניסה והיציאה, שיעזור לכם להבין את ההפרות של ההיקף.
הפרה של כלל לתעבורת נתונים נכנסת (ingress)
הפרה של כלל לתעבורת נתונים נכנסת מציינת שלקוח API מחוץ לגבול הגזרה ניסה לגשת למשאב בתוך גבול הגזרה. הבקשה נדחית על ידי אזור השירות כי אין כללים תואמים של תעבורת נתונים נכנסת או רמות גישה.
הפרטים הבאים מופיעים ביומן הביקורת לגבי הפרה של כלל תעבורה נכנסת:
- השם של ההיקף שבו התרחשה ההפרה של כלל הכניסה.
- המשאב בתוך ההיקף שאליו לקוח ה-API מחוץ להיקף ניסה לגשת.
בדוגמה הבאה להפרה של כלל תעבורה נכנסת, לקוח API מחוץ להיקף מנסה לגשת לקטגוריית Cloud Storage prod-protected-storage-bucket בתוך ההיקף prod-perimeter.
ingressViolations: [
0: {
targetResource: "projects/1234/buckets/prod-protected-storage-bucket"
servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
}
]
כדי לפתור את הבעיה, צריך ליצור כלל כניסה להיקף. מידע נוסף על כללי תעבורה נכנסת זמין במאמר הפניה לכללי תעבורה נכנסת.
הפרה של כלל לתעבורת נתונים יוצאת (egress)
הפרה של כלל יציאה ביומן הביקורת מציינת אחד מהאירועים הבאים:
- לקוח API בתוך ההיקף ניסה לגשת למשאב מחוץ להיקף.
- בקשת API שכוללת משאב בתוך ההיקף ומשאב מחוץ להיקף. לדוגמה, לקוח Cloud Storage שמפעיל פקודת העתקה כשקטגוריית אחסון אחת נמצאת בתוך ההיקף וקטגוריית האחסון השנייה נמצאת מחוץ להיקף.
היקף השירות דוחה את הבקשה כי אין כללים תואמים ליציאה. הפרטים הבאים מופיעים ביומן הביקורת לגבי הפרה של כלל יציאה:
- סוג המקור, למשל רשת או משאב.
- המקור, שהוא משאב או רשת, שהיקף האבטחה שלו נפרץ בגלל יציאה (egress) לא מורשית.
- ההיקף שבו אירעה הפרה של יציאת נתונים.
- משאב היעד מחוץ להיקף שבו הבקשה ניסתה לגשת.
בדוגמה הבאה של הפרת כלל יציאה, בקשת ה-API כוללת משאב מ-projects/5678, שנמצא בתוך ההיקף prod-perimeter, ואובייקט מהקטגוריה external-storage-bucket ב-Cloud Storage, שנמצא מחוץ להיקף.
egressViolations: [
0: {
sourceType: "Resource"
source: "projects/5678"
targetResource: "projects/4321/buckets/external-storage-bucket/objects/corp-resources.json"
servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
}
]
כדי לפתור את הבעיה, צריך ליצור כלל ליציאה עבור ההיקף. מידע נוסף על כללי יציאה מופיע במאמר הפניה לכללי יציאה.
ניפוי באגים בבקשות שנחסמו על ידי VPC Service Controls
יומן הביקורת של VPC Service Controls הוא הכלי העיקרי לניפוי באגים בבקשה שנחסמה על ידי VPC Service Controls.
אם הגישה נחסמה באופן לא צפוי, כדאי לעיין ביומני הביקורת בפרויקט שמוגן על ידי היקף ה-Service Control. היומנים האלה מכילים נתונים חשובים על המשאבים המבוקשים ועל הסיבה לדחיית הבקשה. מידע על אבחון יומני הביקורת מופיע במאמר גישה לכלי לניתוח הפרות.
בקטעים הבאים מפורטים הערכים של violationReason שאולי תיתקלו בהם כשמשתמשים ב-VPC Service Controls.
NETWORK_NOT_IN_SAME_SERVICE_PERIMETER
הסיבות האפשריות לבעיה הזו:
- לקוח ברשת VPC בתוך היקף שירות מנסה לגשת לפרויקט שלא נמצא באותו היקף. הבקשה הזו גורמת להפרה של יציאת נתונים. כדי לפתור את הבעיה, צריך ליצור כלל ליציאה.
- לקוח ברשת VPC שנמצאת מחוץ ל-service perimeter מנסה לגשת לפרויקט שמוגן על ידי ה-service perimeter. הבקשה הזו גורמת להפרה של כללי הכניסה. כדי לפתור את הבעיה הזו, צריך ליצור כלל תעבורת נתונים נכנסת (ingress).
הלקוח יכול לשלוח את הבקשה ממכונה וירטואלית של Compute Engine או Google Kubernetes Engine, או מרשת מקומית דרך Cloud Interconnect או VPN שהוגדר באמצעות רשת VPC.
בתרשים הבא אפשר לראות שמתרחשת הפרה של תעבורת נתונים יוצאת (egress) כשלקוח ברשת VPC בגבול גזרה של שירות מנסה לגשת לפרויקט מחוץ לגבול הגזרה:

דוגמה להפרה של יציאת נתונים:
egressViolations: [
{
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
source: "projects/<NETWORK_PROJECT_NUMBER>"
sourceType: "Network"
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>"
}
]
כאשר:
-
<POLICY_NAME>הוא השם המספרי של מדיניות הגישה. -
<PERIMETER_NAME>הוא השם של service perimeter. -
<NETWORK_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את רשת ה-VPC. -
<RESOURCE_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את המשאב.
בתרשים הבא אפשר לראות שהפרה של כניסה מתרחשת כשלקוח מחוץ להיקף מנסה לגשת לפרויקט בתוך ההיקף:

דוגמה להפרה של כללי הכניסה:
ingressViolations: [
{
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
source: "projects/<NETWORK_PROJECT_NUMBER>"
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
}
]
כאשר:
-
<RESOURCE_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את המשאב. -
<NETWORK_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את רשת ה-VPC. -
<POLICY_NAME>הוא השם המספרי של מדיניות הגישה. -
<PERIMETER_NAME>הוא השם של service perimeter.
רזולוציה
כדי לפתור את השגיאה הזו, צריך ליצור כלל כניסה או יציאה להיקף.
RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER
הבעיה הזו מתרחשת כשבקשה אחת ניגשת למספר משאבים, אבל המשאבים לא נמצאים באותו היקף שירות. הבעיה הזו מתרחשת בלי קשר למיקום של הלקוח ולשאלה אם יש לו גישה למשאבים.
בתרשים הבא מוצגת גישה של לקוח למשאבים מפרויקט מחוץ לגבולות הגזרה ומפרויקט בתוך גבולות הגזרה של השירות:

בתרשים הבא מוצג לקוח שניגש למשאבים מפרויקטים שנמצאים בשני היקפי שירות שונים, אבל ההיקפים לא מתקשרים ביניהם:

דוגמה להפרה של יציאת נתונים:
egressViolations: [
{
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
source: "projects/<RESOURCE_PROJECT_INSIDE_THIS_PERIMETER>"
sourceType: "Resource"
targetResource: "projects/<RESOURCE_PROJECT_OUTSIDE_THIS-PERIMETER>"
}
]
כאשר:
-
<POLICY_NAME>הוא השם המספרי של מדיניות הגישה. -
<PERIMETER_NAME>הוא השם של service perimeter. -
<RESOURCE_PROJECT_INSIDE_THIS_PERIMETER>הוא מספר הפרויקט של Google Cloud הפרויקט שנמצא בתוך ההיקף. -
<RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER>הוא מספר הפרויקט של הפרויקט Google Cloud שנמצא מחוץ להיקף.
רזולוציה
כדי לפתור את הבעיה, צריך ליצור כלל יציאה להיקף.
NO_MATCHING_ACCESS_LEVEL
הבעיה הזו מתרחשת כשכתובת ה-IP, דרישת המכשיר או זהות המשתמש לא תואמות לאף כלל כניסה או רמת גישה שהוקצו להיקף. המשמעות היא שלקוח שלא שייך לרשת Google Cloud מנסה לגשת למשאבי הרשת של Google Cloud מחוץ להיקף. לדוגמה, כתובת ה-IP שמתאימה לשדה callerIp ברשומת הביקורת לא תואמת לאף טווח CIDR שמוגדר ברמות הגישה של היקף השירות.
אם כתובת ה-IP של הגורם ששלח את הקריאה חסרה או מופיעה ככתובת IP פנימית, יכול להיות שההפרה הזו נובעת מ Google Cloud שירות שלא משולב עם VPC Service Controls. הסיבה לכך יכולה להיות שהשירותGoogle Cloud מנסה לגשת לשירות מוגן ונכשל, כצפוי.
כדי לפתור את הבעיה הזו, מומלץ ליצור כלל תעבורת נתונים נכנסת במקום רמת גישה, כי כלל תעבורת נתונים נכנסת מספק בקרת גישה פרטנית.
בתרשים הבא מוצג לקוח שמנסה לגשת למשאבים מחוץ לגבולות:

דוגמה להפרה של כללי הכניסה:
authenticationInfo: {
principalEmail: "EMAIL"
}
requestMetadata: {
callerIp: "<PUBLIC_IP_ADDRESS>"
deviceState: "Cross Organization"
}
ingressViolations: [
{
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER-NAME>"
}
]
כאשר:
<EMAIL>היא כתובת האימייל של חשבון השירות או של המשתמש המאומת.אם אתם משתמשים בשירות ש-VPC Service Controls לא תומך בו, כתובות אימייל ששייכות לדומיין
google.comיוסתרו ויוחלפו ב-google-internal. Google Cloud google-internalמתייחס לזהויות פנימיות בבעלות Google.
<PUBLIC_IP_ADDRESS>היא כתובת ה-IP של המתקשר. למתקשר מהאינטרנט, זו תהיה כתובת IPv4 או IPv6 ציבורית.
<RESOURCE_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את המשאב.
<POLICY_NAME>הוא השם המספרי של מדיניות הגישה.
<PERIMETER_NAME>הוא השם של service perimeter.
שימו לב: במקרה הזה, יכול להיות שעדיין תהיה גישה ל-metadata.accessLevels כי יכול להיות שרמות הגישה האלה לא צוינו בהיקף שהופר.
SERVICE_NOT_ALLOWED_FROM_VPC
הבעיה הזו מתרחשת כשלקוח מנסה לגשת למשאבים מרשת VPC. Google Cloud הלקוח יכול לשלוח את הבקשה ממכונה וירטואלית של Compute Engine או Google Kubernetes Engine, או מרשת מקומית דרך Cloud Interconnect או VPN שהוגדר באמצעות רשת VPC.
כדי לפתור את הבעיה, צריך לוודא שהשירות שאליו מתבצעת הקריאה מותר בהגדרה VPC accessible services של גבול הגזרה לשירות.
תרחישים לדוגמה
בדוגמאות הבאות מוסבר על בעיות שאתם עשויים להיתקל בהן במהלך השימוש ב-VPC Service Controls.
- גישה ל-Cloud Storage משרת מקומי
- גישה ל-BigQuery ממכונה וירטואלית מחוץ לפרויקט
- שאילתת BigQuery בין פרויקטים
- העברת קובץ Cloud Storage בתוך ההיקף
- העברת קובץ Cloud Storage אל מחוץ להיקף
- העתקה של מערך נתונים ב-BigQuery ממכונה וירטואלית בתוך ההיקף
- קריאת משימות של Managed Service for Apache Spark מפרויקט
- שירות לא נתמך עם כתובת VIP מוגבלת
- ייצוא יומן לפרויקט מחוץ להיקף
- שליפת נתונים מ-BigQuery ל-Cloud Storage
גישה ל-Cloud Storage משרתים מקומיים
בדוגמה הזו, VPC Service Controls חוסם בקשה מתחנת עבודה של עובד (מזוהה על ידי callerIp) לקטגוריה ב-Cloud Storage בפרויקט corp-storage.
הבקשה יוצרת את הרשומה הבאה ביומן הביקורת:
{
insertId: "222lvajc6f7"
logName: "projects/corp-storage/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "someone@google.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/_"
]
violationReason: "NO_MATCHING_ACCESS_LEVEL"
}
methodName: "google.storage.NoBillingOk"
requestMetadata: {
callerIp: "b1d5:d26d:5b17:43fe:d358:586b:db59:9617"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/690885588241"
serviceName: "storage.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-27T21:40:43.823209571Z"
resource: {
labels: {
method: "google.storage.NoBillingOk"
project_id: "corp-storage"
service: "storage.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-27T21:40:42.973784140Z"
}
הפרויקט corp-storage נכלל בגבולות גזרה לשירות. תחנת העבודה של העובד לא נמצאת באף רשת בתוך ההיקף הזה. מכיוון שתחנת העבודה של העובד נמצאת מחוץ להיקף, הבקשה נחסמת.
גישה ל-BigQuery ממכונה וירטואלית מחוץ לפרויקט
בדוגמה הזו, מכונה וירטואלית ששייכת לפרויקט 458854174376 (data-collector) מנסה להריץ שאילתת BigQuery על מערך נתונים בפרויקט 798816221974 (corp-resources-protected), אבל הפעולה נדחית.
מכונת ה-VM משתמשת בשאילתה הבאה:
bq --project=corp-resources-protected query 'select count(*) from babynames.yob2000'
השאילתה מחזירה את הפלט הבא:
BigQuery error in query operation: VPC Service Controls: Request is
prohibited by organization's policy. Operation ID:
33643962-6a0f-4091-9283-bcdf7e9271f0
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "1ei551d2pdq"
logName: "projects/corp-resources-protected/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "714877721106-compute@developer.gserviceaccount.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/1004338142803"
]
violationReason: "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "bigquery.googleapis.com/bigquery.jobs.create"
requestMetadata: {
callerIp: "10.105.0.2"
callerNetwork: "//compute.googleapis.com/projects/ameet-dataflow/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/1004338142803"
serviceName: "bigquery.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-28T23:06:13.579882505Z"
resource: {
labels: {
method: "bigquery.googleapis.com/bigquery.jobs.create"
project_id: "corp-resources-protected"
service: "bigquery.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-28T23:06:12.799656975Z"
}
בדוגמה הזו, הערך של violationReason הוא NETWORK_NOT_IN_SAME_SERVICE_PERIMETER. callerNetwork כלול בנוסף לcallerIp. כתובת ה-IP פרטית, והרשת מסופקת כדי להבחין בינה לבין כתובות אחרות. המשאבים הרלוונטיים שקשורים לבעיה הזו מפורטים בשני מקומות: VpcServiceControlAuditMetadata.resourceNames ו-requestMetadata.callerNetwork (הפרויקט שבבעלותו הרשת).
הבעיה היא שהפרויקט corp-resources-protected נמצא בתוך היקף שירות, אבל הפרויקט data-collector, שכולל את הרשת שהמכונה הווירטואלית שייכת לה, לא נמצא בתוך היקף שירות. במקרה כזה, הגישה נדחית כמו שצריך.
שאילתת BigQuery חוצת-פרויקטים
בדוגמה הזו, מכונה וירטואלית ששייכת לפרויקט perimeter-network מנסה להריץ שאילתה על מופעי BigQuery של שני פרויקטים שונים: corp-resources-protected, שנמצא באותו היקף שירות כמו perimeter-network, ו-corp-resources-public, שלא נמצא באותו היקף שירות.
מכונת ה-VM משתמשת בפקודה הבאה:
bq query --use_legacy_sql=false \
'select count(priv.name),count(pub.name) from \
`corp-resources-protected.babynames.yob2000` as priv, \
`corp-resources-public.babynames.yob2000` as pub'
השאילתה מחזירה את הפלט הבא:
BigQuery error in query operation: Error processing job
'example:bqjob_r211e6f6eec928ffb_000001675c996aa8_1': VPC Service Controls:
Request is prohibited by organization's policy. Operation ID:
dc4fc177-4850-4fc5-b2e7-8c33f302149a
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "17kg4exd24ag"
logName: "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/117961063178"
1: "projects/690885588241"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "bigquery.googleapis.com/bigquery.tables.getData"
requestMetadata: {
callerIp: "130.211.225.66"
callerNetwork: "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/927005422713"
serviceName: "bigquery.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-28T20:48:51.384237810Z"
resource: {
labels: {
method: "bigquery.googleapis.com/bigquery.tables.getData"
project_id: "perimeter-network"
service: "bigquery.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-28T20:48:50.561884949Z"
}
אם מסתכלים על callerNetwork ועל VpcServiceControlAuditMetadata.resourceNames, אפשר לראות שלושה פרויקטים: perimeter-network, 117961063178 (corp-resources-public) ו-690885588241 (corp-resources-protected). כזכור, corp-resources-public לא נמצא באותו היקף שירות כמו perimeter-network ו-corp-resources-protected.
הערך violationReason, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER מציין שחלק מהמשאבים בבקשה נמצאים מחוץ לגבולות הגזרה שחלים על הבקשה. במקרה הזה, המשאב הוא corp-resources-public.
העברת קובץ Cloud Storage בתוך ההיקף
בדוגמה הזו, מכונה וירטואלית בפרויקט perimeter-network משתמשת בפקודה כדי להעביר קובץ מקטגוריה אחת של Cloud Storage, שנמצאת בפרויקט corp-resources-protected, לקטגוריה אחרת, שנמצאת בפרויקט corp-resources-public.
מכונת ה-VM משתמשת בפקודה הבאה:
gcloud storage mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
הפקודה מחזירה את הפלט הבא:
Copying gs://corp-resources-private-1/yob2000.txt [Content-Type=text/plain]...
AccessDeniedException: 403 Request violates VPC Service Controls.
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "1xxnssmd2hqo"
logName: "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "storage-accessing@example.iam.gserviceaccount.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/_/buckets/corp-resources-public-1"
]
violationReason: "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "google.storage.BillingRequiredRead"
requestMetadata: {
callerIp: "130.211.225.66"
callerNetwork: "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/927005422713"
serviceName: "storage.googleapis.com"
status: {…}
}
receiveTimestamp: "2018-11-28T00:45:31.531623485Z"
resource: {
labels: {
method: "google.storage.BillingRequiredRead"
project_id: "perimeter-network"
service: "storage.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-28T00:45:31.351140381Z"
}
במקרה הזה, היומן פחות ברור כי השיטה שמופיעה בו היא BillingRequiredRead והפעולה שבוצעה היא move. זו מגבלה של הפונקציונליות הנוכחית של יומן הביקורת ב-VPC Service Controls.
הסיבה פחות ברורה, אבל רשומת יומן הביקורת הזו מציינת שחלק מהמשאבים בבקשה נמצאים מחוץ להיקף שחל על הבקשה. במקרה הזה, המשאב הוא corp-resources-public.
העברת קובץ Cloud Storage מחוץ להיקף
בדוגמה הזו, מכונה וירטואלית בפרויקט public-network משתמשת בפקודה כדי להעביר קובץ מקטגוריה אחת של Cloud Storage, שנמצאת בפרויקט corp-resources-protected, לקטגוריה אחרת, שנמצאת בפרויקט corp-resources-public.
הפרויקט corp-resources-protected מוגן על ידי גבולות גזרה לשירות. הפרויקטים public-network ו-corp-resources-public קיימים מחוץ לגבולות.
מכונת ה-VM משתמשת בפקודה הבאה:
gcloud storage mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
הפקודה מחזירה את הפלט הבא:
Copying gs://corp-resources-private-1/yob2000.txt [Content-Type=text/plain]...
AccessDeniedException: 403 Request violates VPC Service Controls.
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "10moqhsch9v"
logName: "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "user@example.biz"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/_/buckets/corp-resources-private-1/objects/yob2000.txt"
1: "projects/_/buckets/corp-resources-public-1/objects/out.txt"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "google.storage.Write"
requestMetadata: {
callerIp: "2620:15c:2c4:203:63d6:5eb8:418d:c034"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/1004338142803"
serviceName: "storage.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-30T16:34:46.948010626Z"
resource: {
labels: {
method: "google.storage.Write"
project_id: "corp-resources-private"
service: "storage.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-30T16:34:46.898098978Z"
}
בדוגמה הזו, יומן הביקורת מציין שאי אפשר להעתיק נתונים מעבר לגבול של היקף שירות (שני המשאבים נמצאים ברשומה ביומן הביקורת).
חשוב לזכור שהבקשה מגיעה מחוץ לגבולות (המכונה הווירטואלית ב-public-network), ואחד ממאגרי המידע נמצא מחוץ לגבולות (corp-resources-public-1).
מחוץ להיקף, אפשר לכתוב ל-bucket
corp-resources-public-1, ולכן הבדיקה שנכשלה בדוגמה הקודמת עוברת. עם זאת, הבדיקה הבאה שנועדה להעתיק את הנתונים נכשלת.
בדוגמה הזו אפשר לראות איך לפעמים פעולת משתמש אחת מובילה לכמה פעולות פנימיות שצריכות לעבור את האכיפה של VPC Service Controls.
העתקה של מערך נתונים ב-BigQuery ממכונה וירטואלית בתוך ההיקף
בדוגמה הזו, מכונה וירטואלית בפרויקט 927005422713 (perimeter-network) מנסה להעתיק מערך נתונים של BigQuery מפרויקט corp-resources-private אל corp-resources-public (117961063178). הפרויקטים perimeter-network ו-corp-resources-private חולקים היקף, אבל corp-resources-public נמצא מחוץ להיקף.
מכונת ה-VM משתמשת בפקודה הבאה:
bq cp corp-resources-private:babynames.yob2000 \
corp-resources-public:babynames.yob2000
הפקודה מחזירה את הפלט הבא:
BigQuery error in cp operation: VPC Service Controls: Request is prohibited by
organization's policy. Operation ID: c00dbc44-460f-4bd0-9d09-cda98ac800f9
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "146o5fd2hbp"
logName: "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/117961063178"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "bigquery.googleapis.com/bigquery.tables.get"
requestMetadata: {
callerIp: "131.201.221.16"
callerNetwork: "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/927005422713"
serviceName: "bigquery.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-28T00:27:05.688803777Z"
resource: {
labels: {
method: "bigquery.googleapis.com/bigquery.tables.get"
project_id: "perimeter-network"
service: "bigquery.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-28T00:27:05.378584819Z"
}
בדוגמה הזו, אין פעולת API בסיסית אחת שמציגה את כל המשאבים שמשתתפים בבקשה הזו, בגלל מגבלות של מנגנון הרישום ביומן והארכיטקטורה המבוזרת של BigQuery.
הרשומה ביומן הביקורת מציינת שהפעולה נכשלה כי כדי להעתיק את הנתונים, ל-BigQuery צריכה להיות גישה לפרויקט היעד (corp-resources-public) באמצעות הרשת בפרויקט perimeter-network (מקור הבקשה). זוכרים שהרכיב corp-resources-public נמצא מחוץ להיקף שמגן על perimeter-network? הבקשה נדחתה כי זו הייתה
ניסיון להעביר נתונים אל corp-resources-public.
הדוגמה הזו ממחישה שאותה פעולה קונספטואלית, כמו העתקת נתונים, יכולה להפעיל כמה ניסיונות לגשת לנתונים ממערכות אחסון שונות, כמו Cloud Storage, BigQuery ו-Bigtable. בהתאם לאופן הביצוע של הפעולה, רשומת יומן הביקורת שנוצרת שונה מהפקודה המקורית של המשתמש. בנוסף, כשמתבצעות כמה בדיקות בשירות מסוים, והן עלולות להיכשל, רשומת יומן הביקורת שנוצרת נראית שונה מהפקודה המקורית של המשתמש.
קריאת משימות של Managed Service for Apache Spark מפרויקט
בדוגמה הזו נסביר איך לנפות באגים בשגיאות עקיפות של VPC Service Controls שמתרחשות כשמשתמשים בשירותים לעיבוד נתונים כמו Managed Service for Apache Spark.
בדוגמה הזו, אשכול של Managed Service for Apache Spark פועל בפרויקט שמוגן על ידי VPC Service Controls. Hello-world.py היא משימת PySpark שמנסה לגשת לנתונים מקטגוריה של Cloud Storage בתוך ההיקף ואז לכתוב אותם לקטגוריה אחרת שנמצאת מחוץ להיקף.
VPC Service Controls חוסם את הפעולה שכותבת נתונים לדלי מחוץ לגבולות הגזרה.
הפקודה הבאה משמשת להפעלת Hello-world.py:
gcloud dataproc jobs submit pyspark hello-world.py --cluster test-cluster-new2
הפקודה מחזירה את הפלט הבא:
Job [50f16ca8-5102-442b-a545-eed5e4f5f5da] submitted.
Waiting for job output...
18/11/29 00:31:34 INFO org.spark_project.jetty.util.log: Logging initialized @2552ms
18/11/29 00:31:34 INFO org.spark_project.jetty.server.Server: jetty-9.3.z-SNAPSHOT
18/11/29 00:31:34 INFO org.spark_project.jetty.server.Server: Started @2640ms
18/11/29 00:31:34 INFO org.spark_project.jetty.server.AbstractConnector: Started ServerConnector@1f1c18ec{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
18/11/29 00:31:34 INFO com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystemBase: GHFS version: 1.6.4-hadoop2
18/11/29 00:31:35 INFO org.apache.hadoop.yarn.client.RMProxy: Connecting to ResourceManager at test-cluster-new2-m/10.246.0.3:8032
18/11/29 00:31:37 INFO org.apache.hadoop.yarn.client.api.impl.YarnClientImpl: Submitted application application_1522454176466_0005
Traceback (most recent call last):
File "/tmp/50f16ca8-5102-442b-a545-eed5e4f5f5da/hello-world.py", line 8, in <module>
lear.saveAsTextFile("gs://corp-resources-public-1/out.txt")
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 1553, in saveAsTextFile
File "/usr/lib/spark/python/lib/py4j-0.10.4-src.zip/py4j/java_gateway.py", line 1133, in __call__
File "/usr/lib/spark/python/lib/py4j-0.10.4-src.zip/py4j/protocol.py", line 319, in get_return_value
py4j.protocol.Py4JJavaError: An error occurred while calling o49.saveAsTextFile.
: java.io.IOException: Error accessing: bucket: corp-resources-public-1, object: out.txt
at com.google.cloud.hadoop.gcsio.GoogleCloudStorageImpl.wrapException(GoogleCloudStorageImpl.java:1767)
$sp(PairRDDFunctions.scala:961)
(truncated)
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Request violates VPC Service Controls.",
"reason" : "vpcServiceControls"
} ],
"message" : "Request violates VPC Service Controls."
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
(truncated)
18/11/29 00:31:43 INFO org.spark_project.jetty.server.AbstractConnector: Stopped Spark@1f1c18ec{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
ERROR: (gcloud.dataproc.jobs.submit.pyspark) Job [50f16ca8-5102-442b-a545-eed5e4f5f5da] entered state [ERROR] while waiting for [DONE].
שימו לב לחריגת ה-IO שמתרחשת כשקוראים למתודה saveAsTextFile.
Cloud Storage מחזיר שגיאה 403 עם ההודעה Request violates VPC Service Controls. השגיאה מציינת שצריך לבדוק את הפעולה ביומן הביקורת של Cloud Storage.
ביומני הביקורת של פרויקט perimeter-network, שבו בוצעה הפקודה, יש רשומה ביומן הביקורת של הפעולה saveAsTextFile:
{
insertId: "qdj1o9d1run"
logName: "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "1004338142803-compute@developer.gserviceaccount.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/_/buckets/corp-resources-public-1/objects/out.txt"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "google.storage.BillingRequiredRead"
requestMetadata: {
callerIp: "10.246.0.3"
callerNetwork: "//compute.googleapis.com/projects/corp-resources-private/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/1004338142803"
serviceName: "storage.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-29T00:31:43.666227930Z"
resource: {
labels: {
method: "google.storage.BillingRequiredRead"
project_id: "corp-resources-private"
service: "storage.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-29T00:31:43.608250320Z"
}
בגלל מגבלות ביומני הביקורת, הפעולה methodName ב-Cloud Storage מופיעה כ-Read, למרות שהיא למעשה פעולה מסוג write. הרשומה ביומן הביקורת מציינת שהפעולה נכשלה כי רשת בפרויקט corp-resources-private ניסתה לגשת לנתונים (במקרה הזה, לכתוב) של משאב בקטגוריה corp-resources-public-1. בגלל המגבלות של יומן הביקורת של Cloud Storage, לא ברור לאיזו קטגוריית פרויקט שייך corp-resources-public-1.
כדי לזהות את הפרויקט שמכיל את corp-resources-public-1, משתמשים בפקודה הבאה:
gcloud storage ls gs://corp-resources-public-1 --buckets --log-http 2>&1 | grep projectNumber
הפקודה מחזירה את הפלט הבא:
"projectNumber": "117961063178",
117961063178 הוא פרויקט corp-resources-public, שנמצא מחוץ לגבולות הגזרה.
לכן, השגיאה צפויה.
שגיאה בגלל שירותים שלא נתמכים
חלק מהשירותים של Google Cloud תלויים בשירותים אחרים של Google Cloud כחלק מההטמעה שלהם. אם נעשה שימוש בשירות לא נתמך כמו App Engine בתוך פרויקט שמוגן על ידי גבול גזרה, יכול להיות שלא תהיה גישה למשאבים של השירות.
מידע על מקרים בעייתיים ידועים מופיע במאמר מגבלות ידועות של השירות.
שירות לא נתמך עם כתובת VIP מוגבלת
ניסיון לגשת ל-API שלא נתמך על ידי ה-VIP המוגבל של VPC Service Controls יוביל לשגיאה 403. לדוגמה, VPC Service Controls לא תומך ב-App Engine, ולכן App Engine Admin API לא זמין כשמשתמשים ב-VIP המוגבל.
לדוגמה, נניח שהפקודה הבאה משמשת לרישום כל שירותי App Engine בתוך היקף שירות:
gcloud app services list
הפקודה מחזירה את אחד מהפלט הבאים:
ERROR: (gcloud.app.services.list) User [***] does not have permission to access apps instance [***] (or it may not exist): <!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 403 (Forbidden)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){ #logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){ #logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>403.</b> <ins>That's an error.</ins>
<p>Your client does not have permission to get URL <code>/v1/apps/***/services</code> from this server. <ins>That's all we know.</ins>
The service that you're trying to access isn't available on Google's Restricted VIPs. For a list of services that support VPC Service Controls, see https://cloud.google.com/vpc-service-controls/docs/supported-products.
סוג השגיאה הזה צפוי בשירותים שלא נתמכים על ידי VPC Service Controls ושלא זמינים ב-VIP המוגבל. אם השגיאה הזו מתרחשת בשירות שנתמך על ידי VPC Service Controls, מומלץ לבדוק את המגבלות הידועות של השירות כדי לראות אם מדובר במגבלה מוכרת. אחרת, צריך לדווח על הבעיה.
ייצוא יומנים לפרויקט מחוץ להיקף
בדוגמה הזו, ייצוא יומן נחסם על ידי VPC Service Controls.
יעד הייצוא, פרויקט corp-resources-public, נמצא מחוץ לגבולות הגזרה של VPC Service Controls, בעוד שמאגר הנתונים נוצר בפרויקט perimeter-network, שנמצא בתוך גבולות הגזרה.
לדוגמה, נניח שמשתמשים בפקודה הבאה:
gcloud logging sinks describe example-sink
הפקודה מחזירה את הפלט הבא:
destination: bigquery.googleapis.com/projects/corp-resources-public/datasets/logs
filter: |-
resource.type="audited_resource"
resource.labels.service="bigquery.googleapis.com"
name: example-sink
outputVersionFormat: V2
writerIdentity: serviceAccount:p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "e5i2i8cbqw"
logName: "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "corp-resources-public"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "google.cloud.bigquery.v2.TableDataService.InsertAll"
requestMetadata: {
callerIp: "2002:a49:8c51::"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/927005422713"
serviceName: "bigquery.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-11-29T17:32:19.287138882Z"
resource: {
labels: {
method: "google.cloud.bigquery.v2.TableDataService.InsertAll"
project_id: "perimeter-network"
service: "bigquery.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-11-29T17:32:19.054662413Z"
}
רשומת יומן הביקורת נוצרת עבור BigQuery, ולא עבור Logging. הסיבה לכך היא ש-BigQuery הוא שירות היעד שאליו שירות Logging מנסה לכתוב.
הייצוא נכשל כי corp-resources-public נמצא מחוץ לגבולות שמגנים על perimeter-network.
בדוגמה הזו אפשר לראות שבמקרים שבהם שירות אחד קורא לשירות אחר באמצעות חשבון שירות מנוהל שהוא פנימי ל- Google Cloud, כמו p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com, 'פרויקט הרשת' (במקרה הזה, perimeter-network) של הבקשה נגזר מהזהות הזו. Google Cloud אותו זהות מייצגת את משאב ייצוא היומן עצמו.
התבנית הזו נפוצה ב- Google Cloud והיא חלה על מקרים רבים של אינטראקציה בין שירותים.
שליפת נתונים מ-BigQuery ל-Cloud Storage
בדוגמה הזו מוסבר איך לנפות באגים בחילוצים שנכשלו מ-BigQuery ל-Cloud Storage.
בדוגמה הזו, corp-resources-private ו-perimeter-network הם פרויקטים שמוגנים על ידי גבולות גזרה לשירות. corp-resources-public הוא פרויקט שקיים מחוץ לגבולות.
נניח שהשתמשתם בפקודה הבאה:
bq extract babynames.yob2000
הפקודה מחזירה את הפלט הבא:
gs://corp-resources-public-1/export.txt
Waiting on bqjob_r47ee34109d02b41_000001676b27157c_1 ... (1s) Current status: DONE
BigQuery error in extract operation: Error processing job 'corp-resources-private:bqjob_r47ee34109d02b41_000001676b27157c_1': Access
Denied: BigQuery BigQuery: Permission denied while writing data.
במקרה הזה, השגיאה לא קשורה ספציפית ל-VPC Service Controls. שגיאה דומה מוצגת אם יש כשל בניהול הזהויות והרשאות הגישה.
נוצרת הרשומה הבאה ביומן הביקורת:
{
insertId: "4gbh6pe8jld7"
logName: "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fdata_access"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "storage-accessing@example.iam.gserviceaccount.com"
}
methodName: "jobservice.jobcompleted"
requestMetadata: {
callerIp: "10.5.0.4"
callerNetwork: "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
callerSuppliedUserAgent: "google-api-python-client/1.6.5 (gzip),gzip(gfe)"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/corp-resources-private/jobs/bqjob_r47ee34109d02b41_000001676b27157c_1"
serviceData: {
@type: "type.googleapis.com/google.cloud.bigquery.logging.v1.AuditData"
jobCompletedEvent: {
eventName: "extract_job_completed"
job: {
jobConfiguration: {
extract: {
destinationUris: [
0: "gs://corp-resources-public-1/export.txt"
]
sourceTable: {
datasetId: "babynames"
projectId: "corp-resources-private"
tableId: "yob2000"
}
}
}
jobName: {
jobId: "bqjob_r47ee34109d02b41_000001676b27157c_1"
location: "US"
projectId: "corp-resources-private"
}
jobStatistics: {
createTime: "2018-12-01T19:03:03.908Z"
endTime: "2018-12-01T19:03:05.494Z"
startTime: "2018-12-01T19:03:04.013Z"
}
jobStatus: {
additionalErrors: [
0: {
code: 7
message: "Access Denied: BigQuery BigQuery: Permission denied while writing data."
}
]
error: {
code: 7
message: "Access Denied: BigQuery BigQuery: Permission denied while writing data."
}
state: "DONE"
}
}
}
}
serviceName: "bigquery.googleapis.com"
status: {
code: 7
message: "Access Denied: BigQuery BigQuery: Permission denied while writing data."
}
}
receiveTimestamp: "2018-12-01T19:03:05.532169998Z"
resource: {
labels: {
project_id: "corp-resources-private"
}
type: "bigquery_resource"
}
severity: "ERROR"
timestamp: "2018-12-01T19:03:05.503Z"
}
ברשומה הזו ביומן הביקורת, storage-accessing@example.iam.gserviceaccount.com מזוהה כזהות שמנסה להריץ את הפעולה. בדוגמה הזו, נניח שלמשתמש storage-accessing@example.iam.gserviceaccount.com יש את הרשאות ה-IAM הנדרשות להפעלת הפקודה.
הרשאות IAM לא גורמות לבעיה, ולכן השלב הבא הוא לבדוק אם יש כשלים ב-VPC Service Controls.
רשומת יומן הביקורת של שירות היעד (Cloud Storage) מכילה סיבות מפורטות לכישלון:
{
insertId: "1bq397kcfj1"
logName: "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "storage-accessing@example.iam.gserviceaccount.com"
}
metadata: {
@type: "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
resourceNames: [
0: "projects/1004338142803"
1: "projects/_/buckets/corp-resources-public-1"
]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
}
methodName: "google.storage.BillingRequiredRead"
requestMetadata: {
callerIp: "10.5.0.4"
callerNetwork: "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/1004338142803"
serviceName: "storage.googleapis.com"
status: {
code: 7
details: [
0: {
@type: "type.googleapis.com/google.rpc.PreconditionFailure"
violations: [
0: {
type: "VPC_SERVICE_CONTROLS"
}
]
}
]
message: "Request is prohibited by organization's policy"
}
}
receiveTimestamp: "2018-12-01T19:03:05.617451586Z"
resource: {
labels: {
method: "google.storage.BillingRequiredRead"
project_id: "corp-resources-private"
service: "storage.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
timestamp: "2018-12-01T19:03:05.420005215Z"
}
מהיומן הזה ברור ששני הפרויקטים 1004338142803(corp-resources-private-1) ו-corp-resources-public משמשים להשלמת הפקודה. מכיוון שהפרויקטים האלה לא חולקים היקף, עבודת החילוץ נכשלת.
בדוגמה הזו אפשר לראות שבפעולות מורכבות שכוללות כמה שירותים, יומני הביקורת של שירותי המקור והיעד עשויים להכיל נתונים שימושיים לניפוי באגים.
גישה להיקף האבטחה דרך שער Cloud NAT
בדוגמה הזו, נניח שפרויקט א' מארגון א' לא מוגדר באף היקף. פרויקט ב' מאובטח על ידי היקף הרשאות בארגון אחר. משאבים פרטיים בפרויקט א' משתמשים בשער Cloud NAT כדי להגיע לאינטרנט ולשירותים ולממשקי ה-API של Google. רמת גישה מוגדרת בפרויקט ב' כדי לאפשר גישה על סמך כתובות ה-IP של השער החיצוני של פרויקט א'.
מכונה וירטואלית ששייכת לפרויקט א (יכול להיות שזה צומת של Google Kubernetes Engine) מנסה לגשת למשאב מוגן בפרויקט ב, אבל החיבור נכשל. בעקבות זאת, נוצר בפרויקט ב רשומה ביומן הביקורת:
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {
"code": 7,
"message": "Request is prohibited by organization's policy. vpcServiceControlsUniqueIdentifier: kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw",
"details": [
{
"@type": "type.googleapis.com/google.rpc.PreconditionFailure",
"violations": [
{
"type": "VPC_SERVICE_CONTROLS",
"description": "kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw"
}
]
}
]
},
"authenticationInfo": {
"principalEmail": "my-user@example.iam.gserviceaccount.com",
"serviceAccountKeyName": "//iam.googleapis.com/projects/my-project/serviceAccounts/my-user@example.iam.gserviceaccount.com/keys/<code><var>ACCOUNT_KEY</var></code>"
},
"requestMetadata": {
"callerIp": "gce-internal-ip",
"requestAttributes": {},
"destinationAttributes": {}
},
"serviceName": "cloudfunctions.googleapis.com",
"methodName": "google.cloud.functions.v1.CloudFunctionsService.ListFunctions",
"resourceName": "<code><var>PROJECT_ID_1</var></code>",
"metadata": {
"violationReason": "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER",
"resourceNames": [
"projects/<code><var>PROJECT_ID_2</var></code>/locations/-"
],
"securityPolicyInfo": {
"servicePerimeterName": "accessPolicies/<code><var>ACCESS_POLICY</var></code>/servicePerimeters/us_sandbox",
"organizationId": "<code><var>ORGANIZATION_ID</var></code>"
},
"deviceState": "Unknown",
"vpcServiceControlsUniqueId": "kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw",
"ingressViolations": [
{
"targetResource": "projects/<code><var>PROJECT_ID_1</var></code>",
"servicePerimeter": "accessPolicies/<code><var>ACCESS_POLICY</var></code>/servicePerimeters/<code><var>PERIMETER_NAME</var></code>",
"source": "<code><var>PROJECT_ID_2</var></code>"
}
],
"@type": "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
}
},
"insertId": "tzf7fd103i",
"resource": {
"type": "audited_resource",
"labels": {
"service": "cloudfunctions.googleapis.com",
"method": "google.cloud.functions.v1.CloudFunctionsService.ListFunctions",
"project_id": "<code><var>PROJECT_ID_2</var></code>"
}
},
"timestamp": "2024-04-02T19:56:10.770681816Z",
"severity": "ERROR",
"logName": "projects/<code><var>PROJECT_ID_2</var></code>/logs/cloudaudit.googleapis.com%2Fpolicy",
"receiveTimestamp": "2024-04-02T19:56:11.463811603Z"
}
במשאב callerIp לא מתועדת כתובת IP חיצונית. במקום כתובת ה-IP החיצונית של שער Cloud NAT, במשאב callerIp מוצגת כתובת ה-IP gce-internal-ip.
השדה callerIp מוסתר ומוצג כ-gce-internal-ip כשהבקשות מגיעות מפרויקט או מארגון אחרים, ולמכונה הווירטואלית של Compute Engine שממנה מגיעות הבקשות אין כתובת IP חיצונית.
ל-Cloud NAT יש שילוב עם גישה פרטית ל-Google, שמאפשר באופן אוטומטי גישה פרטית ל-Google ברשת המשנה של המשאב, ושומר על התנועה לממשקי API ולשירותים של Google כפנימית, במקום לנתב אותה לאינטרנט באמצעות כתובת ה-IP החיצונית של שער Cloud NAT.
במקרה הזה, התעבורה מנותבת בתוך הרשת הפנימית של Google, ולכן השדה RequestMetadata.caller_ip באובייקט AuditLog מצונזר ל-gce-internal-ip. כדי לפתור את הבעיה, במקום להשתמש בכתובת ה-IP החיצונית של שער Cloud NAT ברמת הגישה של רשימת ההיתרים מבוססת-IP, צריך להגדיר כלל תעבורת נתונים נכנסת (ingress) כדי לאפשר גישה מהפרויקט או מחשבון השירות.
המאמרים הבאים
- איך מאחזרים שגיאות של VPC Service Controls מיומני ביקורת
- כאן מוסבר איך לפתור בעיות נפוצות שקשורות לשירותים אחרים של Google Cloud .
- איך מאבחנים דחיית גישה בכלי לניתוח הפרות ואיך צופים בדוח ההערכה המקיף.