执行 lint 请求政策

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

准备工作

  • 启用 IAM API。

    启用 API

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

所需的角色

如需对资源的允许政策执行 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

要获取所需的权限,请让管理员授予您包含权限的预定义角色或自定义角色。例如,管理员可以向您授予 Security Admin 角色 (roles/iam.securityAdmin),该角色拥有获取几乎所有 Google Cloud 资源和管理其允许政策的权限。

了解适用于允许政策的 lint 请求

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

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

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

对条件执行 lint 请求

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

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

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

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

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

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

控制台

  1. 在 Google Cloud 控制台中,转到 IAM 页面。

    转到 IAM

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

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

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

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

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

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

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

  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

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

REST

iamPolicies.lintPolicy 方法可对允许政策中的条件表达式执行 lint 请求或进行验证。

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

  • 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 请求的示例

本部分介绍了导致每个验证单元报告问题的条件示例。每个示例均使用 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