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.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 isfalse
.
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.rotationPeriod) && resource.rotationPeriod < duration('60h') |
compute.googleapis.com/Network |
Match Virtual Private Cloud peering rule to network peers | 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 |
Only allow internal ingress traffic for a Cloud Run function | has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY') |
compute.googleapis.com/Instance |
Resource name matches pattern | resource.name.matches('^gcp-vm-(linux|windows)-v\\\\d+$') |
serviceusage.googleapis.com/Service |
Only allow storage-related APIs to be enabled | 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
|
Only permit public IP addresses that are on the allowlist | (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 |
Check if project IDs in a Dataproc cluster contain
the substrings testing or development |
has(resource.projectId) && !resource.projectId.contains('testing') || !resource.projectId.contains('development') |