对 Security Health Analytics 的自定义模块进行编码

本页介绍了如何使用通用表达式语言 (CEL)YAML 对自定义模块定义进行编码。

您可以使用 Google Cloud CLI 将自定义模块定义上传到 Security Health Analytics。

在 YAML 文件中,自定义模块定义由一组结构化属性组成,您可以使用这些属性来定义 Security Health Analytics 自定义模块的以下元素:

  • 要扫描的资源。
  • 要使用的检测逻辑。
  • 要向安全团队提供的信息,以便他们快速了解、分类和解决检测到的问题。

编码步骤中介绍了构成 YAML 定义的特定必需属性和可选属性。

避免创建冗余的检测器

如需控制发现结果数量,请避免创建和运行包含冗余功能的模块。

例如,如果您创建了一个自定义模块,用于检查 30 天后未轮替的加密密钥,请考虑停用内置的 Security Health Analytics 检测器 KMS_KEY_NOT_ROTATED,因为其检查使用值 90 天,这是多余的。

如需详细了解如何停用检测器,请参阅启用和停用检测器

编码步骤

您可以将 Security Health Analytics 的自定义模块定义编码为一系列 YAML 属性,其中一些属性包含 CEL 表达式。

如需对自定义定义模块进行编码,请按照以下步骤操作:

  1. 创建一个文件扩展名为 yaml 的文本文件。

  2. 在该文本文件中,创建 resource_selector 属性并指定要扫描的自定义模块的资源类型(一到五个)。在自定义模块定义中,资源类型不能重复指定。例如:

    resource_selector:
     resource_types:
     ‐ cloudkms.googleapis.com/CryptoKey

    您指定的资源类型必须受 Security Command Center 支持。如需查看支持的资源类型列表,请参阅支持的资源类型

  3. 创建 predicate 属性,并指定一个或多个用于检查要扫描的资源类型的属性的 CEL 表达式。您在 CEL 表达式中引用的任何属性都必须存在于您在 resource_selector 下指定的每个资源类型的 Google Cloud API 定义中。如需触发发现结果,表达式必须解析为 TRUE。例如,在以下表达式中,只有大于 2592000srotationPeriod 值会触发发现。

    predicate:
     expression: resource.rotationPeriod > duration("2592000s")

    如需有关编写 CEL 表达式的帮助,请参阅以下资源:

  4. 创建 description 属性,以说明自定义模块检测到的漏洞或配置错误。此说明会显示在每个发现结果实例中,以帮助调查人员了解检测到的问题。文本必须用英文引号括起来。例如:

    description: "The rotation period of
     the identified cryptokey resource exceeds 30 days, the
     maximum rotation period that our security guidelines allow."
  5. 创建 recommendation 属性,以说明如何解决检测到的问题。gcloud CLI 要求在某些字符(例如英文引号)之前使用转义字符。以下示例展示了如何使用反斜杠转义每组英文引号:

    recommendation: "To fix this issue go to
      https://console.cloud.google.com/security/kms. Click the key-ring that
      contains the key. Click the key. Click \"Edit rotation period\". Then
      set the rotation period to at most 30 days."
    

    如果您使用 Google Cloud 控制台创建或更新自定义模块,则无需转义字符。

  6. 创建 severity 属性,并为此模块创建的发现指定默认严重程度。severity 属性的常用值包括 LOWMEDIUMHIGHCRITICAL。例如:

    severity: MEDIUM
  7. (可选)创建 custom_output 属性并指定要随每个发现结果一起返回的详细信息。以一个或多个名称-值对形式指定要返回的信息。 您可以返回扫描的资源的属性值或字面量字符串。属性必须指定为 resource.PROPERTY_NAME。字面量字符串必须用英文引号括起来。以下示例展示了一个 custom_output 定义,该定义会返回属性值(即扫描的 CryptoKey 资源中 rotationPeriod 的值)和文本字符串 "Excessive rotation period for CryptoKey"

     custom_output:
       properties:
         - name: duration
           value_expression:
             expression: resource.rotationPeriod
         - name: note
           value_expression:
             expression: "Excessive rotation period for CryptoKey"
    
  8. 将文件保存到 gcloud CLI 可以访问的位置。

  9. 使用以下命令将定义上传到 Security Health Analytics:

     gcloud scc custom-modules sha create \
         --organization=organizations/ORGANIZATION_ID \
         --display-name="MODULE_DISPLAY_NAME" \
         --enablement-state="ENABLED" \
         --custom-config-from-file=DEFINITION_FILE_NAME.yaml
    

    替换以下值:

    • ORGANIZATION_ID 替换为自定义模块的父级组织的 ID,或将 --organization 标志替换为 --folders--project 并指定父级文件夹或项目的 ID。
    • MODULE_DISPLAY_NAME 替换为自定义模块返回发现结果时显示为发现结果类别的名称。该名称必须介于 1 到 128 个字符之间,以小写字母开头,并且只能包含字母数字字符或下划线。
    • DEFINITION_FILE_NAME 替换为包含自定义模块定义的 YAML 文件的路径和文件名称。

    如需详细了解如何使用 Security Health Analytics 自定义模块,请参阅使用 Security Health Analytics 的自定义模块

