Project: Checkov (Provisioning / Security & Compliance)
File: YAML Custom Policies.md

layout: default published: true title: YAML Custom Policies nav_order: 3 Custom policies created in YAML support checking a resources connection state and the use of complex AND/OR logic. Read also how to . A YAML-based custom policy for Checkov consists of sections for the Metadata and Policy Definition. Metadata The Metadata includes: Policy Name ID - `CKV2<provider><number>` Category Guideline (optional) The possible values for category are: GENERAL_SECURITY LOGGING ENCRYPTION NETWORKING IAM BACKUPANDRECOVERY CONVENTION SECRETS KUBERNETES APPLICATION_SECURITY SUPPLY_CHAIN API_SECURITY ```yaml metadata: id: "CKV2CUSTOM1" name: "Ensure bucket has versioning and owner tag" category: "BACKUPANDRECOVERY" guideline: "https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/aws-general-policies/ckv2custom1" ``` The policy definition consists of: Definition Block(s) - either Attribute Block(s) or Connection State Block(s)* or both Logical Operator(s)* (optional) Filter* (optional) The top level object under `definition` must be a single object (not a list). It can be an attribute block, a connection block, or a logical operator (`and`, `or`, `not`). Attribute Blocks: The policy describes resources with a certain configuration as defined by a configuration attribute* and its value (per Terraform), or by the presence/absence of an attribute. Connection State Blocks - The policy describes resources in a particular Connection state*; either connected or not connected to another type of resource (for example, a security group). A policy definition may include multiple blocks (Attribute, Connection state or both), associated by AND/OR logic. A policy definition may include any block (Attribute, Connection state, or AND/OR) underneath a `not` block to invert the statement. An Attribute Block in a policy's definition indicates that a resource will be non-compliant if a certain configuration attribute does not have a specified value or if it exists/doesn't exist. Prisma Cloud's custom policies in code utilize the Terraform attribute library and syntax. These policies are checked during scans of both build-time and runtime resources and for all supported cloud providers. The Attribute Block in the `definition` in the example below is used to ensure that a proper back-up policy is configured for Redshift clusters: ```yaml definition: cond_type: "attribute" resource_types: "awsredshiftcluster" attribute: "automatedsnapshotretention_period" operator: "not_equals" value: "0" ``` | Value in YAML | Description | Value types | Example | |--|--|-|| | `equals` | Exact value match | String, Int, Bool | operator: "equals"<br>value: "t3.nano" | | `notequals` | Not equal to the value | String, Int, Bool | operator: "notequals"<br>value: "t3.nano" | | `regexmatch` | The value must match the regular <br>expression | String (RegEx) | operator: "regexmatch"<br>value: "^myex-.*" | | `notregexmatch` | The value must not match the regular <br>expression | String (RegEx) | operator: "notregexmatch"<br>value:

| | `exists` | The attribute or connection appears in the <br>resource definition | None | attribute: "name"<br>operator: exists | | `notexists` | The attribute or connection does not <br>appear in the resource | None | attribute: "name"<br>operator: notexists | | `oneexists` | At least one connection of a specific type <br>exists | None | resourcetypes:<br> - awsvpc<br>connectedresourcetypes:<br> - awsflowlog<br>operator: oneexists<br>attribute: networking<br>cond_type: connection | | `any` | Any of a list of attribute values match what <br>the resource contains | (List) Strings | operator: "any"<br>value: <br>-"value1" | | `contains` | The values of a resource attribute includes <br>all of these values | (List) Strings | operator: "contains"<br>value: <br>-"value1" | | `notcontains` | The values of a resource attribute includes <br>all of these values | (List) Strings | operator: "notcontains"<br>value: <br>-"value1" | | `within` | Used with filter to focus the findings on a <br>specific resource type or with attribute to <br>provide a list of possible options | String | condtype: filter<br>attribute: resourcetype<br>value:<br> - googleloggingorganization_sink<br>operator: within | | `notwithin` | Specify a list of unacceptable resource <br>and value options | (List) Strings | condtype: attribute<br>attribute: 'subjects.*.kind'<br>operator: notwithin<br>value:<br> - 'Node'<br>resourcetypes:<br> - ClusterRoleBinding | | `startingwith` | The value must begin with a string | String | operator: startingwith<br>value: terraform-aws-modules | | `notstartingwith` | The value must not begin with a string | String | operator: notstartingwith<br>value: terraform-aws-modules | | `endingwith` | The value used by the attribute must end <br>with this string | String | operator: notending_with<br>value: "-good" | | `notendingwith` | The value used by the attribute must not <br>end with this string | String | operator: ending_with<br>value: "-bad" | | `greaterthan` | The value used by the attribute must be <br>greater than this value | String, Int | operator: greaterthan<br>value: "100" | | `greaterthanorequal` | The value used by the attribute must be <br>greater than or equal to this value | String, Int | operator: lessthanorequal<br>value: "100" | | `lessthan` | The value used by the attribute must be <br>less than this value | String, Int | operator: lessthan<br>value: "100" | | `lessthanorequal` | The value used by the attribute must be <br>less than or equal to this value | String, Int | operator: lessthanorequal<br>value: "100" | | `subset` | The values used by the attribute must be <br>a subset of the listed values and not <br>outside of that | (List) String | operator: subset<br>value: <br> - "a"<br> - "b" | | `notsubset` | The values used by the attribute must <br>not be any of a subset of the listed <br>values and not outside of that | (List) String | operator: notsubset<br>value: <br> - "a"<br> - "b" | | `isempty` | The attribute must not have a value | None | attribute:

