feat(misconf): Add support for deprecating a check (#6664)

Signed-off-by: Simar <simar@linux.com>
This commit is contained in:
simar7
2024-05-15 19:14:51 -06:00
committed by GitHub
parent 1ad47c24ef
commit 88702cfd59
47 changed files with 358 additions and 90 deletions

View File

@@ -129,8 +129,8 @@ $ trivy image --skip-db-update --skip-java-db-update --offline-scan alpine:3.12
No special measures are required to detect misconfigurations in an air-gapped environment.
### Run Trivy with `--skip-policy-update` option
In an air-gapped environment, specify `--skip-policy-update` so that Trivy doesn't attempt to download the latest misconfiguration policies.
### Run Trivy with `--skip-check-update` option
In an air-gapped environment, specify `--skip-check-update` so that Trivy doesn't attempt to download the latest misconfiguration checks.
```
$ trivy conf --skip-policy-update /path/to/conf

View File

@@ -3,7 +3,7 @@ The cache directory includes
- [Vulnerability Database][trivy-db][^1]
- [Java Index Database][trivy-java-db][^2]
- [Misconfiguration Policies][misconf-policies][^3]
- [Misconfiguration Checks][misconf-checks][^3]
- Cache of previous scans.
The cache option is common to all scanners.
@@ -70,7 +70,7 @@ $ trivy server --cache-backend redis://localhost:6379 \
[trivy-db]: ./db.md#vulnerability-database
[trivy-java-db]: ./db.md#java-index-database
[misconf-policies]: ../scanner/misconfiguration/check/builtin.md
[misconf-checks]: ../scanner/misconfiguration/check/builtin.md
[^1]: Downloaded when scanning for vulnerabilities
[^2]: Downloaded when scanning `jar/war/par/ear` files

View File

@@ -483,7 +483,7 @@ trivy image --ignore-policy contrib/example_policy/basic.rego centos:7
For more advanced use cases, there is a built-in Rego library with helper functions that you can import into your policy using: `import data.lib.trivy`.
More info about the helper functions are in the library [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/pkg/result/module.go).
You can find more example policies [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/pkg/result/module.go)
You can find more example checks [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/pkg/result/module.go)
### By Vulnerability Exploitability Exchange (VEX)
| Scanner | Supported |

View File

@@ -11,7 +11,7 @@ The following scanners are supported.
Trivy recursively searches directories and scans all found Helm files.
It evaluates variables, functions, and other elements within Helm templates and resolve the chart to Kubernetes manifests then run the Kubernetes checks.
See [here](../../scanner/misconfiguration/check/builtin.md) for more details on the built-in policies.
See [here](../../scanner/misconfiguration/check/builtin.md) for more details on the built-in checks.
### Value overrides
There are a number of options for overriding values in Helm charts.

View File

@@ -87,6 +87,7 @@ trivy aws [flags]
-h, --help help for aws
--ignore-policy string specify the Rego file path to evaluate each vulnerability
--ignorefile string specify .trivyignore file (default ".trivyignore")
--include-deprecated-checks include deprecated checks
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--list-all-pkgs enabling the option will output all packages regardless of vulnerability
--max-cache-age duration The maximum age of the cloud cache. Cached data will be required from the cloud provider if it is older than this. (default 24h0m0s)

View File

@@ -31,6 +31,7 @@ trivy config [flags] DIR
-h, --help help for config
--ignore-policy string specify the Rego file path to evaluate each vulnerability
--ignorefile string specify .trivyignore file (default ".trivyignore")
--include-deprecated-checks include deprecated checks
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0)
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])

View File

@@ -49,6 +49,7 @@ trivy filesystem [flags] PATH
--ignore-unfixed display only fixed vulnerabilities
--ignored-licenses strings specify a list of license to ignore
--ignorefile string specify .trivyignore file (default ".trivyignore")
--include-deprecated-checks include deprecated checks
--include-dev-deps include development dependencies in the report (supported: npm, yarn)
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1")

View File

@@ -67,6 +67,7 @@ trivy image [flags] IMAGE_NAME
--ignorefile string specify .trivyignore file (default ".trivyignore")
--image-config-scanners strings comma-separated list of what security issues to detect on container image configurations (misconfig,secret)
--image-src strings image source(s) to use, in priority order (docker,containerd,podman,remote) (default [docker,containerd,podman,remote])
--include-deprecated-checks include deprecated checks
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--input string input file path instead of image name
--java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1")

View File

@@ -62,6 +62,7 @@ trivy kubernetes [flags] [CONTEXT]
--ignore-unfixed display only fixed vulnerabilities
--ignorefile string specify .trivyignore file (default ".trivyignore")
--image-src strings image source(s) to use, in priority order (docker,containerd,podman,remote) (default [docker,containerd,podman,remote])
--include-deprecated-checks include deprecated checks
--include-kinds strings indicate the kinds included in scanning (example: node)
--include-namespaces strings indicate the namespaces included in scanning (example: kube-system)
--include-non-failures include successes and exceptions, available with '--scanners misconfig'

View File

@@ -49,6 +49,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--ignore-unfixed display only fixed vulnerabilities
--ignored-licenses strings specify a list of license to ignore
--ignorefile string specify .trivyignore file (default ".trivyignore")
--include-deprecated-checks include deprecated checks
--include-dev-deps include development dependencies in the report (supported: npm, yarn)
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1")

View File

@@ -52,6 +52,7 @@ trivy rootfs [flags] ROOTDIR
--ignore-unfixed display only fixed vulnerabilities
--ignored-licenses strings specify a list of license to ignore
--ignorefile string specify .trivyignore file (default ".trivyignore")
--include-deprecated-checks include deprecated checks
--include-non-failures include successes and exceptions, available with '--scanners misconfig'
--java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1")
--license-confidence-level float specify license classifier's confidence level (default 0.9)

View File

@@ -383,9 +383,13 @@ misconfiguration:
# Default is false
include-non-failures: false
# Same as '--policy-bundle-repository'
# Same as '--include-deprecated-checks'
# Default is false
include-deprecated-checks: false
# Same as '--check-bundle-repository' and '--policy-bundle-repository'
# Default is 'ghcr.io/aquasecurity/trivy-checks:0'
policy-bundle-repository: ghcr.io/aquasecurity/trivy-checks:0
check-bundle-repository: ghcr.io/aquasecurity/trivy-checks:0
# Same as '--miconfig-scanners'
# Default is all scanners

View File

@@ -3,10 +3,10 @@ Exceptions let you specify cases where you allow policy violations.
Trivy supports two types of exceptions.
!!! info
Exceptions can be applied to built-in policies as well as custom policies.
Exceptions can be applied to built-in checks as well as custom checks.
## Namespace-based exceptions
There are some cases where you need to disable built-in policies partially or fully.
There are some cases where you need to disable built-in checks partially or fully.
Namespace-based exceptions lets you rough choose which individual packages to exempt.
To use namespace-based exceptions, create a Rego rule with the name `exception` that returns the package names to exempt.
@@ -26,7 +26,7 @@ The `exception` rule must be defined under `namespace.exceptions`.
}
```
This example exempts all built-in policies for Kubernetes.
This example exempts all built-in checks for Kubernetes.
## Rule-based exceptions
There are some cases where you need more flexibility and granularity in defining which cases to exempt.
@@ -73,7 +73,7 @@ The above would provide an exception from `deny_foo` and `deny_bar`.
}
```
If you want to apply rule-based exceptions to built-in policies, you have to define the exception under the same package.
If you want to apply rule-based exceptions to built-in checks, you have to define the exception under the same package.
!!! example
``` rego

