Writing Cloud Custodian Compliance Policies

Follow

Writing Cloud Custodian Compliance Policies

Kion includes the open-source Cloud Custodian rules engine, which allows you to easily write and run YAML policies against your cloud resources like EC2 instances, VPCs, root users, etc. These policies are implemented using compliance checks, which runs the policy on a cloud resource to see if it matches an undesirable configuration. You would typically use these checks to find resources with insecure configurations, so an example would be a check for an S3 bucket that is configured as publicly accessible. You can learn more about compliance checks in our What is a Compliance Check? article.

Cloud Custodian documentation is available and is a great resource for example policies, but this article will explain the basics of writing your own Cloud Custodian compliance policy and how the webhook actions work in Kion.

Compliance Policy Basics

A Cloud Custodian policy should define, at a minimum:

  • name - the unique name for the policy.
  • resource - the type of resource the policy should run against.

  • filters - filters that further narrow down the set of resources. This can include tag, type, key, value, and more, including and, or, or not logic statements.

  • actions - actions to take on the filtered set of resources. When used within Kion, this will include both the action that posts the findings to Kion via a webhook (so that it shows on your compliance overview, etc.), as well as actions to automatically remediate the finding, if desired.

Here are some basic examples for both AWS and Azure (which have slightly different rules):

AWS

This policy stops all EC2 instances that are tagged in the AWS Console with the tag Test (without posting the finding to Kion):

policies:
  - name: stop-ec2-test-instances
    resource: aws.ec2 
filters:
- "tag:Test": present
actions: - type: stop

To ensure this finding is posted to Kion and shows up in the compliance overview, etc, you'll need to also include some webhook action logic. For AWS, you would add this:

    actions:
- type: webhook
url: '{{CT::CallbackURL}}'
method: POST
batch: true
headers:
Authorization: '`{{CT::Authorization}}`'
body: |-
{
"compliance_check_id": `{{CT::CheckId}}`,
"account_number": account_id,
"region": region,
"scan_started_at": execution_start,
"findings": resources[].{resource_name: InstanceId, resource_type: `ec2`} }

So the final policy will look like this:

policies: 
- name: stop-ec2-test-instances
resource
: aws.ec2
filters:
- "tag:Test": present
actions:
- type: stop
- type: webhook
url: '{{CT::CallbackURL}}'
method: POST
batch: true
headers:
Authorization: '`{{CT::Authorization}}`'
body: |-
{
"compliance_check_id": `{{CT::CheckId}}`,
"account_number": account_id,
"region": region,
"scan_started_at": execution_start,
"findings": resources[].{resource_name: InstanceId, resource_type: `ec2`}
}

Azure

This policy adds the tag Project and sets the value to NA to all Virtual Machines (VMs) with the name test (without posting the finding to Kion):

policies:
  - name: tag-test-vms-project-na
resource: azure.vm 
filters:
- type: value
- key: name
- value: test
actions: - type: tag
- tag: Project
- value: NA

To ensure this finding is posted to Kion and shows up in the compliance overview, etc, you'll need to also include some webhook action logic. For Azure, you would add this:

    actions:
- type: webhook
url: '{{CT::CallbackURL}}'
method: POST
batch: true
headers:
Authorization: '`{{CT::Authorization}}`'
body: |-
{
"compliance_check_id": `{{CT::CheckId}}`,
"account_number": account_id,
"scan_started_at": execution_start,
"findings": resources[].{resource_name: VirtualMachine, resource_type: `vm`, region: location} }

So the final policy for Azure will look like this:

policies: 
- name: tag-test-vms-project-na
resource
: azure.vm
filters:
- type: value
- key: name
- value: test
actions:
- type: tag
tag: Project
value: NA
- type: webhook
url: '{{CT::CallbackURL}}'
method: POST
batch: true
headers:
Authorization: '`{{CT::Authorization}}`'
body: |-
{
"compliance_check_id": `{{CT::CheckId}}`,
"account_number": account_id,
"scan_started_at": execution_start,
"findings": resources[].{resource_name: VirtualMachine, resource_type: `vm`, region: location}
}

The final versions for both AWS and Azure contains the following information:

  1. The name of the policy. This can be any name that is unique among policies.

  2. The resource type to query against. You can find a list of resources and their common actions and filters here:

  3. The filters to use. You can find a list of common filters here:

  4. The actions to take if any resources are found with the specified criteria (including sending the finding to Kion via a webhook so that it shows in the application). You can find a list of common actions here:

Note that everything above the actions: section is a native c7n YAML, so you can copy/paste pre-written policies from other sources (github repos, etc.), and then just add in the actions section with the webhook for it to work in Kion.

The webhook for Kion we used here included the following supported parameters, which will be replaced when the policy runs as shown below:

  • {{CT::CheckId}} - will be replaced with the Check ID that will be scanned.
  • {{CT::Authorization}} - will be replaced with the appropriate authorization token specifically for ingesting findings via the public scan API.
  • {{CT::CallbackURL}} - will be replaced with the callback URL cloud custodian will POST to for ingesting findings via the public scan API.

The webhook action can be customized and still send findings to Kion as intended, but we recommend you use the examples shown above on all compliance checks to start. Make sure you change the resource_name and resource_type in the webhook action to the appropriate values (learn more about that in our article on Required Compliance Policy Fields).

Once you're done writing your own policy, you can use the button on the add a compliance check page to Validate Policy, which ensures your policy code is valid. You'll set the compliance check frequency and regions as fields within Kion when you, so they do not need to be part of the policy code.

Advanced Logic for Compliance Policies

While Cloud Custodian supports various types of advanced and conditional logic for AWS and for Azure, the following policy is an example using or and not logic. Use this example, which checks if the default security group has a value for either IpPermissions OR IpPermissionsEgress, as a guideline to incorporate this logic into your own policies. The or could be replaced with and to only find cases where the default security group has a value for BOTH IpPermissions AND IpPermissionsEgress:

policies:
- name: cis_sg-default-allowing-traffic
resource: aws.security-group description: | CIS 1.2.0 - 4.3 Ensure the default security group for every VPC restricts all traffic filters: - GroupName: default - or: - not: - IpPermissions: empty - not: - IpPermissionsEgress: empty actions: - type: webhook url: '{{CT::CallbackURL}}' method: POST batch: true headers: Authorization: '`{{CT::Authorization}}`' body: |- { "compliance_check_id": `{{CT::CheckId}}`, "account_number": account_id, "region": region, "scan_started_at": execution_start, "findings": resources[].{resource_name: GroupId, resource_type: `security-group`, data_json: {ingress_rules: IpPermissions, egress_rules: IpPermissionsEgress}} }

 

Was this article helpful?
0 out of 0 found this helpful