is_empty | | `isnotempty` | The attribute must have a value | None | attribute: "description"<br>operator: isnotempty | | `lengthequals` | The list of attributes of that type must <br>be of this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: length_equals<br>value: "2" | | `lengthnotequals` | The list of attributes of that type must <br>not be of this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: lengthnot_equals<br>value: "2" | | `lengthlessthan` | The list of attributes of that type must <br>be less than this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: lengthless_than<br>value: "20" | | `lengthlessthanorequal` | The list of attributes of that type must <br>be less than or equal to this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: lengthlessthanor_equal<br>value: "20" | | `lengthgreaterthan` | The list of attributes of that type must <br>be greater than this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: lengthgreater_than<br>value: "20" | | `lengthgreaterthanorequal` | The list of attributes of that type must <br>be greater than or equal to this number | String, Int | resourcetypes:<br> - awssecuritygroup<br>attribute: ingress<br>operator: lengthgreaterthanor_equal<br>value: "20" | | `isfalse` | The value of the attribute must be false | None | operator: isfalse | | `istrue` | The value of the attribute must be true | None | operator: istrue | | `intersects` | Given 2 values, check if those values <br>intersect | (List) Strings | attribute: "availability_zone"<br>operator: "intersects"<br>value: "us-" | | `notintersects` | Given 2 values, check if those values do<br> not intersect | (List) Strings | attribute: "availabilityzone"<br>operator: "not_intersects"<br>value: "us-" | | `equalsignorecase` | The value of the attribute equals this <br>value, ignoring case for both | String | operator: "equalsignorecase"<br>value: "INGRESS" | | `notequalsignorecase` | The value of the attribute does not <br>equal this value, ignoring case for both | String | operator: "notequalsignorecase"<br>value: "INGRESS" | | `rangeincludes` | The range of the value of the attribute <br>includes this single number | String, Int | operator: "rangeincludes"<br>value: 3000 | | `rangenotincludes` | The range of the value of the attribute <br>does not include this single number | String, Int | operator: "rangenotincludes"<br>value: 3000 | | `numberofwordsequals` | The number of words in the value of the <br>attribute is equal to this number | String, Int | operator: numberofwordsequals<br>value: 6 | | `numberofwordsnotequals` | The number of words in the value of the <br>attribute is not equal to this number | String, Int | operator: numberofwordsnotequals<br>value: 6 | All those operators are supporting JSONPath attribute expression by adding the `jsonpath` prefix to the operator, for example - `jsonpathlength_equals` | Key | Type | Value(s) | | | |-| | `cond_type` | string | Must be `attribute` | | `resource_type` | collection of strings | Use either `all` or `[resource types from list]` | | `attribute` | string | Attribute of defined resource types. For example, `automatedsnapshotretention_period` | | `operator` | string | - `equals`, `notequals`, `regexmatch`, `notregexmatch`, `exists`, `not exists`, `any`, `contains`, `notcontains`, `within`, `startingwith`, `notstartingwith`, `endingwith`, `notendingwith`, `greaterthan`, `greaterthanorequal`, `lessthan`, `lessthanorequal`, `isempty`, `isnotempty`, `lengthequals`, `lengthnotequals`, `lengthgreaterthan`, `lengthgreaterthanorequal`, `lengthlessthan`, `lengthlessthanorequal`, `istrue`, `isfalse`, `intersects`, `notintersects` | | `value` (not relevant for operator: `exists`/`not_exists`) | string | User input. | You may use a wildcard (``) to evaluate all of the items within a list. You may use multiple wildcards to evaluated nested lists. If any* item in the list matches the condition, then the condition passes. For example, consider the following resource: ``` resource "awssecuritygroup" "sg" { ... ingress { cidr_blocks = ["0.0.0.0/0"] ... } ingress { cidr_blocks = ["192.168.1.0/24"] ... } } ``` The following definition will return `true`, because one of the CIDR blocks contains `0.0.0.0/0`: ```yaml cond_type: attribute resource_types: "awssecuritygroup" attribute: "ingress.*.cidr_blocks" operator: "contains" value:

``` Note that switching the operator to `not_contains` will still result in the evaluation being `true`, because there is also an element that does not contain `0.0.0.0/0`. If you want to write a policy that fails if any CIDR block contains `0.0.0.0/0`, consider the `not` operator, described below. A Connection State Block indicates a type of resource that has or does not have a connection to another type of resource. In the example presented in the table below, in order to be compliant, `awslb` and `awselb` must have connections to either `awssecuritygroup` or `awsdefaultsecurity_group`. | Group A | Group B | | | | |`awslb` `awselb` | `awssecuritygroup` `awsdefaultsecurity_group` | The Connection State Block below indicates that to be compliant with the policy, resources of type `awslb` or of type `awselb` must be connected to either a resource of type `awssecuritygroup` or a resource of type `awsdefaultsecurity_group`. ```yaml definition: cond_type: "connection" resource_types: "aws_elb" "aws_lb" connectedresourcetypes: "awssecuritygroup" "awsdefaultsecurity_group" operator: "exists" ``` | Operator | Value | | -- | -- | | Exists | `exists` | | Not Exists | `not_exists` | | One Exists | `one_exists` | | Key | Type | Values | | -- | -- | -- | | `cond_type` | string | Must be `connection` | | `resource_types` | | Use either `all` or `[included resource type from list]` | | `connectedresourcetypes` | collection of strings | Use either `all` or `[included resource type from list]` | | `operator` | string | `exists`/`not exists` | Filters can be used to limit the types of resources relevant to a condition. Filters are most commonly used for Connection Blocks (for Attribute Blocks you can easily limit the resource type with the `resource_type` parameter). For example, you may want to enforce a policy only for a specific resource type (or types) from specific groups defined in the conditions. Filters are available only for AND logic at the top level. The Custom Policy in this example ensures that all ELBs are attached to security groups as shown in the table below. In line with best practices, connections of this nature should be defined using the `security_groups` key. | Group A | Group B | | -- | -- | | `awselb` | `awssecuritygroup` `awsdefaultsecuritygroup` | | Not Exists | `not_exists` | ```yaml definition: and: cond_type: "filter" attribute: "resource_type" value: "aws_elb" operator: "within" cond_type: "connection" resource_types: "aws_elb" connectedresourcetypes: "awssecuritygroup" "awsdefaultsecurity_group" operator: "exists" ``` Note: The condition above uses AND logic. See for complex logic in policy definitions. The Prisma Cloud platform allows you to combine definition blocks using AND/OR operators. The top-level logical operator is the first key below \"definition\" (and not an item in a collection). Most policies will start with an `and` or `or` key here, with multiple conditions nested within that. Filter blocks apply (only) to the top-level and constitute an AND