新的自定义模块的扫描延迟时间

创建自定义模块不会触发新扫描。

除非以下任一情况,否则 Security Health Analytics 不会开始使用新的自定义模块:

  • 创建自定义模块后首次进行批量扫描。根据您按批量扫描时间表创建自定义模块的时间,您最长可能需要等待 24 小时,Security Health Analytics 才会开始使用该自定义模块。
  • 对目标资源的更改触发实时扫描。

自定义模块定义示例

以下示例展示了一个已完成的自定义模块定义,该定义会在 cloudkms.googleapis.com/CryptoKey 资源的 rotationPeriod 属性值超过 2,592,000 秒(30 天)时触发发现结果。该示例会在 custom_output 部分返回两个可选值:resource.rotationPeriod 的值和作为文本字符串的备注。

在此示例中,请注意以下元素:

  • 要检查的资产或资源类型列在 resource_selector 部分中的 resource_types 下方。
  • 模块对资源执行的检查(其检测逻辑)expression 前面的 predicate 部分中定义。
  • 两个自定义来源属性 durationviolationcustom_output 部分中定义。
  • description 属性中指定了检测到的问题的说明。
  • 有关修复检测到的问题的指导信息在 recommendation 属性中指定。由于指导信息中显示英文引号,因此每个英文引号前面都需要使用反斜杠转义字符。
severity: HIGH
description: "Regular key rotation helps provide protection against
compromised keys, and limits the number of encrypted messages available
to cryptanalysis for a specific key version."
recommendation: "To fix this issue go to
https://console.cloud.google.com/security/kms. Click the key-ring that
contains the key. Click the key. Click \"Edit rotation period\". Then
set the rotation period to at most 30 days."
resource_selector:
  resource_types:
  - cloudkms.googleapis.com/CryptoKey
predicate:
  expression: resource.rotationPeriod > duration("2592000s")
custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.rotationPeriod
    - name: violation
      value_expression:
        expression:
          "Excessive rotation period for CryptoKey"

在自定义模块中引用资源和政策属性

无论您使用哪种方法(使用 Google Cloud 控制台或通过自行编写定义)创建自定义模块,您都需要能够查找您可以在自定义模块中评估的属性。您还需要了解如何在自定义模块定义中引用这些属性。

查找资源或政策的属性

Google Cloud 资源的属性在该资源的 API 定义中定义。您可以通过点击支持的资源类型上的资源名称来找到此定义。

您可以在 IAM API 参考文档中找到政策的属性。如需了解政策的属性,请参阅政策

在自定义模块定义中引用资源属性

