בדף הזה מפורטות בעיות שונות שאפשר להיתקל בהן כשמגדירים את 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 ב-גבולות גזרה לשירות.
בקשות בין היקפים
בדרך כלל, רמות גישה משמשות כדי לאפשר בקשות ממחוץ לגבולות גזרה של שירות למשאבים מוגנים בתוך גבולות הגזרה.
עם זאת, בקשה מפרויקט בגבולות גזרה למשאב מוגן בגבולות גזרה אחר נדחית, גם אם רמת גישה מאפשרת בדרך כלל את הבקשה.
לדוגמה, נניח שבפרויקט א' בגבול גזרה 1 מתבצעת בקשה למשאב מפרויקט ב'. המשאב בפרויקט ב' מוגן על ידי גבול הגזרה 2. מכיוון שפרויקט א' נמצא בגבולות גזרה, גם אם רמת הגישה לגבולות גזרה 2 מאפשרת בדרך כלל את הבקשה למשאב המוגן, הבקשה נדחית.
כדי להקל על שליחת בקשות בין גבולות, אפשר להשתמש באחת מהגישות הבאות:
שימוש במדיניות תעבורת נתונים יוצאת (egress) ומדיניות תעבורת נתונים נכנסת (ingress). כדי לאפשר בקשות מגבולות גזרה אחרים למשאבים מוגנים בגבולות הגזרה שלכם, גבולות הגזרה האחרים צריכים להשתמש במדיניות תעבורת נתונים יוצאת (egress), ואתם צריכים להגדיר מדיניות תעבורת נתונים נכנסת (ingress) בגבולות הגזרה שלכם.
שימוש בגבולות גזרה מגושרים. גשרים מאפשרים לשני פרויקטים או יותר שנמצאים בהיקפים שונים לשלוח בקשות לכל השירותים בפרויקטים האלה. הבקשות האלה מותרות גם אם השירותים מוגנים על ידי ההיקפים המתאימים.
מוודאים שגם השירות ששולח את הבקשה וגם משאב היעד לא מוגנים על ידי גבולות הגזרה. במקרה כזה, הפעולה תצליח כי השירותים לא מוגנים.
כתובת האימייל לא תקינה או לא קיימת
כשמעדכנים היקף שמכיל חשבון משתמש שנמחק, יכול להיות שתיתקלו בשגיאה The email address is invalid or non-existent.
כדי לפתור את הבעיה, צריך להסיר את כתובת האימייל הלא תקינה מכל ההיקפים:
ייצוא כל ההיקפים בדוגמה הבאה מוצגת פקודה לייצוא רשימה של גבולות שירות בפורמט YAML:
gcloud access-context-manager perimeters list \ --policy=POLICY_NAME \ --format="json(name,title,description,perimeterType,status,spec,useExplicitDryRunSpec)" \ > my-perimeters.yaml
מסירים את כתובת האימייל הלא תקינה מהקובץ
my-perimeters.yamlושומרים אותו בשםmy-perimeters-updated.yaml.
הפרות של כללים לתעבורת נתונים נכנסת ויוצאת
יומן הביקורת מכיל מידע על הפרות של כללי תעבורת נתונים נכנסת (ingress) ותעבורת נתונים יוצאת (egress), שיעזור לכם להבין הפרות של גבולות גזרה.
הפרה של כלל לתעבורת נתונים נכנסת (ingress)
הפרה של כלל לתעבורת נתונים נכנסת מציינת שלקוח API מחוץ לגבולות הגזרה ניסה לגשת למשאב בתוך גבולות הגזרה. הבקשה נדחית על ידי גבולות גזרה לשירות כי אין כללים תואמים של תעבורת נתונים נכנסת או רמות גישה.
הפרטים הבאים מופיעים ביומן הביקורת לגבי הפרה של כלל תעבורת נתונים נכנסת (ingress):
- שם גבולות הגזרה שבהם התרחשה ההפרה של כלל תעבורת הנתונים הנכנסת (ingress).
- המשאב בתוך גבולות הגזרה שאליו לקוח ה-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"
}
]
כדי לפתור את הבעיה, צריך ליצור כלל כניסה להיקף. מידע נוסף על כללי תעבורת נתונים נכנסת (ingress) זמין במאמר הפניה לכללי תעבורת נתונים נכנסת (ingress).
הפרה של כלל לתעבורת נתונים יוצאת (egress)
הפרה של כלל יציאה ביומן הביקורת מציינת אחד מהאירועים הבאים:
- לקוח API בתוך גבולות הגזרה ניסה לגשת למשאב מחוץ לגבולות הגזרה.
- בקשת API שכוללת משאב בתוך ההיקף ומשאב מחוץ להיקף. לדוגמה, לקוח Cloud Storage שמפעיל פקודת העתקה כשקטגוריית אחסון אחת נמצאת בתוך גבולות הגזרה וקטגוריית האחסון השנייה נמצאת מחוץ לגבולות הגזרה.
גבולות גזרה לשירות דוחים את הבקשה כי אין כללים תואמים לתעבורת נתונים יוצאת (egress). הפרטים הבאים מופיעים ביומן הביקורת לגבי הפרה של כלל תעבורת נתונים יוצאת (egress):
- סוג המקור, למשל רשת או משאב.
- המקור, שהוא משאב או רשת, שגבולות הגזרה שלו נפרצו בגלל הפרת תעבורת נתונים יוצאת (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"
}
]
כדי לפתור את הבעיה, צריך ליצור כלל ליציאה עבור ההיקף. מידע נוסף על כללי תעבורת נתונים יוצאת (egress) מופיע במאמר הפניה לכללי תעבורת נתונים יוצאת (egress).
ניפוי באגים בבקשות שנחסמו על ידי VPC Service Controls
יומן הביקורת של VPC Service Controls הוא הכלי העיקרי לניפוי באגים בבקשה שנחסמה על ידי VPC Service Controls.
אם הגישה נחסמה באופן לא צפוי, כדאי לעיין ביומני הביקורת בפרויקט שמוגן על ידי גבולות גזרה לשירות. היומנים האלה מכילים נתונים חשובים על המשאבים המבוקשים ועל הסיבה לדחיית הבקשה. מידע על אבחון יומני הביקורת מופיע במאמר גישה לכלי לניתוח הפרות.
בקטעים הבאים מפורטים הערכים של violationReason שאולי תיתקלו בהם כשמשתמשים ב-VPC Service Controls.
NETWORK_NOT_IN_SAME_SERVICE_PERIMETER
הסיבות האפשריות לבעיה הזו:
- לקוח ברשת VPC בתוך גבולות גזרה לשירות מנסה לגשת לפרויקט שלא נמצא באותם גבולות גזרה. הבקשה הזו גורמת להפרה של תעבורת נתונים יוצאת (egress). כדי לפתור את הבעיה, צריך ליצור כלל ליציאה.
- לקוח ברשת VPC שנמצאת מחוץ לגבולות גזרה לשירות מנסה לגשת לפרויקט שמוגן על ידי גבולות גזרה לשירות. הבקשה הזו גורמת להפרת Ingress. כדי לפתור את הבעיה הזו, צריך ליצור כלל תעבורת נתונים נכנסת (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>הוא השם של גבולות גזרה לשירות. -
<NETWORK_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את רשת ה-VPC. -
<RESOURCE_PROJECT_NUMBER>הוא מספר הפרויקט של Google Cloud הפרויקט שמכיל את המשאב.
בתרשים הבא אפשר לראות שמתרחשת הפרה של תעבורת נתונים נכנסת (ingress) כשלקוח מחוץ לגבולות גזרה מנסה לגשת לפרויקט בתוך גבולות גזרה:

דוגמה להפרה של כללי הכניסה:
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>הוא השם של גבולות גזרה לשירות.
רזולוציה
כדי לפתור את השגיאה הזו, צריך ליצור כלל תעבורת נתונים נכנסת (ingress) או תעבורת נתונים יוצאת (egress) עבור גבולות הגזרה.
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>הוא השם של גבולות גזרה לשירות. -
<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 מנסה לגשת לשירות מוגן ונכשל, כצפוי.
כדי לפתור את הבעיה הזו, מומלץ ליצור כלל Ingress במקום רמת גישה, כי כלל Ingress מספק בקרת גישה מפורטת.
בתרשים הבא מוצג לקוח שמנסה לגשת למשאבים מחוץ לגבולות גזרה:

דוגמה להפרה של כללי הכניסה:
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>הוא השם של גבולות גזרה לשירות.
שימו לב שבמקרה הזה, יכול להיות שהערך metadata.accessLevels עדיין יופיע כי יכול להיות שרמות הגישה האלה לא צוינו בגבולות הגזרה שהופרו.
SERVICE_NOT_ALLOWED_FROM_VPC
הבעיה הזו מתרחשת כשלקוח מנסה לגשת למשאבים מרשת VPC. Google Cloud הלקוח יכול לשלוח את הבקשה ממכונת VM ב-Compute Engine או ב-Google Kubernetes Engine, או מרשת מקומית דרך Cloud Interconnect או VPN שהוגדר באמצעות רשת VPC.
כדי לפתור את הבעיה, צריך לוודא שהשירות שאליו מתבצעת הקריאה מותר בהגדרה VPC accessible services של גבול הגזרה לשירות.
תרחישים לדוגמה
בדוגמאות הבאות מוסבר על בעיות שאולי תיתקלו בהן במהלך השימוש ב-VPC Service Controls.
- גישה ל-Cloud Storage משרת מקומי
- גישה ל-BigQuery ממכונה וירטואלית מחוץ לפרויקט
- שאילתת BigQuery בין פרויקטים
- העברת קובץ Cloud Storage בתוך ההיקף
- העברת קובץ Cloud Storage אל מחוץ לגבולות גזרה
- העתקה של מערך נתונים ב-BigQuery ממכונה וירטואלית בתוך ההיקף
- קריאת משימה של Dataproc מפרויקט
- שירות לא נתמך עם כתובת 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"
}
בדוגמה הזו, יומן הביקורת מציין שאי אפשר להעתיק נתונים מעבר לגבול של גבולות גזרה לשירות (שני המשאבים מופיעים ברשומה ביומן הביקורת).
חשוב לזכור שהבקשה מגיעה מחוץ לגבולות גזרה (ה-VM ב-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. בהתאם לאופן הביצוע של הפעולה, רשומת יומן הביקורת שנוצרת שונה מהפקודה המקורית של המשתמש. בנוסף, כשמתבצעות כמה בדיקות בשירות מסוים, והן עלולות להיכשל, רשומת יומן הביקורת שנוצרת נראית שונה מהפקודה המקורית של המשתמש.
קריאת משימה ב-Dataproc מפרויקט
בדוגמה הזו מוסבר איך לנפות באגים בשגיאות עקיפות של VPC Service Controls שמתרחשות כשמשתמשים בשירותי עיבוד נתונים כמו Dataproc.
בדוגמה הזו, אשכול Dataproc פועל בפרויקט שמוגן על ידי 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>
סוג השגיאה הזה צפוי בשירותים שלא נתמכים על ידי 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 כדי להגיע לאינטרנט ולשירותים ול-Google APIs. רמת גישה מוגדרת בפרויקט ב' כדי לאפשר גישה על סמך כתובות ה-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 ברשת המשנה של המשאב, ושומר על התנועה ל-Google APIs ולשירותים של Google כפנימית, במקום לנתב אותה לאינטרנט באמצעות כתובת ה-IP החיצונית של שער Cloud NAT.
במקרה כזה, מכיוון שתעבורת הנתונים מנותבת בתוך הרשת הפנימית של Google, השדה RequestMetadata.caller_ip באובייקט AuditLog מצונזר ל-gce-internal-ip. כדי לפתור את הבעיה, במקום להשתמש בכתובת ה-IP החיצונית של שער Cloud NAT ברמת הגישה של רשימת ההיתרים מבוססת-IP, צריך להגדיר כלל תעבורת נתונים נכנסת (ingress) כדי לאפשר גישה מהפרויקט או מחשבון השירות.
המאמרים הבאים
- איך מאחזרים שגיאות של VPC Service Controls מיומני ביקורת
- כאן מוסבר איך לפתור בעיות נפוצות שקשורות לשירותים אחרים של Google Cloud .
- איך מאבחנים דחיית גישה בכלי לניתוח הפרות ואיך צופים בדוח ההערכה המקיף.