For example, if you'd like to indicate a requirement for a Connection State between types of resources, but only within a certain subset of all of those resources. Every other logical operator applies within a collection. For example, you can use AND/OR logic in a collection of key-value pairs. The value for the `and` or `or` key must be a list; each element of the list must be a valid definition on its own (i.e., a combination of attribute conditions, connection conditions, nested AND/OR, etc). The logic in the policy definition shown below is: `AND[block 1,block 2,OR[block 3,block 4]]`. ```yaml definition: and: #filter block 1 #block 2 or: #block 3 #block 4 ``` You can use `not` in the same places that you may use `and` and `or` to invert the nested condition definition. The value of the `not` element in the policy may be either a list containing exactly one element (which can also be nested more deeply), or any other type of block. The definition below inverts the example in the previous section. ```yaml definition: not: and: #filter block 1 #block 2 or: #block 3 #block 4 ``` The following code is also valid (the child of `not` is a list of length 1): ```yaml definition: not: and: #filter block 1 #block 2 or: #block 3 #block 4 ``` Following `resource_types` are supported `block` `tasks.[module name]` ex. ```yaml cond_type: attribute resource_types: tasks.ansible.builtin.uri tasks.uri attribute: url operator: starting_with value: "https://" ``` In the case a module can be used without parameters by just adding the value to it, then it can be queried via a the special attribute `self`. ex. ```yaml cond_type: "attribute" resource_types: "ansible.builtin.command" "command" attribute: "self" operator: "not_contains" value: "vim" ``` All resources can be referenced under `resource_types`. Currently, no support for connections. All resources can be referenced under `resource_types`. Any kind of connection between resources is supported All resources can be referenced under `resource_types`. Any kind of connection between resources is supported All official Docker instructions can be referenced under `resource_types`. Currently, no support for connections. Following attribute values are supported `content` stores the raw data for an instruction `value` stores the sanitized data for an instruction ex. ```dockerfile RUN apt-get update \ && sudo apt-get install vim ``` -> ```yaml content: "RUN apt-get update \\\n && sudo apt-get install vim\n" value: "apt-get update && sudo apt-get install vim" ``` Following `resource_types` are supported `permissions` on the root level `steps` `jobs` `on` Following connections are supported `steps` -> `jobs` The value for `permissions` can be either a map or a single string. Map entries should be prefixed with `permissions.` key and a single string entry can be accessed by using `permissions` as the attribute. ex. ```yaml cond_type: "attribute" resource_types: "permissions" attribute: "permissions" operator: "not_equals" value: "write-all" ``` The value for `on` can be either a map, a string or a list of strings. ex. ```yaml cond_type: attribute resource_types: "on" attribute: on.push.branches operator: contains value: main ``` All resources can be referenced under `resource_types`. Currently, no support for connections. All resources can be referenced under `resource_types`. Any kind of connection between resources is supported