Contribute Rego Checks¶
The following guide provides an overview of contributing checks to the default checks in Trivy.
All of the checks in Trivy can be found in the trivy-checks repository on GitHub. Before you begin writing a check, ensure:
- The check does not already exist as part of the default checks in the trivy-checks repository.
- The pull requests in the trivy-checks repository to see whether someone else is already contributing the check that you wanted to add.
- The issues in Trivy to see whether any specific checks are missing in Trivy that you can contribute.
If anything is unclear, please start a discussion and we will do our best to help.
Check structure¶
Checks are written in Rego and follow a particular structure in Trivy. Below is an example check for AWS:
# METADATA
# title: "RDS IAM Database Authentication Disabled"
# description: "Ensure IAM Database Authentication is enabled for RDS database instances to manage database access"
# scope: package
# schemas:
# - input: schema["aws"]
# related_resources:
# - https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth.html
# custom:
# id: AVD-AWS-0176
# avd_id: AVD-AWS-0176
# provider: aws
# service: rds
# severity: MEDIUM
# short_code: enable-iam-auth
# recommended_action: "Modify the PostgreSQL and MySQL type RDS instances to enable IAM database authentication."
# input:
# selector:
# - type: cloud
# subtypes:
# - service: rds
# provider: aws
package builtin.aws.rds.aws0176
deny[res] {
instance := input.aws.rds.instances[_]
instance.engine.value == ["postgres", "mysql"][_]
not instance.iamauthenabled.value
res := result.new("Instance does not have IAM Authentication enabled", instance.iamauthenabled)
}
Verify the provider and service exists¶
Every check for a cloud service references a cloud provider. The list of providers are found in the Trivy repository.
Before writing a new check for a cloud provider, you need to verify if the cloud provider or resource type that your check targets is supported by Trivy. If it's not, you'll need to add support for it. Additionally, if the provider that you want to target exists, you need to check whether the service your policy will target is supported. As a reference you can take a look at the AWS provider here.
Note
New Kubernetes and Dockerfile checks do not require any additional provider definitions. You can find an example of a Dockerfile check here and a Kubernetes check here.
Add Support for a New Service in an existing Provider¶
Please reference the documentation on adding Support for a New Service.
This guide also showcases how to add new properties for an existing Service.
Create a new .rego file¶
The following directory in the trivy-checks repository contains all of our custom checks. Depending on what type of check you want to create, you will need to nest a new .rego
file in either of the subdirectories:
- cloud: All checks related to cloud providers and their services
- docker: Docker specific checks
- kubernetes: Kubernetes specific checks
Check Package name¶
Have a look at the existing package names in the built in checks.
The package name should be in the format builtin.PROVIDER.SERVICE.ID
, e.g. builtin.aws.rds.aws0176
.
Generating an ID¶
Every check has a custom ID that is referenced throughout the metadata of the check to uniquely identify the check. If you plan to contribue your check back into the trivy-checks repository, it will require a valid ID.
Running make id
in the root of the trivy-checks repository will provide you with the next available ID for your rule.
Check Schemas¶
Rego Checks for Trivy can utilise Schemas to map the input to specific objects. The schemas available are listed here..
More information on using the builtin schemas is provided in the main documentation.
Check Metadata¶
The metadata is the top section that starts with # METADATA
, and has to be placed on top of the check. You can copy and paste from another check as a starting point. This format is effectively yaml within a Rego comment, and is defined as part of Rego itself.
For detailed information on each component of the Check Metadata, please refer to the main documentation.
Note that while the Metadata is optional in your own custom checks for Trivy, if you are contributing your check to the Trivy builtin checks, the Metadata section will be required.
Writing Rego Rules¶
Rules are defined using OPA Rego. You can find a number of examples in the checks
directory (Link). The OPA documentation is a great place to start learning Rego. You can also check out the Rego Playground to experiment with Rego, and join the OPA Slack.
deny[res] {
instance := input.aws.rds.instances[_]
instance.engine.value == ["postgres", "mysql"][_]
not instance.iamauthenabled.value
res := result.new("Instance does not have IAM Authentication enabled", instance.iamauthenabled)
}
The rule should return a result, which can be created using result.new
. This function does not need to be imported, it is defined internally and provided at runtime. The first argument is the message to display and the second argument is the resource that the issue was detected on.
It is possible to pass any rego variable that references a field of the input document.
Generate docs¶
Finally, you'll want to generate documentation for your newly added rule. Please run make docs
in the trivy-checks directory to generate the documentation for your new policy and submit a PR for us to take a look at.
Adding Tests¶
All Rego checks need to have tests. There are many examples of these in the checks
directory for each check (Link). More information on how to write tests for Rego checks is provided in the custom misconfiguration section of the docs.
Example PR¶
You can see a full example PR for a new rule being added here: https://github.com/aquasecurity/defsec/pull/1000.