איתור שגיאות בקוד (linting) של מדיניות

בנושא הזה נסביר איך לאתר שגיאות בקוד (lint) או איך מתקפים את מדיניות ההרשאות של ניהול זהויות והרשאות גישה (IAM).

לפני שמתחילים

  • מפעילים את IAM API.

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    להפעלת ה-API

  • במאמר סקירה כללית על התנאים ב-IAM תוכלו למצוא הסבר לגבי העקרונות הבסיסיים של התנאים ב-IAM והשימוש בהם.

התפקידים הנדרשים

כדי שתוכלו לאתר שגיאות בקוד של מדיניות ההרשאות של המשאב, נדרשות הרשאות כדי לקבל את המשאב וכן הרשאות כדי לקבל ולהגדיר את כללי מדיניות ההרשאות שלו. ההרשאות האלה מופיעות בפורמט הבא, כאשר SERVICE הוא השם של השירות שהמשאב נמצא בבעלותו ו-RESOURCE_TYPE הוא השם של סוג המשאב שרוצים לנהל את הגישה אליו:

  • SERVICE.RESOURCE_TYPE.get
  • SERVICE.RESOURCE_TYPE.getIamPolicy
  • SERVICE.RESOURCE_TYPE.setIamPolicy

לדוגמה, כדי לאתר שגיאות בקוד של מדיניות ההרשאות של פרויקט, נדרשות ההרשאות הבאות:

  • resourcemanager.projects.get
  • resourcemanager.projects.getIamPolicy
  • resourcemanager.projects.setIamPolicy

כדי לקבל את ההרשאות הנדרשות, אתם צריכים לבקש מהאדמין להקצות לכם תפקיד מוגדר מראש או תפקיד מותאם אישית שכולל את ההרשאות. לדוגמה, האדמין יכול לתת לכם את התפקיד אדמין לענייני אבטחה (roles/iam.securityAdmin), שכולל הרשאות גישה כמעט לכל המשאבים שלCloud de Confiance ולניהול מדיניות ההרשאות שלהם.

הסבר על איתור שגיאות בקוד (linting) של מדיניות הרשאות

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

  • הצעות
  • אזהרות
  • מידע שיכול לעזור לדייק את הכוונה של מדיניות ההרשאות, למשל, תחביר או סמנטיקה טובים יותר
  • שגיאות סמנטיות או בעיות בתחביר שיגרמו לפעולות setIamPolicy להיכשל

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

איתור שגיאות בקוד (linting) של תנאי

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

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

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

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

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

כדי לאתר שגיאות בקוד בביטוי של תנאי:

המסוף

  1. נכנסים לדף IAM במסוף Cloud de Confiance .

    כניסה לדף IAM

  2. לוחצים על Select a project, בוחרים את הפרויקט ולוחצים על Open.

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

  4. בחלונית Edit permissions מאתרים את התפקיד שרוצים לאתר בו שגיאות בקוד. לאחר מכן, בקטע IAM condition (optional) לוחצים על שם התנאי.

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

  6. כדי לאמת את תחביר ה-CEL, לוחצים על Run Linter.

    אם בתחביר יש שגיאות, מופיע הסמל Error ליד השורה השגויה. כדי לראות פרטים לגבי כל שגיאה, מעבירים את הסמן מעל לסמל.

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

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

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

  8. כשאין יותר שגיאות או אזהרות, לוחצים על Save כדי להחיל את התנאי.

  9. לאחר שהחלונית Edit condition נסגרת, לוחצים שוב על Save בחלונית Edit permissions כדי לעדכן את מדיניות ההרשאות.

gcloud

כדי לאתר שגיאות בקוד של ביטוי נתון של תנאי, מפעילים את הפקודה gcloud alpha iam policies lint-condition. כדי להעביר את התנאי לפקודה הזו בזמן ההפעלה אתם יכולים ליצור קובץ טקסט שמכיל את התנאי או לציין דגלים לכותרת של התנאי, לתיאור שלו ולביטוי התנאי עצמו.

הדוגמה הבאה משתמשת בקובץ טקסט שמכיל את התנאי הבא:

condition.json

{
  "title": "1_less_than_2",
  "description": "",
  "expression": "1 <"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

בפלט של הפקודה:

lintResults:
- debugMessage: |-
    ERROR: Parse expression:1:3: mismatched input '<EOF>' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}
      | 1 >
      | ...^
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 3
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionCompileCheck
...

כל אחת מהתוצאות של איתור השגיאות בקוד מכילה שדה debugMessage שיכול לעזור לאתר את הבעיה שקיימת בביטוי של התנאי. אם התנאי לא הצליח לעבור הידור (compile), יכול להיות שתראו סוגים שונים של validationUnitName עם הטקסט הבא בשדה debugMessage:

The validation unit is skipped due to absence of a required object: CheckedExpr

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

REST

ה-‎method iamPolicies.lintPolicy מאתר שגיאות או מאמת ביטוי של תנאי במדיניות הרשאות.

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

  • condition: אובייקט מסוג Expr שמייצג את התנאי שצריך לבדוק. לדוגמה:

    "title": "1_less_than_2",
    "description": "",
    "expression": "1 <"

    למידע נוסף על הפורמט של אובייקט Expr, עיינו בחומר העזר על סכימות של Expr.

