程式碼檢查政策

本主題說明如何檢查或驗證身分與存取權管理 (IAM) 允許政策。

事前準備

  • Enable the IAM API.

    Enable the API

  • 請參閱 IAM 條件總覽,瞭解 IAM 條件的基本概念。

必要的角色

如要對資源的允許政策執行 Lint 作業,您需要取得資源的權限,以及取得和設定資源允許政策的權限。這些權限的格式如下,其中 SERVICE 是擁有資源的服務名稱,RESOURCE_TYPE 則是您要管理存取權的資源類型名稱:

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

舉例來說,如要對專案的允許政策執行 Lint 檢查,您需要下列權限:

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

如要取得必要權限,請要求管理員授予包含這些權限的預先定義或自訂角色。舉例來說,管理員可以授予您安全管理員角色 (roles/iam.securityAdmin),讓您有權取得幾乎所有Google Cloud 資源,並管理這些資源的允許政策。

瞭解允許政策的 Linting

就允許政策而言,Linting 是檢查新政策或現有政策,並找出特定問題的方法。這類問題包括下列可能性:

  • 建議
  • 警告
  • 有助於改善允許政策意圖的資訊,例如更完善的語法和語意
  • 導致 setIamPolicy 作業失敗的語法或語意錯誤

如果嘗試更新允許政策時發生錯誤,可以對允許政策執行 Lint 作業,找出錯誤原因。您也可以使用 Lint,確保條件式角色繫結能達到預期效果。

檢查條件

條件運算式可能很複雜,尤其是在需要多個子句和邏輯運算子才能適當管理存取權的情況下。如果條件運算式含有無效邏輯,或語法違反條件運算式的限制,您就無法將條件新增至允許政策。

此外,即使條件運算式使用正確的語法,也可能包含語意錯誤,導致允許政策和角色繫結無法正常運作。常見的語意錯誤包括:

  • 使用不建議的函式
  • 使用舊版資源類型或舊版服務名稱
  • 條件無效,例如日期或時間範圍不適用

對條件執行 Lint 時,Lint 工具會檢查條件運算式,並回報任何語法錯誤。此外,也會回報可能導致非預期結果的語意錯誤。

嘗試設定新的條件式角色繫結前,建議您先檢查運算式。本節說明如何使用 Google Cloud 控制台、Google Cloud CLI 或 REST API,對條件運算式執行 Lint 檢查。

如要對條件運算式執行 Lint 檢查,請按照下列步驟操作:

控制台

  1. 前往 Google Cloud 控制台的「IAM」(身分與存取權管理) 頁面。

    前往「IAM」頁面

  2. 按一下 [選取專案],選擇專案,然後按一下 [開啟]

  3. 在主體清單中找出所需主體,然後按一下「編輯」按鈕。

  4. 在「編輯權限」面板中,找出要進行 Lint 檢查的角色。然後在「IAM 條件 (選用)」下方,按一下條件名稱。

  5. 條件編輯器中,手動新增或編輯條件運算式。

  6. 如要驗證 CEL 語法,請按一下「執行 Linter」

    如果語法有誤,錯誤行旁邊會顯示 「錯誤」圖示。如要查看各項錯誤的詳細資料,請將指標懸停在圖示上。

    如果條件使用正確語法,但 Lint 發現可能的問題,有問題的行旁會顯示 「警告」圖示。如要查看每項警告的詳細資料,請將指標懸停在圖示上。

  7. 視需要變更條件運算式。按一下「執行 Linter」後,系統就會在背景自動執行 Linter,方便您編輯運算式。

    你必須先修正所有錯誤,才能儲存條件運算式。我們強烈建議您修正所有警告。

  8. 如果沒有錯誤或警告,請按一下「儲存」套用條件。

  9. 關閉「編輯條件」面板後,再次按一下「編輯權限」面板中的「儲存」,即可更新允許政策。

gcloud

執行 gcloud alpha iam policies lint-condition 指令,對指定條件運算式執行 Lint 檢查。如要執行這項指令,您可以建立包含條件的文字檔,或是指定條件標題、說明和運算式的旗標。

以下範例使用包含下列條件的文字檔:

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
...

每個 Lint 結果都包含 debugMessage,可用於找出條件運算式中的問題。如果條件無法編譯,您可能會看到許多不同的 validationUnitName 類型,並顯示以下 debugMessage 文字:

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

請進行變更,讓運算式能夠編譯,然後再次檢查條件。

REST

iamPolicies.lintPolicy 方法會檢查或驗證允許政策中的條件運算式。

使用任何要求資料之前,請先替換以下項目:

  • condition:代表要檢查的條件的 Expr 物件。例如:

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

    如要瞭解 Expr 物件的格式,請參閱Expr 結構定義參考資料

HTTP 方法和網址:

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"
  }
}

每個 Lint 結果都包含 debug_message,可用於找出條件運算式中的問題。如果條件無法編譯,您可能會看到許多不同的 validation_unit_name 類型,並顯示下列 debugMessage 文字:

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

請進行變更,讓運算式能夠編譯,然後再次檢查條件。

支援的驗證單位

如先前所述,驗證單元是個別的 Lint 類型,可評估運算式是否有語法問題。下表彙整了支援的驗證單元,每個單元都有預期的 Lint 級別、Lint 結果嚴重程度和簡短說明。

驗證單位 Lint 層級 嚴重性 說明
ConditionCompileCheck CONDITION ERROR 條件運算式含有編譯錯誤,原因是 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 執行 Lint 檢查。

沒有驗證問題

條件範例:

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

執行下列指令:

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

Lint 結果:

{}

ConditionCompileCheck

條件範例:

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

執行下列指令:

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

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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"

Lint 結果:

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