创建自定义模块时,对扫描的资源的属性的所有直接引用都必须以 resource 开头,后跟任何父级属性,最后是目标属性。这些属性用英文句点分隔,采用 JSON 样式的点表示法。

下面是资源属性及其检索方式的示例:

  • resourceName:在 Cloud Asset Inventory 中存储资源的完整名称,例如 //cloudresourcemanager.googleapis.com/projects/296605646631
  • resource.rotationPeriod:其中 rotationPeriodresource 的属性。
  • resource.metadata.name:其中 namemetadata 的子属性,后者是 resource 的子属性。

引用 IAM 政策属性

您可以创建 CEL 表达式,通过引用资源的 IAM 政策属性来评估资源的 IAM 政策。可用的属性只有绑定和绑定中的角色。

引用 IAM 政策属性时,policy 是顶级属性。

下面是 IAM 政策属性及其检索方式的示例:

  • policy.bindings,其中 bindingspolicy 的属性。
  • policy.version,其中 versionpolicy 的属性。

如需查看更多示例,请参阅 CEL 表达式示例

如需了解政策的属性,请参阅政策

编写 CEL 表达式

创建自定义模块时,您可以使用 CEL 表达式来评估扫描的资源的属性。(可选)您还可以使用 CEL 表达式来定义自定义 name-value 对,以随发现结果一起返回详细信息。

无论您是在 Google Cloud 控制台中创建自定义模块,还是自行在 YAML 文件中编写自定义模块定义,您定义的 CEL 表达式都是相同的。

用于检测逻辑的 CEL 表达式

您可以结合使用 CEL 表达式和标准 CEL 运算符对自定义模块的检测逻辑进行编码,以评估扫描的资源的属性。

表达式可以是单个值的简单检查,也可以是检查多个值或条件的更复杂的复合表达式。无论哪种方式,表达式都必须解析为布尔值 true 才能触发发现结果。

如果您要在 Google Cloud 控制台中创建自定义模块,则可以在配置模块页面上的表达式编辑器中编写这些表达式。

如果您要在 YAML 文件中对自定义模块进行编码,请在 predicate 属性下添加这些表达式。

无论您使用 Google Cloud 控制台还是 YAML 文件,用于评估资源属性的 CEL 表达式都必须遵循以下规则:

  • 您在 CEL 表达式中指定的属性必须是扫描的资源的属性,如资源类型的 API 定义中所定义。
  • 如果自定义模块评估多个资源类型,则您在 CEL 表达式中指定的属性必须是自定义模块评估的每种资源类型的通用属性。

    例如,如果您定义了一个名为 invalid_cryptokey 的自定义模块,用于检查 cloudkms.googleapis.com/CryptoKeycloudkms.googleapis.com/CryptoKeyVersion 这两种资源类型,则可以编写以下表达式,因为 CryptoKeyCryptoKeyVersion 资源类型都包含 name 属性:

    predicate:
    resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")

    但是,您不能在 invalid_cryptokey 自定义模块中指定以下表达式,因为该表达式评估的 importTimerotationPeriod 属性不是由这两种资源类型共用:

    predicate:
    resource.importTime >= timestamp("2022-10-02T15:01:23Z") || resource.rotationPeriod > duration("2592000s")
  • CEL 表达式中的所有枚举都必须以字符串表示。例如,以下是 cloudkms.googleapis.com/CryptoKeyVersion 资源类型的有效表达式:

    resource.state = "PENDING_GENERATION"
  • 您在 predicate 属性中定义的 CEL 表达式的结果必须是布尔值。只有当结果为 true 时,才会触发发现。

如需详细了解 CEL,请参阅以下内容:

CEL 表达式示例

下表列出了一些可用于评估资源属性的 CEL 表达式。您可以在 Google Cloud 控制台和 YAML 自定义模块定义中使用这些 CEL 表达式。

