执行 lint 请求政策

本主题介绍如何对 Identity and Access Management (IAM) 政策执行 lint 请求(即进行验证)。

准备工作

阅读 IAM Conditions 概览,了解 IAM Conditions 的基础知识。

了解适用于 IAM 政策的 lint 请求

在 IAM 政策的上下文中,执行 lint 请求是一种检查新政策或现有政策以及确认其是否存在特定问题的方法。这些问题有以下几种可能的类型:

  • 建议
  • 警告
  • 有助于改善政策意图的信息,比如更好的语法和语义
  • 导致 setIamPolicy 操作失败的语法或语义错误

如果您尝试更新 IAM 政策,但收到错误,对政策执行 lint 请求可帮助您找到错误的原因。您还可以使用 linter 帮助确保条件角色绑定发挥预期作用。

对条件执行 lint 请求

条件表达式可能会十分复杂,尤其是在需要多个子句和逻辑运算符来正确管理访问权限的情况下。如果条件表达式包含无效逻辑,或者语法违反了条件表达式的限制,您无法将条件添加到 IAM 政策。

此外,即使条件表达式使用正确的语法,它也可能包含语义错误,从而导致 IAM 政策和角色绑定无法发挥预期作用。常见的语义错误包括:

  • 使用不推荐的函数
  • 使用旧版资源类型或旧版服务名称
  • 无效条件,例如不适用的日期或时间范围

对条件执行 lint 请求后,linter 会检查条件表达式并报告所有语法错误。此外,它还会报告可能导致意外结果的语义错误。

在尝试设置新的条件角色绑定之前,建议您先对表达式执行 lint 请求。本部分介绍了如何使用 Cloud Console、gcloud 命令行工具或 REST API 来对条件执行 lint 请求。

要对条件表达式执行 lint 请求,请执行以下操作:

控制台

  1. 在 Cloud Console 中,转到 IAM 页面。

    转到 IAM

  2. 点击选择项目,然后选择一个项目并点击打开

  3. 从主帐号列表中,找到所需主帐号,然后点击 修改按钮。

  4. 修改权限面板中,找到想要对其执行 lint 请求的角色。然后在条件下,点击条件的名称。

  5. 条件编辑器中,手动添加或修改条件表达式。

  6. 要验证 CEL 语法,请点击运行 Linter

    如果语法包含错误,错误的行旁边会显示 错误图标。如需查看每个错误的详细信息,请将指针悬停在图标上方。

    如果条件使用了正确的语法,但 linter 发现了潜在问题,则该问题所在的行旁边会显示 警告图标。如需查看每个警告的详细信息,请将指针悬停在图标上方。

  7. 对条件表达式进行必要的更改。点击运行 Linter 后,linter 会在您修改表达式时自动在后台运行。

    您必须更正所有错误,然后才能保存条件表达式。我们强烈建议您也解决所有警告。

  8. 在没有错误或警告后,点击保存以应用条件。

  9. 关闭修改条件面板后,在修改权限面板中再次点击保存,以更新 IAM 政策。

gcloud

执行 gcloud alpha iam policies lint-condition 命令,对给定条件表达式执行 lint 请求。要执行此命令,可以创建包含该条件的文本文件,也可以为条件的标题、说明和表达式指定标志。

下面的示例使用包含以下条件的文本文件:

condition.json

{
  "condition": {
    "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

进行更改,以使表达式能够编译,然后再次对条件执行 lint 请求。

REST

iamPolicies.lintPolicy 方法 lint(验证)IAM 政策中的条件表达式。

在使用任何请求数据之前,请先进行以下替换:

  • conditionExpr 对象,表示要对其执行 lint 请求的条件。例如:

    "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 请求结果严重级别和简要说明。

验证单元 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 表达式使用的特性受限或不受支持。设置条件表达式可能会失败。请参阅特性列表

执行 lint 请求的示例

本部分提供每个验证单元的执行 lint 请求政策使用示例。 对于每个验证单元,都会提供有问题的输入示例。每个示例均使用 gcloud 命令行工具演示了执行 lint 请求的操作

ConditionCompileCheck

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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

条件表达式示例:

{
  "condition": {
    "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