Custom Policies

Overview

You can write custom policies in Rego. Once you finish writing custom policies, you can pass the directory where those policies are stored with --policy option.

  1. trivy conf --policy /path/to/custom_policies --namespaces user /path/to/config_dir

As for --namespaces option, the detail is described as below.

File formats

If a file name matches the following file patterns, Trivy will parse the file and pass it as input to your Rego policy.

File formatFile pattern
JSON.json
YAML.yaml
TOML.toml
HCL.hcl, .hcl1, and .hcl2
DockerfileDockerfile, Dockerfile., and .Dockerfile

Configuration languages

In the above general file formats, Trivy automatically identifies the following types of configuration files:

  • Ansible (YAML)
  • CloudFormation (JSON/YAML)
  • Kubernetes (JSON/YAML)

This is useful for filtering inputs, as described below.

Warning

Custom policies do not support Terraform at the moment.

Rego format

A single package must contain only one policy.

Example

  1. package user.kubernetes.ID001
  2. __rego_metadata__ := {
  3. "id": "ID001",
  4. "title": "Deployment not allowed",
  5. "severity": "LOW",
  6. "type": "Custom Kubernetes Check",
  7. "description": "Deployments are not allowed because of some reasons.",
  8. }
  9. __rego_input__ := {
  10. "selector": [
  11. {"type": "kubernetes"},
  12. ],
  13. }
  14. deny[msg] {
  15. input.kind == "Deployment"
  16. msg = sprintf("Found deployment '%s' but deployments are not allowed", [input.metadata.name])
  17. }

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.

Policy structure

package (required)

  • MUST follow the Rego’s specification
  • MUST be unique per policy
  • SHOULD include policy id for uniqueness
  • MAY include the group name such as kubernetes for clarity
    • Group name has no effect on policy evaluation

__rego_metadata__ (optional)

  • SHOULD be defined for clarity since these values will be displayed in the scan results

__rego_input__ (optional)

  • MAY be defined when you want to specify input format

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 string
    • Although object with msg field is accepted, other fields are dropped and string is recommended.
    • e.g. {"msg": "deny message", "details": "something"}

Package

A package name must be unique per policy.

Example

  1. package user.kubernetes.ID001

By default, only appshield.* packages will be evaluated. If you define custom packages, you have to specify the package prefix via --namespaces option.

  1. trivy conf --policy /path/to/custom_policies --namespaces user /path/to/config_dir

In this case, user.* will be evaluated. Any package prefixes such as main and user are allowed.

Metadata

Metadata helps enrich Trivy’s scan results with useful information.

Example

  1. __rego_metadata__ := {
  2. "id": "ID001",
  3. "title": "Deployment not allowed",
  4. "severity": "LOW",
  5. "type": "Custom Kubernetes Check",
  6. "description": "Deployments are not allowed because of some reasons.",
  7. "recommended_actions": "Remove Deployment",
  8. "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-resource-requests-and-limits",
  9. }

All fields under __rego_metadata__ are optional.

Field nameAllowed valuesDefault valueIn tableIn JSON
idAny charactersN/AOverview - 图1Overview - 图2
titleAny charactersN/AOverview - 图3Overview - 图4
severityLOW, MEDIUM, HIGH, CRITICALUNKNOWNOverview - 图5Overview - 图6
typeAny charactersN/AOverview - 图7Overview - 图8
descriptionAny charactersOverview - 图9Overview - 图10
recommended_actionsAny charactersOverview - 图11Overview - 图12
urlAny charactersOverview - 图13Overview - 图14

Some fields are displayed in scan results.

  1. deployment.yaml (kubernetes)
  2. ============================
  3. Tests: 28 (SUCCESSES: 14, FAILURES: 14, EXCEPTIONS: 0)
  4. Failures: 14 (HIGH: 1)
  5. +---------------------------+------------+-------------------------------------+----------+------------------------------------------+
  6. | TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE |
  7. +---------------------------+------------+-------------------------------------+----------+------------------------------------------+
  8. | Custom Kubernetes Check | ID001 | Deployment not allowed | LOW | Found deployment 'test' but deployments |
  9. | | | | | are not allowed |
  10. +---------------------------+------------+-------------------------------------+----------+------------------------------------------+

Input

You can specify input format via __rego_input__. All fields under __rego_input are optional.

Example

  1. __rego_input__ := {
  2. "combine": false,
  3. "selector": [
  4. {"type": "kubernetes"},
  5. ],
  6. }

combine (boolean)

The details is here.

selector (array)

This option filters the input by file formats or configuration languages. In the above example, Trivy passes only Kubernetes files to this policy. Even if Dockerfile exists in the specified directory, it will not be passed to the policy as input.

When configuration language such as Kubernetes is not identified, file format such as JSON will be used as type. When 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, ansible, cloudformation, json, yaml, toml, or hcl.