资源类型 说明 CEL 表达式
具有 IAM 政策的任何资源 IAM 政策检查,用于识别来自网域外的成员 !policy.bindings.all(binding, binding.members.all(m ,!m.endsWith('@gmail.com')))
cloudkms.googleapis.com/CryptoKey Cloud KMS 密钥轮替周期检查 has(resource.rotationPeriod) && resource.rotationPeriod > duration('60h')
使用单个政策管理多种资源类型 根据资源类型检查资源名称是以 dev 还是以 devAccess 开头 (resource.type == 'compute.googleapis.com/Disk' && resource.name.startsWith('projects/PROJECT_ID/regions/ REGION/disks/devAccess')) || (resource.type == 'compute.googleapis.com/Instance ' && resource.name.startsWith('projects/PROJECT_ID/zones/REGION/instances/dev-'))
compute.googleapis.com/Network 用于匹配网络对等方的 Virtual Private Cloud 对等互连规则 resource.selfLink.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/default') || resource.peerings.exists(p, p.network.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/shared$'))
cloudfunctions.googleapis.com/CloudFunction 仅允许 Cloud Run 函数的内部入站流量 has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY')
compute.googleapis.com/Instance 资源名称与模式匹配 resource.name.matches('^gcp-vm-(linux|windows)-v\\d+$')
serviceusage.googleapis.com/Service 仅允许启用存储相关 API resource.state == 'ENABLED' && !( resource.name.matches('storage-api.googleapis.com') || resource.name.matches('bigquery-json.googleapis.com') || resource.name.matches('bigquery.googleapis.com') || resource.name.matches('sql-component.googleapis.com') || resource.name.matches('spanner.googleapis.com'))
sqladmin.googleapis.com/Instance 仅允许已列入许可名单的公共 IP (resource.instanceType == 'CLOUD_SQL_INSTANCE' && resource.backendType == 'SECOND_GEN' && resource.settings.ipConfiguration.ipv4Enabled ) && !(resource.ipAddresses.all(ip, ip.type != 'PRIMARY' || ip.ipAddress.matches('IP_ADDRESS'))))
dataproc.googleapis.com/Cluster 检查 Dataproc 集群中的项目 ID 是否包含“testing”或“development”子字符串 has(resource.projectId) && resource.projectId.contains('testing') || resource.projectId.contains('development')

适用于自定义发现结果属性的 CEL 表达式

(可选)如需随每个发现结果一起返回详细信息以用于发现结果查询,您最多可以定义 10 个与自定义模块生成的发现结果一起返回的自定义属性。

自定义属性会显示在采用 JSON 格式的发现结果的来源属性中以及 Google Cloud 控制台中发现结果详情的来源属性标签页下。

您可以将自定义属性定义为 name - value 对。

如果您要在 Google Cloud 控制台中创建自定义模块,则可以在定义发现结果详情页面上的 Custom finding properties(自定义发现结果属性)部分中定义 name-value 对。

如果您要在 YAML 文件中对自定义模块进行编码,请在 custom_output 属性下将 name-value 对列为 properties

无论您使用 Google Cloud 控制台还是 YAML 文件,以下规则都适用:

  • 以不带英文引号的文本字符串形式指定 name
  • value 指定为以下某个值:

    • 如需返回某个属性的值,请按以下格式指定该属性:

      RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN

    在此示例中:

    • RESOURCE_TYPE 可以是 resourcepolicy
    • PROPERTY:包含要返回的值的属性的一个或多个父级属性。
    • PROPERTY_TO_RETURN 是包含要返回的值的属性。

    • 如需返回文本字符串,请用英文引号将字符串括起来。

以下示例展示了 YAML 文件中的 custom_output 下正确定义的两个 name-value 对:

custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.name
    - name: property_with_text
      value_expression:
        expression: "Note content"

后续步骤

如需测试、提交、查看和更新自定义模块,请参阅以下页面: