Write rules for custom cloud controls

When you create a custom cloud control, you use Common Expression Language (CEL) expressions to create the rules that evaluate the properties of the scanned resource.

Your expressions can be checks of a single value or more complex compound expressions that check multiple values or conditions. Either way, the expression must resolve to a boolean false to trigger a finding.

CEL expressions that evaluate resource properties must conform to the following rules:

  • The properties that you specify in a CEL expression must be properties of the scanned resource, as defined in the API definition of the resource type.

  • All enums in a CEL expression must be represented as strings. For example, the following is a valid expression for the cloudkms.googleapis.com/CryptoKeyVersion resource type:

    resource.data.state = "PENDING_GENERATION"
  • The result of the CEL expressions that you define in the condition property must be a Boolean. A finding is triggered only if the result is false.

To find the name for a resource, see Asset types.

For more information about CEL, see the following:

Example CEL expressions

The following table lists some CEL expressions that you can use to evaluate resource properties.

Resource type Description CEL expression
cloudkms.googleapis.com/CryptoKey Check the Cloud KMS key rotation period has(resource.data.rotationPeriod) && resource.data.rotationPeriod < duration('60h')
compute.googleapis.com/Network Match Virtual Private Cloud peering rule to network peers resource.data.selfLink.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/default') || resource.data.peerings.exists(p, p.network.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/shared$'))
cloudfunctions.googleapis.com/CloudFunction Only allow internal ingress traffic for a Cloud Run function has(resource.data.ingressSettings) && resource.data.ingressSettings.matches('ALLOW_INTERNAL_ONLY')
compute.googleapis.com/Instance Resource name matches pattern resource.data.name.matches('^gcp-vm-(linux|windows)-v\\\\d+$')
serviceusage.googleapis.com/Service Only allow storage-related APIs to be enabled resource.data.state == 'ENABLED' && !( resource.data.name.matches('storage-api.googleapis.com') || resource.data.name.matches('bigquery-json.googleapis.com') || resource.data.name.matches('bigquery.googleapis.com') || resource.data.name.matches('sql-component.googleapis.com') || resource.data.name.matches('spanner.googleapis.com'))
sqladmin.googleapis.com/Instance Only permit public IP addresses that are on the allowlist (resource.data.instanceType == 'CLOUD_SQL_INSTANCE' && resource.data.backendType == 'SECOND_GEN' && resource.data.settings.ipConfiguration.ipv4Enabled ) && (resource.data.ipAddresses.all(ip, ip.type != 'PRIMARY' || ip.ipAddress.matches('IP_ADDRESS')))
dataproc.googleapis.com/Cluster Check if project IDs in a Dataproc cluster contain the substrings testing or development has(resource.data.projectId) && !resource.data.projectId.contains('testing') || !resource.data.projectId.contains('development')

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年11月11日 UTC.