View File

@@ -1,6 +1,6 @@
# Custom Data
Custom policies may require additional data in order to determine an answer.
Custom checks may require additional data in order to determine an answer.
For example, an allowed list of resources that can be created.
Instead of hardcoding this information inside your policy, Trivy allows passing paths to data files with the `--data` flag.

View File

@@ -1,10 +1,10 @@
# Debugging policies
# Debugging checks
When working on more complex queries (or when learning Rego), it's useful to see exactly how the policy is applied.
For this purpose you can use the `--trace` flag.
This will output a large trace from Open Policy Agent like the following:
!!! tip
Only failed policies show traces. If you want to debug a passed policy, you need to make it fail on purpose.
Only failed checks show traces. If you want to debug a passed check, you need to make it fail on purpose.
```shell
$ trivy conf --trace configs/

View File

@@ -1,8 +1,8 @@
# Custom Policies
# Custom Checks
## Overview
You can write custom policies in [Rego][rego].
Once you finish writing custom policies, you can pass the policy files or the directory where those policies are stored with `--policy` option.
You can write custom checks in [Rego][rego].
Once you finish writing custom checks, you can pass the policy files or the directory where those policies are stored with `--policy` option.
``` bash
trivy conf --policy /path/to/policy.rego --policy /path/to/custom_policies --namespaces user /path/to/config_dir
@@ -120,7 +120,7 @@ Trivy supports extra fields in the `custom` section as described below.
```
All fields are optional. The `schemas` field should be used to enable policy validation using a built-in schema. The
schema that will be used is based on the input document type. It is recommended to use this to ensure your policies are
schema that will be used is based on the input document type. It is recommended to use this to ensure your checks are
correct and do not reference incorrect properties/values.
| Field name | Allowed values | Default value | In table | In JSON |
@@ -131,6 +131,7 @@ correct and do not reference incorrect properties/values.
| custom.id | Any characters | N/A | :material-check: | :material-check: |
| custom.severity | `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` | UNKNOWN | :material-check: | :material-check: |
| custom.recommended_actions | Any characters | | :material-close: | :material-check: |
| custom.deprecated | `true`, `false` | `false` | :material-close: | :material-check: |
| custom.input.selector.type | Any item(s) in [this list][source-types] | | :material-close: | :material-check: |
| url | Any characters | | :material-close: | :material-check: |

View File

@@ -54,7 +54,7 @@ Currently, out of the box the following schemas are supported natively:
3. [Cloud](https://github.com/aquasecurity/trivy/blob/main/pkg/iac/rego/schemas/cloud.json)
## Custom Policies with Custom Schemas
## Custom Checks with Custom Schemas
You can also bring a custom policy that defines one or more custom schema.
@@ -71,21 +71,21 @@ You can also bring a custom policy that defines one or more custom schema.
}
```
The policies can be placed in a structure as follows
The checks can be placed in a structure as follows
!!! example
```
/Users/user/my-custom-policies
/Users/user/my-custom-checks
├── my_policy.rego
└── schemas
└── fooschema.json
└── barschema.json
```
To use such a policy with Trivy, use the `--config-policy` flag that points to the policy file or to the directory where the schemas and policies are contained.
To use such a policy with Trivy, use the `--config-policy` flag that points to the policy file or to the directory where the schemas and checks are contained.
```bash
$ trivy --config-policy=/Users/user/my-custom-policies <path/to/iac>
$ trivy --config-policy=/Users/user/my-custom-checks <path/to/iac>
```
For more details on how to define schemas within Rego policies, please see the [OPA guide](https://www.openpolicyagent.org/docs/latest/policy-language/#schema-annotations) that describes it in more detail.
For more details on how to define schemas within Rego checks, please see the [OPA guide](https://www.openpolicyagent.org/docs/latest/policy-language/#schema-annotations) that describes it in more detail.

View File

@@ -1,9 +1,9 @@
# Testing
It is highly recommended to write tests for your custom policies.
It is highly recommended to write tests for your custom checks.
## Rego testing
To help you verify the correctness of your custom policies, OPA gives you a framework that you can use to write tests for your policies.
By writing tests for your custom policies you can speed up the development process of new rules and reduce the amount of time it takes to modify rules as requirements evolve.
To help you verify the correctness of your custom checks, OPA gives you a framework that you can use to write tests for your checks.
By writing tests for your custom checks you can speed up the development process of new rules and reduce the amount of time it takes to modify rules as requirements evolve.
For more details, see [Policy Testing][opa-testing].
@@ -22,12 +22,12 @@ For more details, see [Policy Testing][opa-testing].
}
```
To write tests for custom policies, you can refer to existing tests under [trivy-checks][trivy-checks].
To write tests for custom checks, you can refer to existing tests under [trivy-checks][trivy-checks].
## Go testing
[Fanal][fanal] which is a core library of Trivy can be imported as a Go library.
You can scan config files in Go and test your custom policies using Go's testing methods, such as [table-driven tests][table].
This allows you to use the actual configuration file as input, making it easy to prepare test data and ensure that your custom policies work in practice.
You can scan config files in Go and test your custom checks using Go's testing methods, such as [table-driven tests][table].
This allows you to use the actual configuration file as input, making it easy to prepare test data and ensure that your custom checks work in practice.
In particular, Dockerfile and HCL need to be converted to structural data as input, which may be different from the expected input format.

View File

@@ -1,6 +1,6 @@
# Misconfiguration Scanning
Trivy provides built-in policies to detect configuration issues in popular Infrastructure as Code files, such as: Docker, Kubernetes, Terraform, CloudFormation, and more.
In addition to built-in policies, you can write your own custom policies, as you can see [here][custom].
Trivy provides built-in checks to detect configuration issues in popular Infrastructure as Code files, such as: Docker, Kubernetes, Terraform, CloudFormation, and more.
In addition to built-in checks, you can write your own custom checks, as you can see [here][custom].
## Quick start
@@ -94,7 +94,7 @@ In the above example, Trivy detected vulnerabilities of Python dependencies and
## Type detection
The specified directory can contain mixed types of IaC files.
Trivy automatically detects config types and applies relevant policies.
Trivy automatically detects config types and applies relevant checks.
For example, the following example holds IaC files for Terraform, CloudFormation, Kubernetes, Helm Charts, and Dockerfile in the same directory.
@@ -326,8 +326,8 @@ trivy config --misconfig-scanners=terraform,dockerfile .
Will only scan for misconfigurations that pertain to Terraform and Dockerfiles.
### Passing custom policies
You can pass policy files or directories including your custom policies through `--policy` option.
### Passing custom checks
You can pass policy files or directories including your custom checks through `--policy` option.
This can be repeated for specifying multiple files or directories.
```bash
@@ -335,7 +335,7 @@ cd examplex/misconf/
trivy conf --policy custom-policy/policy --policy combine/policy --policy policy.rego --namespaces user misconf/mixed
```
For more details, see [Custom Policies](./custom/index.md).
For more details, see [Custom Checks](./custom/index.md).
!!! tip
You also need to specify `--namespaces` option.
@@ -352,8 +352,8 @@ trivy conf --policy ./policy --data ./data --namespaces user ./configs
For more details, see [Custom Data](./custom/data.md).
### Passing namespaces
By default, Trivy evaluates policies defined in `builtin.*`.
If you want to evaluate custom policies in other packages, you have to specify package prefixes through `--namespaces` option.
By default, Trivy evaluates checks defined in `builtin.*`.
If you want to evaluate custom checks in other packages, you have to specify package prefixes through `--namespaces` option.
This can be repeated for specifying multiple packages.
``` bash

View File

@@ -99,11 +99,11 @@ If you want to force the cache to be refreshed with the latest data, you can use
Or if you'd like to use cached data for a different timeframe, you can specify `--max-cache-age` (e.g. `--max-cache-age 2h`.).
Regardless of whether the cache is used or not, rules will be evaluated again with each run of `trivy aws`.
## Custom Policies
## Custom Checks
You can write custom policies for Trivy to evaluate against your AWS account.
These policies are written in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), the same language used by [Open Policy Agent](https://www.openpolicyagent.org/).
See the [Custom Policies](../scanner/misconfiguration/custom/index.md) page for more information on how to write custom policies.
You can write custom checks for Trivy to evaluate against your AWS account.
These checks are written in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), the same language used by [Open Policy Agent](https://www.openpolicyagent.org/).
See the [Custom Checks](../scanner/misconfiguration/custom/index.md) page for more information on how to write custom checks.
Custom policies in cloud scanning also support passing in custom data. This can be useful when you want to selectively enable/disable certain aspects of your cloud policies.
See the [Custom Data](../scanner/misconfiguration/custom/data.md) page for more information on how to provide custom data to custom policies.
Custom checks in cloud scanning also support passing in custom data. This can be useful when you want to selectively enable/disable certain aspects of your cloud checks.
See the [Custom Data](../scanner/misconfiguration/custom/data.md) page for more information on how to provide custom data to custom checks.

View File

@@ -16,7 +16,7 @@ Below is a list of additional resources from the community.
## Misconfiguration Scanning
- [Identifying Misconfigurations in your Terraform](https://youtu.be/cps1V5fOHtE)
- [How to write custom policies for Trivy](https://blog.ediri.io/how-to-write-custom-policies-for-trivy)
- [How to write custom checks for Trivy](https://blog.ediri.io/how-to-write-custom-policies-for-trivy)
## SBOM, Attestation & related

View File

@@ -90,7 +90,7 @@ trivy conf --tf-vars terraform.tfvars ./
```
### Custom Checks
We have lots of examples in the [documentation](https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/custom/) on how you can write and pass custom Rego policies into terraform misconfiguration scans.
We have lots of examples in the [documentation](https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/custom/) on how you can write and pass custom Rego checks into terraform misconfiguration scans.
## Secret and vulnerability scans

2
go.mod
View File

@@ -26,7 +26,7 @@ require (
github.com/aquasecurity/table v1.8.0
github.com/aquasecurity/testdocker v0.0.0-20240419073403-90bd43849334
github.com/aquasecurity/tml v0.6.1
github.com/aquasecurity/trivy-aws v0.8.0
github.com/aquasecurity/trivy-aws v0.8.1-0.20240511051125-4393910b056b
github.com/aquasecurity/trivy-checks v0.10.5-0.20240514040354-93bcb2f8c233
github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48

4
go.sum
View File

@@ -773,8 +773,8 @@ github.com/aquasecurity/testdocker v0.0.0-20240419073403-90bd43849334 h1:MgvbLyL
github.com/aquasecurity/testdocker v0.0.0-20240419073403-90bd43849334/go.mod h1:TKXn7bPfMM52ETP4sjjwkTKCZ18CqCs+I/vtFePSdBc=
github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo=
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
github.com/aquasecurity/trivy-aws v0.8.0 h1:4ij8MiZ2sJUH+vWpSeoGVhPr109ZBcNp7LNLfPuv5Cw=
github.com/aquasecurity/trivy-aws v0.8.0/go.mod h1:Pb9xqOuTKMHVgjsnjvudjqZh3nmzdFqFVfRkXnoIZBM=
github.com/aquasecurity/trivy-aws v0.8.1-0.20240511051125-4393910b056b h1:mBMM6+kLTPaqSxNLO51rL6HiCKL1ElV5RXM+BEAK8fg=
github.com/aquasecurity/trivy-aws v0.8.1-0.20240511051125-4393910b056b/go.mod h1:z638DsULU5CCIk8QZqcj8u2D5IIRzvjq4jI1VDQGda4=
github.com/aquasecurity/trivy-checks v0.10.5-0.20240514040354-93bcb2f8c233 h1:7TnJS1JEmrNfznu1Y9Rzbboxl7J4hxjIKQ8tV3k5UQs=
github.com/aquasecurity/trivy-checks v0.10.5-0.20240514040354-93bcb2f8c233/go.mod h1:+G8Ft1pJAmsSPzfSQHdSQ5zcWHWPOxVdQHHA+eHP3eU=
github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d h1:fjI9mkoTUAkbGqpzt9nJsO24RAdfG+ZSiLFj0G2jO8c=

View File

@@ -57,7 +57,7 @@ nav:
- Policy:
- Built-in Checks: docs/scanner/misconfiguration/check/builtin.md
- Exceptions: docs/scanner/misconfiguration/check/exceptions.md
- Custom Policies:
- Custom Checks:
- Overview: docs/scanner/misconfiguration/custom/index.md
- Data: docs/scanner/misconfiguration/custom/data.md
- Combine: docs/scanner/misconfiguration/custom/combine.md

View File

@@ -587,6 +587,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
K8sVersion: opts.K8sVersion,
DisableEmbeddedPolicies: disableEmbedded,
DisableEmbeddedLibraries: disableEmbedded,
IncludeDeprecatedChecks: opts.IncludeDeprecatedChecks,
TfExcludeDownloaded: opts.TfExcludeDownloaded,
}
}

View File

@@ -7,6 +7,11 @@ package flag
// config-policy: "custom-policy/policy"
// policy-namespaces: "user"
var (
IncludeDeprecatedChecksFlag = Flag[bool]{
Name: "include-deprecated-checks",
ConfigName: "rego.include-deprecated-checks",
Usage: "include deprecated checks",
}
SkipCheckUpdateFlag = Flag[bool]{
Name: "skip-check-update",
ConfigName: "rego.skip-check-update",
@@ -53,28 +58,31 @@ var (
// RegoFlagGroup composes common printer flag structs used for commands providing misconfinguration scanning.
type RegoFlagGroup struct {
SkipCheckUpdate *Flag[bool]
Trace *Flag[bool]
CheckPaths *Flag[[]string]
DataPaths *Flag[[]string]
CheckNamespaces *Flag[[]string]
IncludeDeprecatedChecks *Flag[bool]
SkipCheckUpdate *Flag[bool]
Trace *Flag[bool]
CheckPaths *Flag[[]string]
DataPaths *Flag[[]string]
CheckNamespaces *Flag[[]string]
}
type RegoOptions struct {
SkipCheckUpdate bool
Trace bool
CheckPaths []string
DataPaths []string
CheckNamespaces []string
IncludeDeprecatedChecks bool
SkipCheckUpdate bool
Trace bool
CheckPaths []string
DataPaths []string
CheckNamespaces []string
}
func NewRegoFlagGroup() *RegoFlagGroup {
return &RegoFlagGroup{
SkipCheckUpdate: SkipCheckUpdateFlag.Clone(),
Trace: TraceFlag.Clone(),
CheckPaths: ConfigCheckFlag.Clone(),
DataPaths: ConfigDataFlag.Clone(),
CheckNamespaces: CheckNamespaceFlag.Clone(),
IncludeDeprecatedChecks: IncludeDeprecatedChecksFlag.Clone(),
SkipCheckUpdate: SkipCheckUpdateFlag.Clone(),
Trace: TraceFlag.Clone(),
CheckPaths: ConfigCheckFlag.Clone(),
DataPaths: ConfigDataFlag.Clone(),
CheckNamespaces: CheckNamespaceFlag.Clone(),
}
}
@@ -84,6 +92,7 @@ func (f *RegoFlagGroup) Name() string {
func (f *RegoFlagGroup) Flags() []Flagger {
return []Flagger{
f.IncludeDeprecatedChecks,
f.SkipCheckUpdate,
f.Trace,
f.CheckPaths,
@@ -98,10 +107,11 @@ func (f *RegoFlagGroup) ToOptions() (RegoOptions, error) {
}
return RegoOptions{
SkipCheckUpdate: f.SkipCheckUpdate.Value(),
Trace: f.Trace.Value(),
CheckPaths: f.CheckPaths.Value(),
DataPaths: f.DataPaths.Value(),
CheckNamespaces: f.CheckNamespaces.Value(),
IncludeDeprecatedChecks: f.IncludeDeprecatedChecks.Value(),
SkipCheckUpdate: f.SkipCheckUpdate.Value(),
Trace: f.Trace.Value(),
CheckPaths: f.CheckPaths.Value(),
DataPaths: f.DataPaths.Value(),
CheckNamespaces: f.CheckNamespaces.Value(),
}, nil
}

View File

@@ -5,6 +5,7 @@ import (
checks "github.com/aquasecurity/trivy-checks"
"github.com/aquasecurity/trivy/pkg/iac/rules"
"github.com/aquasecurity/trivy/pkg/iac/scan"
"github.com/open-policy-agent/opa/ast"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -103,3 +104,102 @@ deny[res]{
})
}
}
func Test_RegisterDeprecatedRule(t *testing.T) {
var testCases = []struct {
name string
id string
inputPolicy string
expected scan.Rule
}{
{
name: "deprecated check",
id: "AVD-DEP-0001",
inputPolicy: `# METADATA
# title: "deprecated check"
# description: "some description"
# scope: package
# schemas:
# - input: schema["dockerfile"]
# custom:
# avd_id: AVD-DEP-0001
# input:
# selector:
# - type: dockerfile
# deprecated: true
package builtin.dockerfile.DS1234
deny[res]{
res := true
}`,
expected: scan.Rule{
Deprecated: true,
},
},
{
name: "not a deprecated check",
id: "AVD-NOTDEP-0001",
inputPolicy: `# METADATA
# title: "not a deprecated check"
# description: "some description"
# scope: package
# schemas:
# - input: schema["dockerfile"]
# custom:
# avd_id: AVD-NOTDEP-0001
# input:
# selector:
# - type: dockerfile
package builtin.dockerfile.DS1234
deny[res]{
res := true
}`,
expected: scan.Rule{
Deprecated: false,
},
},
{
name: "invalid deprecation value",
id: "AVD-BADDEP-0001",
inputPolicy: `# METADATA
# title: "badly deprecated check"
# description: "some description"
# scope: package
# schemas:
# - input: schema["dockerfile"]
# custom:
# avd_id: AVD-BADDEP-0001
# input:
# selector:
# - type: dockerfile
# deprecated: "this is bad, deprecation is a bool value not a string"
package builtin.dockerfile.DS1234
deny[res]{
res := true
}`,
expected: scan.Rule{
Deprecated: false,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
policies := make(map[string]*ast.Module)
newRule, err := ast.ParseModuleWithOpts("/rules/newrule.rego", tc.inputPolicy, ast.ParserOptions{
ProcessAnnotation: true,
})
require.NoError(t, err)
policies["/rules/newrule.rego"] = newRule
assert.NotPanics(t, func() {
RegisterRegoRules(policies)
})
for _, rule := range rules.GetRegistered() {
if rule.AVDID == tc.id {
assert.Equal(t, tc.expected.Deprecated, rule.GetRule().Deprecated, tc.name)
}
}
})
}
}

View File

@@ -100,12 +100,12 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b
if len(paths) > 0 {
loaded, err := LoadPoliciesFromDirs(srcFS, paths...)
if err != nil {
return fmt.Errorf("failed to load rego policies from %s: %w", paths, err)
return fmt.Errorf("failed to load rego checks from %s: %w", paths, err)
}
for name, policy := range loaded {
s.policies[name] = policy
}
s.debug.Log("Loaded %d policies from disk.", len(loaded))
s.debug.Log("Loaded %d checks from disk.", len(loaded))
}
if len(readers) > 0 {

View File

@@ -20,6 +20,7 @@ import (
const annotationScopePackage = "package"
type StaticMetadata struct {
Deprecated bool
ID string
AVDID string
Title string
@@ -70,6 +71,12 @@ func (sm *StaticMetadata) Update(meta map[string]any) error {
upd(&sm.RecommendedActions, "recommended_actions")
upd(&sm.RecommendedActions, "recommended_action")
if raw, ok := meta["deprecated"]; ok {
if dep, ok := raw.(bool); ok {
sm.Deprecated = dep
}
}
if raw, ok := meta["severity"]; ok {
sm.Severity = strings.ToUpper(fmt.Sprintf("%s", raw))
}
@@ -208,6 +215,7 @@ func (m StaticMetadata) ToRule() scan.Rule {
}
return scan.Rule{
Deprecated: m.Deprecated,
AVDID: m.AVDID,
Aliases: append(m.Aliases, m.ID),
ShortCode: m.ShortCode,

View File

@@ -117,6 +117,23 @@ func Test_UpdateStaticMetadata(t *testing.T) {
assert.Equal(t, expected, sm)
})
t.Run("check is deprecated", func(t *testing.T) {
sm := StaticMetadata{
Deprecated: false,
}
require.NoError(t, sm.Update(map[string]any{
"deprecated": true,
}))
expected := StaticMetadata{
Deprecated: true,
CloudFormation: &scan.EngineMetadata{},
Terraform: &scan.EngineMetadata{},
}
assert.Equal(t, expected, sm)
})
}
func Test_getEngineMetadata(t *testing.T) {

View File

@@ -26,28 +26,33 @@ import (
var _ options.ConfigurableScanner = (*Scanner)(nil)
type Scanner struct {
ruleNamespaces map[string]struct{}
policies map[string]*ast.Module
store storage.Store
dataDirs []string
runtimeValues *ast.Term
compiler *ast.Compiler
regoErrorLimit int
debug debug.Logger
traceWriter io.Writer
tracePerResult bool
retriever *MetadataRetriever
policyFS fs.FS
dataFS fs.FS
frameworks []framework.Framework
spec string
inputSchema interface{} // unmarshalled into this from a json schema document
sourceType types.Source
ruleNamespaces map[string]struct{}
policies map[string]*ast.Module
store storage.Store
dataDirs []string
runtimeValues *ast.Term
compiler *ast.Compiler
regoErrorLimit int
debug debug.Logger
traceWriter io.Writer
tracePerResult bool
retriever *MetadataRetriever
policyFS fs.FS
dataFS fs.FS
frameworks []framework.Framework
spec string
inputSchema interface{} // unmarshalled into this from a json schema document
sourceType types.Source
includeDeprecatedChecks bool
embeddedLibs map[string]*ast.Module
embeddedChecks map[string]*ast.Module
}
func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {
s.includeDeprecatedChecks = b
}
func (s *Scanner) SetUseEmbeddedLibraries(b bool) {
// handled externally
}
@@ -248,6 +253,10 @@ func (s *Scanner) ScanInput(ctx context.Context, inputs ...Input) (scan.Results,
continue
}
if !s.includeDeprecatedChecks && staticMeta.Deprecated {
continue // skip deprecated checks
}
if isPolicyWithSubtype(s.sourceType) {
// skip if check isn't relevant to what is being scanned
if !isPolicyApplicable(staticMeta, inputs...) {

View File

@@ -1011,3 +1011,78 @@ deny {
assert.Contains(t, buf.String(),
`Error occurred while applying rule "deny" from check "checks/bad.rego"`)
}
func Test_RegoScanning_WithDeprecatedCheck(t *testing.T) {
var testCases = []struct {
name string
policy string
expectedResults int
}{
{
name: "happy path check is deprecated",
policy: `# METADATA
# title: i am a deprecated check
# description: i am a description
# related_resources:
# - https://google.com
# custom:
# id: EG123
# avd_id: AVD-EG-0123
# severity: LOW
# recommended_action: have a cup of tea
# deprecated: true
package defsec.test
deny {
input.text
}
`,
expectedResults: 0,
},
{
name: "happy path check is not deprecated",
policy: `# METADATA
# title: i am a deprecated check
# description: i am a description
# related_resources:
# - https://google.com
# custom:
# id: EG123
# avd_id: AVD-EG-0123
# severity: LOW
# recommended_action: have a cup of tea
package defsec.test
deny {
input.text
}
`,
expectedResults: 1,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
srcFS := CreateFS(t, map[string]string{
"policies/test.rego": tc.policy,
})
scanner := NewScanner(types.SourceJSON)
require.NoError(
t,
scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil),
)
results, err := scanner.ScanInput(context.TODO(), Input{
Path: "/evil.lol",
Contents: map[string]interface{}{
"text": "test",
},
})
require.NoError(t, err)
require.Len(t, results, tc.expectedResults, tc.name)
})
}
}

View File

@@ -6,6 +6,7 @@ import (
)
type FlatResult struct {
Deprecated bool `json:"deprecated,omitempty"`
RuleID string `json:"rule_id"`
LongID string `json:"long_id"`
RuleSummary string `json:"rule_description"`
@@ -48,6 +49,7 @@ func (r *Result) Flatten() FlatResult {
}
return FlatResult{
Deprecated: r.rule.Deprecated,
RuleID: r.rule.AVDID,
LongID: r.Rule().LongID(),
RuleSummary: r.rule.Summary,

View File

@@ -36,6 +36,7 @@ type TerraformCustomCheck struct {
}
type Rule struct {
Deprecated bool `json:"deprecated"`
AVDID string `json:"avd_id"`
Aliases []string `json:"aliases"`
ShortCode string `json:"short_code"`
@@ -55,6 +56,10 @@ type Rule struct {
Check CheckFunc `json:"-"`
}
func (r Rule) IsDeprecated() bool {
return r.Deprecated
}
func (r Rule) HasID(id string) bool {
if r.AVDID == id || r.LongID() == id {
return true

View File

@@ -40,6 +40,8 @@ type Scanner struct { // nolint: gocritic
sync.Mutex
}
func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {}
func (s *Scanner) SetSpec(spec string) {
s.spec = spec
}

View File

@@ -64,6 +64,8 @@ type Scanner struct { // nolint: gocritic
sync.Mutex
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) addParserOptions(opt options.ParserOption) {
s.parserOptions = append(s.parserOptions, opt)
}

View File

@@ -34,6 +34,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedPolicies bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetSpec(spec string) {
s.spec = spec
}

View File

@@ -43,6 +43,8 @@ type Scanner struct {
mu sync.Mutex
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetSpec(spec string) {
s.spec = spec
}

View File

@@ -34,6 +34,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedLibraries bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetRegoOnly(bool) {
}

View File

@@ -38,6 +38,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedLibraries bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetSpec(spec string) {
s.spec = spec
}

View File

@@ -24,6 +24,7 @@ type ConfigurableScanner interface {
SetRegoOnly(regoOnly bool)
SetRegoErrorLimit(limit int)
SetUseEmbeddedLibraries(bool)
SetIncludeDeprecatedChecks(bool)
}
type ScannerOption func(s ConfigurableScanner)
@@ -65,6 +66,12 @@ func ScannerWithEmbeddedLibraries(enabled bool) ScannerOption {
}
}
func ScannerWithIncludeDeprecatedChecks(enabled bool) ScannerOption {
return func(s ConfigurableScanner) {
s.SetIncludeDeprecatedChecks(enabled)
}
}
// ScannerWithTrace specifies an io.Writer for trace logs (mainly rego tracing) - if not set, they are discarded
func ScannerWithTrace(w io.Writer) ScannerOption {
return func(s ConfigurableScanner) {

View File

@@ -45,6 +45,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedPolicies bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {}
func (s *Scanner) SetSpec(spec string) {
s.spec = spec
}

View File

@@ -38,6 +38,8 @@ type Scanner struct {
policyReaders []io.Reader
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetUseEmbeddedLibraries(b bool) {
s.loadEmbeddedLibraries = b
}

View File

@@ -32,6 +32,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedLibraries bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetRegoOnly(bool) {}
func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {

View File

@@ -32,6 +32,8 @@ type Scanner struct { // nolint: gocritic
loadEmbeddedPolicies bool
}
func (s *Scanner) SetIncludeDeprecatedChecks(bool) {}
func (s *Scanner) SetRegoOnly(bool) {}
func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {

View File

@@ -54,6 +54,7 @@ type ScannerOption struct {
DataPaths []string
DisableEmbeddedPolicies bool
DisableEmbeddedLibraries bool
IncludeDeprecatedChecks bool
HelmValues []string
HelmValueFiles []string
@@ -217,6 +218,7 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO
options.ScannerWithSkipRequiredCheck(true),
options.ScannerWithEmbeddedPolicies(!opt.DisableEmbeddedPolicies),
options.ScannerWithEmbeddedLibraries(!opt.DisableEmbeddedLibraries),
options.ScannerWithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks),
}
policyFS, policyPaths, err := CreatePolicyFS(opt.PolicyPaths)