שיטת ה-HTTP וכתובת ה-URL:

POST https://iam.googleapis.com/v1/iamPolicies:lintPolicy

תוכן בקשת JSON:

{
  "condition": {
    condition
  }
}

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

גוף התשובה מכיל אובייקט LintResult אחד או יותר, למשל:

{
  "lint_results": {
    "level": "CONDITION",
    "validation_unit_name": "LintValidationUnits/ConditionCompileCheck",
    "severity": "ERROR",
    "field_name": "condition.expression",
    "location_offset": "2",
    "debug_message": "ERROR: Parse expression:1:2: mismatched input \'<EOF>\' expecting {\'[\', \'{\', \'(\', \'.\', \'-\', \'!\', \'true\', \'false\', \'null\', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}\n  | 1<\n  | ..^"
  },
  "lint_results": {
    "level": "CONDITION",
    "validation_unit_name": "LintValidationUnits/ConditionComplexityCheck",
    "severity": "NOTICE",
    "field_name": "condition.expression",
    "debug_message": "The validation unit is skipped due to absence of a required object: CheckedExpr"
  }
}

כל אחת מהתוצאות של איתור השגיאות בקוד מכילה שדה debug_message שיכול לעזור לאתר את הבעיה שקיימת בביטוי של התנאי. אם התנאי לא הצליח לעבור הידור (compile), יכול להיות שתראו סוגים שונים של validation_unit_name עם הטקסט הבא בשדה debugMessage:

The validation unit is skipped due to absence of a required object: CheckedExpr

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

יחידות אימות נתמכות

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

יחידת אימות רמת אימות השגיאות בקוד רמת החומרה תיאור
ConditionCompileCheck CONDITION ERROR ביטוי התנאי מכיל שגיאת הידור (compilation) כתוצאה מתחביר CEL לא חוקי.
ConditionComplexityCheck CONDITION ERROR ביטוי התנאי מכיל יותר מהמגבלה של 12 אופרטורים לוגיים.
DateTimeCheck CONDITION WARNING

ביטוי התנאי מכיל השוואת חותמות זמן שהתוצאה שתמיד מחזירות את אותה התוצאה (TRUE או FALSE), בגלל אחת מהבעיות הבאות:

DateTimeRangeCheck CONDITION WARNING ערך מחוץ לטווח של הפונקציה המתקדמת המיועדת של חותמת הזמן וביטוי ההשוואה. לרשימת הערכים החוקיים של פונקציות מתקדמות של חותמת זמן
DrgGetAttributeDefaultValueCheck CONDITION ERROR ביטוי התנאי קורא לפונקציה api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', V), כאשר V הוא כל ערך מלבד רשימה ריקה, []. לצורך מאפיין ה-API הזה, הערך של V חייב תמיד להכיל רשימה ריקה.
EffectiveTimeRangeCheck CONDITION WARNING כשמשתמשים בפונקציות של חותמת הזמן ובהשוואה של חותמות זמן באופן מורכב, התוצאה של הביטוי בפועל תיצור טווח זמן ריק ולכן התוצאה בפועל תהיה תמיד FALSE. לחלופין, טווח הזמן מכסה טווח מלא ולכן התוצאה בפועל תהיה תמיד TRUE.
HasOnlyListConstCheck CONDITION ERROR ביטוי התנאי קורא לפונקציה hasOnly(List<T>), כאשר המאפיין T אינו מסוג קבוע, כמו מחרוזת או מספר שלם. הפונקציה hasOnly() מקבלת רק רשימה של משתנים קבועים.
HasOnlyListLengthCheck CONDITION ERROR ביטוי התנאי קורא לפונקציה hasOnly(List<T>) כאשר המאפיין List<T> מכיל יותר מהמגבלה של 10 רכיבים.
ResourceServiceLiteralCheck CONDITION WARNING הערך שצוין במאפיין resource.service לא נתמך. כשמשתמשים בליטרל מחרוזת כזה לביטוי של בדיקת שוויון, התוצאה בפועל תהיה תמיד FALSE. עליכם להשתמש באחד מהערכים הנתמכים.
ResourceTypeLiteralCheck CONDITION WARNING הערך שצוין במאפיין resource.type לא נתמך. כשמשתמשים בליטרל מחרוזת כזה לביטוי של בדיקת שוויון, התוצאה בפועל תהיה תמיד FALSE. עליכם להשתמש באחד מהערכים הנתמכים.
RestrictedAttributesCheck CONDITION WARNING הביטוי משתמש במאפיין שמוגבל או לא נתמך. יכול להיות שההגדרה של ביטוי התנאי תיכשל. לרשימת המאפיינים

דוגמאות לאיתור שגיאות בקוד (linting)

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

אין בעיות באימות

תנאי לדוגמה:

{
  "title": "1_less_than_2",
  "description": "",
  "expression": "1 < 2"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

{}

הבדיקה: ConditionCompileCheck

תנאי לדוגמה:

{
  "title": "Condition not compiling",
  "description": "",
  "expression": "true=false"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: |-
    ERROR: Parse expression:1:4: token recognition error at: '=f'
      | true=false
      | ....^
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 4
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionCompileCheck

הבדיקה: ConditionComplexityCheck

תנאי לדוגמה:

{
  "title": "Condition not compiling",
  "description": "",
  "expression":
    "1<2 || 2<3 || 3<4 || 4<5 || 5<6 || 6<7 || 7<8 || 8<9 || 9<10 || 10<11 || 11<12 || 12<13 || 13<14 || 14<15"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: Logical operators count must not be more than 12
  fieldName: condition.expression
  level: CONDITION
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionComplexityCheck

הבדיקה: DateTimeCheck

תנאי לדוגמה:

{
  "title": "Condition not compiling",
  "description": "",
  "expression": "request.time < timestamp('2000-01-01T00:00:00Z')"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: Ineffective date time value 2000-01-01T00:00:00+00:00 parsed
    from "2000-01-01T00:00:00Z"; condition is effectively False. Time expired
    already.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 25
  severity: WARNING
  validationUnitName: LintValidationUnits/DateTimeCheck

הבדיקה: DateTimeRangeCheck

תנאי לדוגמה:

{
  "title": "Time function out of range",
  "description": "",
  "expression": "request.time.getMonth() > 13"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: The value being compared to the specified timestamp function
    (getMonth) must be in range [0, 11].
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 26
  severity: WARNING
  validationUnitName: LintValidationUnits/DateTimeRangeCheck

הבדיקה: DrgGetAttributeDefaultValueCheck

תנאי לדוגמה:

{
  "title": "DRG condition takes non empty list as default value",
  "description": "",
  "expression":
    "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', ['roles/viewer']).hasOnly(['roles/editor'])"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: api.getAttribute call on
    'iam.googleapis.com/modifiedGrantsByRole' can only
    accept empty list ('[]') as default value.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 60
  severity: ERROR
  validationUnitName: LintValidationUnits/DrgGetAttributeDefaultValueCheck

הבדיקה: EffectiveTimeRangeCheck

תנאי לדוגמה:

{
  "title": "Empty time range",
  "description": "",
  "expression": "request.time.getMonth() > 5 && request.time.getMonth() < 4"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: The aggregate of time functions [getMonth] results in empty ranges.
  fieldName: condition.expression
  level: CONDITION
  severity: WARNING
  validationUnitName: LintValidationUnits/EffectiveTimeRangeCheck

הבדיקה: HasOnlyListConstCheck

תנאי לדוגמה:

{
  "title": "hasOnly contains more than constant value",
  "description": "",
  "expression":
    "api.getAttribute('somekey', []).hasOnly(['somevalue', resource.name])"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: hasOnly() expects an argument of type list containing only const
      values, but a non-const expression was found in the list.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 59
  severity: ERROR
  validationUnitName: LintValidationUnits/HasOnlyListConstCheck

הבדיקה: HasOnlyListLengthCheck

תנאי לדוגמה:

{
  "title": "hasOnly contains more than 10 elements",
  "description": "",
  "expression":
    "api.getAttribute('somekey', []).hasOnly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: The list argument to hasOnly() cannot have more than 10 elements
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 39
  severity: ERROR
  validationUnitName: LintValidationUnits/HasOnlyListLengthCheck

הבדיקה: ResourceServiceLiteralCheck

תנאי לדוגמה:

{
  "title": "Condition with unsupported resource service string",
  "description": "",
  "expression": "resource.service == 'resourcemanager'"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: 'resource.service : resourcemanager is not supported. Using this
    value in condition may lead to unintended consequences. Check user guide at
    https://cloud.google.com/iam/docs/conditions-resource-attributes#resource_service_values
    for supported values for resource.service.'
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 20
  severity: WARNING
  validationUnitName: LintValidationUnits/ResourceServiceLiteralCheck

הבדיקה: ResourceTypeLiteralCheck

תנאי לדוגמה:

{
  "title": "Condition with legacy resource type",
  "description": "",
  "expression": "resource.type == 'resourcemanager.projects'"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: 'resource.type : resourcemanager.projects is not supported.
    Using this value in condition may lead to unintended consequences. Check
    user guide at https://cloud.google.com/iam/docs/conditions-resource-attributes#resource_type_values
    for supported values for resource.type.'
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 17
  severity: WARNING
  validationUnitName: LintValidationUnits/ResourceTypeLiteralCheck

הבדיקה: RestrictedAttributesCheck

תנאי לדוגמה:

{
  "title": "Condition with restricted attribute",
  "description": "",
  "expression": "'accessPolicies/123/accesslevels/TRUSTED' in request.auth.access_levels"
}

הפעלת הפקודה:

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

התוצאה של איתור השגיאות בקוד:

lintResults:
- debugMessage: Condition attribute `request.auth.access_levels` is restricted
    or unsupported. Please check https://cloud.google.com/iam/docs/conditions-overview
    for the full list of supported attributes
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 57
  severity: WARNING
  validationUnitName: LintValidationUnits/RestrictedAttributesCheck