本页介绍了如何使用通用表达式语言 (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 表达式。
如需对自定义定义模块进行编码,请按照以下步骤操作:
创建一个文件扩展名为
yaml的文本文件。在该文本文件中,创建
resource_selector属性并指定要扫描的自定义模块的资源类型(一到五个)。在自定义模块定义中,资源类型只能指定一次。例如:resource_selector: resource_types: ‐ cloudkms.googleapis.com/CryptoKey
您指定的资源类型必须受 Security Command Center 支持。如需查看支持的资源类型列表,请参阅支持的资源类型。
创建
predicate属性,并指定一个或多个 CEL 表达式,用于检查要扫描的资源类型的属性。您在 CEL 表达式中引用的任何属性都必须存在于您在resource_selector下指定的每个资源类型的Google Cloud API 定义中。如需触发发现结果,表达式必须解析为TRUE。 例如,在以下表达式中,只有大于2592000s的rotationPeriod值才会触发发现。predicate: expression: resource.rotationPeriod > duration("2592000s")如需获得有关编写 CEL 表达式的帮助,请参阅以下资源:
- 支持的资源类型。 点击每个资源可查看您可以在 CEL 表达式中使用的属性。
- 编写 CEL 表达式。
- 在自定义模块中引用资源和政策属性。
创建
description属性,以说明自定义模块检测到的漏洞或配置错误。此说明会显示在每个发现结果实例中,以帮助调查人员了解检测到的问题。文本必须用英文引号括起来。例如:description: "The rotation period of the identified cryptokey resource exceeds 30 days, the maximum rotation period that our security guidelines allow."
创建
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 控制台创建或更新自定义模块,则无需使用转义字符。
创建
severity属性,并指定此模块创建的发现结果的默认严重程度。severity属性的常用值包括LOW、MEDIUM、HIGH和CRITICAL。例如,severity: MEDIUM
(可选)创建
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"将文件保存到您的 gcloud CLI 可以访问的位置。
使用以下命令将定义上传到 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部分中定义。 - 两个自定义来源属性
duration和violation在custom_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:其中rotationPeriod是resource的属性。resource.metadata.name:其中name是metadata的子属性,后者是resource的子属性。
引用 IAM 政策属性
您可以引用资源的 IAM 政策属性,创建用于评估资源 IAM 政策的 CEL 表达式。唯一可用的属性是绑定以及绑定中的角色。
引用 IAM 政策属性时,policy 是顶级属性。
下面是 IAM 政策属性及其检索方式的示例:
policy.bindings,其中bindings是policy的属性。policy.version,其中version是policy的属性。
如需查看更多示例,请参阅 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/CryptoKey和cloudkms.googleapis.com/CryptoKeyVersion这两种资源类型,则可以编写以下表达式,因为CryptoKey和CryptoKeyVersion资源类型都包含name属性:predicate: resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")但是,您不能在
invalid_cryptokey自定义模块中指定以下表达式,因为该表达式评估的importTime和rotationPeriod属性不是由这两种资源类型共用: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 functions 函数的内部入站流量 | 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 控制台中创建自定义模块,则可以在定义发现结果详情页面上的自定义发现结果属性部分中定义 name-value 对。
如果您要在 YAML 文件中对自定义模块进行编码,请在 custom_output 属性下将 name-value 对列为 properties。
无论您使用 Google Cloud 控制台还是 YAML 文件,以下规则都适用:
- 以不带英文引号的文本字符串形式指定
name。 将
value指定为以下值之一:如需返回属性的值,请按以下格式指定属性:
RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN
在此示例中:
RESOURCE_TYPE可以是resource或policy。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"后续步骤
如需测试、提交、查看和更新自定义模块,请参阅以下页面:
- 如需测试自定义模块,请参阅测试 Security Health Analytics 的自定义模块。
- 如需上传、查看和更新自定义模块,请参阅创建和管理 Security Health Analytics 的自定义模块。