You can write custom checks in Rego.
Once you finish writing custom checks, you can pass the check files or the directory where those checks are stored with --config-check` option.
# METADATA
# title: Deployment not allowed
# description: Deployments are not allowed because of some reasons.
# schemas:
# - input: schema["kubernetes"]
# custom:
# id: ID001
# severity: LOW
# input:
# selector:
# - type: kubernetes
package user.kubernetes.ID001
deny[res] {
input.kind == "Deployment"
msg := sprintf("Found deployment '%s' but deployments are not allowed", [input.metadata.name])
res := result.new(msg, input.kind)
}
In this example, ID001 "Deployment not allowed" is defined under user.kubernetes.ID001.
If you add a new custom policy, it must be defined under a new package like user.kubernetes.ID002.
MAY include the group name such as kubernetes for clarity
Group name has no effect on policy evaluation
deny (required)
SHOULD be deny or start with deny_
Although warn, warn_*, violation, violation_ also work for compatibility, deny is recommended as severity can be defined in __rego_metadata__.
SHOULD return ONE OF:
The result of a call to result.new(msg, cause). The msg is a string describing the issue occurrence, and the cause is the property/object where the issue occurred. Providing this allows Trivy to ascertain line numbers and highlight code in the output.
A string denoting the detected issue
Although object with msg field is accepted, other fields are dropped and string is recommended if result.new() is not utilised.
e.g. {"msg": "deny message", "details": "something"}
By default, only builtin.* packages will be evaluated.
If you define custom packages, you have to specify the package prefix via --namespaces option. By default, Trivy only runs in its own namespace, unless specified by the user. Note that the custom namespace does not have to be user as in this example. It could be anything user-defined.
The check must contain a Rego Metadata section. Trivy uses standard rego metadata to define the new policy and general information about it.
Trivy supports extra fields in the custom section as described below.
Example
# METADATA
# title: Deployment not allowed
# description: Deployments are not allowed because of some reasons.
# custom:
# id: ID001
# severity: LOW
# input:
# selector:
# - type: kubernetes
If you are creating checks for your Trivy misconfiguration scans, some fields are optional as referenced in the table below. The schemas field should be used to enable policy validation using a built-in schema. It is recommended to use this to ensure your checks are
correct and do not reference incorrect properties/values.
The AVD_ID can be used to link the check to the Aqua Vulnerability Database (AVD) entry. For example, the avd_idAVD-AWS-0176 is the ID of the check in the AWS Vulnerability Database. If you are contributing your check to trivy-checks, you need to generate an ID using make id in the trivy-checks repository. The output of the command will provide you the next free IDs for the different providers in Trivy.
The ID is based on the AVD_ID. For instance if the avd_id is AVD-AWS-0176, the ID is ID0176.
The provider field references the provider available in Trivy. This should be the same as the provider name in the pkg/iac/providers directory, e.g. aws.
Services are defined within a provider. For instance, RDS is a service and AWS is a provider. This should be the same as the service name in one of the provider directories. (Link), e.g. aws/rds.
The input tells Trivy what inputs this check should be applied to. Cloud provider checks should always use the selector input, and should always use the type selector with cloud. Check targeting Kubernetes yaml can use kubernetes, RBAC can use rbac, and so on.
This option filters the input by file format or configuration language.
In the above example, Trivy passes only Kubernetes files to this policy.
Even if a Dockerfile exists in the specified directory, it will not be passed to the policy as input.
Possible values for input types are:
dockerfile (Dockerfile)
kubernetes (Kubernetes YAML/JSON)
rbac (Kubernetes RBAC YAML/JSON)
cloud (Cloud format, as defined by Trivy - this is used for Terraform, CloudFormation, and Cloud/AWS scanning)
yaml (Generic YAML)
json (Generic JSON)
toml (Generic TOML)
When configuration languages such as Kubernetes are not identified, file formats such as JSON will be used as type.
When a configuration language is identified, it will overwrite type.
Example
pod.yaml including Kubernetes Pod will be handled as kubernetes, not yaml.
type is overwritten by kubernetes from yaml.
type accepts kubernetes, dockerfile, cloudformation, terraform, terraformplan, json, or yaml.