refactor: rename security-checks to scanners (#3467)

This commit is contained in:
Teppei Fukuda
2023-01-23 16:53:06 +02:00
committed by GitHub
parent aaf845d02e
commit e1076085d9
53 changed files with 1100 additions and 719 deletions

View File

@@ -54,7 +54,7 @@ Trivy is integrated with many popular platforms and applications. The complete l
### General usage
```bash
trivy <target> [--security-checks <scanner1,scanner2>] <subject>
trivy <target> [--scanners <scanner1,scanner2>] <subject>
```
Examples:
@@ -71,7 +71,7 @@ https://user-images.githubusercontent.com/1161307/171013513-95f18734-233d-45d3-a
</details>
```bash
trivy fs --security-checks vuln,secret,config myproject/
trivy fs --scanners vuln,secret,config myproject/
```
<details>

View File

@@ -21,7 +21,7 @@ You need to pass `--sbom-sources rekor` so that Trivy will look for SBOM attesta
$ trivy image --sbom-sources rekor otms61/alpine:3.7.3 [~/src/github.com/aquasecurity/trivy]
2022-09-16T17:37:13.258+0900 INFO Vulnerability scanning is enabled
2022-09-16T17:37:13.258+0900 INFO Secret scanning is enabled
2022-09-16T17:37:13.258+0900 INFO If your scanning is slow, please try '--security-checks vuln' to disable secret scanning
2022-09-16T17:37:13.258+0900 INFO If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2022-09-16T17:37:13.258+0900 INFO Please see also https://aquasecurity.github.io/trivy/dev/docs/secret/scanning/#recommendation for faster secret detection
2022-09-16T17:37:14.827+0900 INFO Detected SBOM format: cyclonedx-json
2022-09-16T17:37:14.901+0900 INFO Found SBOM (cyclonedx) attestation in Rekor
@@ -105,7 +105,7 @@ Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0)
Also, it is applied to non-packaged binaries even in container images.
```bash
$ trivy image --sbom-sources rekor --security-checks vuln alpine-with-bat
$ trivy image --sbom-sources rekor --scanners vuln alpine-with-bat
2022-10-25T13:40:14.920+0300 INFO Vulnerability scanning is enabled
2022-10-25T13:40:18.047+0300 INFO Found SBOM attestation in Rekor: bat
2022-10-25T13:40:18.186+0300 INFO Detected OS: alpine

View File

@@ -27,12 +27,12 @@ Filter by severity:
$ trivy k8s --severity=CRITICAL --report=all cluster
```
Filter by security check (Vulnerabilities, Secrets or Misconfigurations):
Filter by scanners (Vulnerabilities, Secrets or Misconfigurations):
```
$ trivy k8s --security-checks=secret --report=summary cluster
$ trivy k8s --scanners=secret --report=summary cluster
# or
$ trivy k8s --security-checks=config --report=summary cluster
$ trivy k8s --scanners=config --report=summary cluster
```
Scan a specific namespace:
@@ -263,16 +263,16 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN
The infra checks are based on CIS Benchmarks recommendations for kubernetes.
If you want filter only for the infra checks, you can use the flag `--components` along with the `--security-checks=config`
If you want filter only for the infra checks, you can use the flag `--components` along with the `--scanners=config`
```
$ trivy k8s cluster --report summary --components=infra --security-checks=config # scan only infra
$ trivy k8s cluster --report summary --components=infra --scanners=config # scan only infra
```
Or, to filter for all other checks besides the infra checks, you can:
```
$ trivy k8s cluster --report summary --components=workload --security-checks=config # scan all components besides infra
$ trivy k8s cluster --report summary --components=workload --scanners=config # scan all components besides infra
```

View File

@@ -47,10 +47,10 @@ License checking classifies the identified licenses and map the classification t
This section shows how to scan license in container image and filesystem.
### Standard scanning
Specify an image name with `--security-checks license`.
Specify an image name with `--scanners license`.
``` shell
$ trivy image --security-checks license --severity UNKNOWN,HIGH,CRITICAL alpine:3.15
$ trivy image --scanners license --severity UNKNOWN,HIGH,CRITICAL alpine:3.15
2022-07-13T17:28:39.526+0300 INFO License scanning is enabled
OS Packages (license)
@@ -78,7 +78,7 @@ Total: 6 (UNKNOWN: 0, HIGH: 6, CRITICAL: 0)
Specify `--license-full`
``` shell
$ trivy image --security-checks license --severity UNKNOWN,HIGH,CRITICAL --license-full grafana/grafana
$ trivy image --scanners license --severity UNKNOWN,HIGH,CRITICAL --license-full grafana/grafana
2022-07-13T17:48:40.905+0300 INFO Full license scanning is enabled
OS Packages (license)
@@ -141,7 +141,7 @@ Trivy has number of configuration flags for use with license scanning;
Trivy license scanning can ignore licenses that are identified to explicitly remove them from the results using the `--ignored-licenses` flag;
```shell
$ trivy image --security-checks license --ignored-licenses MPL-2.0,MIT --severity LOW grafana/grafana:latest
$ trivy image --scanners license --ignored-licenses MPL-2.0,MIT --severity LOW grafana/grafana:latest
2022-07-13T18:15:28.605Z INFO License scanning is enabled
OS Packages (license)

View File

@@ -37,28 +37,28 @@ $ trivy config [YOUR_IaC_DIRECTORY]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```
You can also enable misconfiguration detection in container image, filesystem and git repository scanning via `--security-checks config`.
You can also enable misconfiguration detection in container image, filesystem and git repository scanning via `--scanners config`.
```bash
$ trivy image --security-checks config IMAGE_NAME
$ trivy image --scanners config IMAGE_NAME
```
```bash
$ trivy fs --security-checks config /path/to/dir
$ trivy fs --scanners config /path/to/dir
```
!!! note
Misconfiguration detection is not enabled by default in `image`, `fs` and `repo` subcommands.
Unlike the `config` subcommand, `image`, `fs` and `repo` subcommands can also scan for vulnerabilities and secrets at the same time.
You can specify `--security-checks vuln,config,secret` to enable vulnerability and secret detection as well as misconfiguration detection.
You can specify `--scanners vuln,config,secret` to enable vulnerability and secret detection as well as misconfiguration detection.
!!! example
``` bash
$ ls myapp/
Dockerfile Pipfile.lock
$ trivy fs --security-checks vuln,config,secret --severity HIGH,CRITICAL myapp/
$ trivy fs --scanners vuln,config,secret --severity HIGH,CRITICAL myapp/
2022-05-16T13:42:21.440+0100 INFO Number of language-specific files: 1
2022-05-16T13:42:21.440+0100 INFO Detecting pipenv vulnerabilities...
2022-05-16T13:42:21.440+0100 INFO Detected config files: 1

View File

@@ -9,7 +9,7 @@ Aliases:
Scan Flags
--offline-scan do not issue API requests to identify dependencies
--security-checks string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--scanners string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal
@@ -47,8 +47,8 @@ Vulnerability Flags
Misconfiguration Flags
--config-data strings specify paths from which data for the Rego policies will be recursively loaded
--config-policy strings specify paths to the Rego policy files directory, applying config files
--file-patterns strings specify config file patterns, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--security-checks config'
--file-patterns strings specify config file patterns, available with '--scanners config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--policy-namespaces strings Rego namespaces
--trace enable more verbose trace output for custom queries

View File

@@ -32,8 +32,8 @@ Cache Flags
Misconfiguration Flags
--config-data strings specify paths from which data for the Rego policies will be recursively loaded
--config-policy strings specify paths to the Rego policy files directory, applying config files
--file-patterns strings specify config file patterns, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--security-checks config'
--file-patterns strings specify config file patterns, available with '--scanners config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--policy-namespaces strings Rego namespaces
--trace enable more verbose trace output for custom queries

View File

@@ -18,7 +18,7 @@ Examples:
Scan Flags
--offline-scan do not issue API requests to identify dependencies
--security-checks string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--scanners string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal
@@ -55,8 +55,8 @@ Vulnerability Flags
Misconfiguration Flags
--config-data strings specify paths from which data for the Rego policies will be recursively loaded
--config-policy strings specify paths to the Rego policy files directory, applying config files
--file-patterns strings specify config file patterns, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--security-checks config'
--file-patterns strings specify config file patterns, available with '--scanners config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--policy-namespaces strings Rego namespaces
--trace enable more verbose trace output for custom queries

View File

@@ -33,7 +33,7 @@ Examples:
Scan Flags
--offline-scan do not issue API requests to identify dependencies
--security-checks string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--scanners string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal
@@ -73,8 +73,8 @@ Vulnerability Flags
Misconfiguration Flags
--config-data strings specify paths from which data for the Rego policies will be recursively loaded
--config-policy strings specify paths to the Rego policy files directory, applying config files
--file-patterns strings specify config file patterns, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--security-checks config'
--file-patterns strings specify config file patterns, available with '--scanners config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--policy-namespaces strings Rego namespaces
--trace enable more verbose trace output for custom queries

View File

@@ -15,7 +15,7 @@ Examples:
Scan Flags
--offline-scan do not issue API requests to identify dependencies
--security-checks string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--scanners string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal
@@ -52,8 +52,8 @@ Vulnerability Flags
Misconfiguration Flags
--config-data strings specify paths from which data for the Rego policies will be recursively loaded
--config-policy strings specify paths to the Rego policy files directory, applying config files
--file-patterns strings specify config file patterns, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--security-checks config'
--file-patterns strings specify config file patterns, available with '--scanners config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--policy-namespaces strings Rego namespaces
--trace enable more verbose trace output for custom queries

View File

@@ -21,7 +21,7 @@ Scan Flags
--offline-scan do not issue API requests to identify dependencies
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (rekor)
--security-checks strings comma-separated list of what security issues to detect (vuln,config,secret,license) (default [vuln,secret])
--scanners strings comma-separated list of what security issues to detect (vuln,config,secret,license) (default [vuln,secret])
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal
@@ -60,7 +60,7 @@ Misconfiguration Flags
--helm-set-file strings specify Helm values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)
--helm-set-string strings specify Helm string values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
--helm-values strings specify paths to override the Helm values.yaml files
--include-non-failures include successes and exceptions, available with '--security-checks config'
--include-non-failures include successes and exceptions, available with '--scanners config'
--tf-vars strings specify paths to override the Terraform tfvars files
Secret Flags

View File

@@ -19,7 +19,7 @@ Examples:
Scan Flags
--offline-scan do not issue API requests to identify dependencies
--security-checks string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--scanners string comma-separated list of what security issues to detect (vuln,config,secret) (default "vuln,secret")
--skip-dirs strings specify the directories where the traversal is skipped
--skip-files strings specify the file paths to skip traversal

View File

@@ -102,9 +102,9 @@ scan:
# Default is false
offline-scan: false
# Same as '--security-checks'
# Same as '--scanners'
# Default depends on subcommand
security-checks:
scanners:
- vuln
- config
- secret

View File

@@ -15,7 +15,7 @@ By default, `--format cyclonedx` represents SBOM and doesn't include vulnerabili
```
$ trivy image --format cyclonedx --output result.json alpine:3.15
2022-07-19T07:47:27.624Z INFO "--format cyclonedx" disables security checks. Specify "--security-checks vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.
2022-07-19T07:47:27.624Z INFO "--format cyclonedx" disables security scanning. Specify "--scanners vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.
```
<details>
@@ -239,10 +239,10 @@ $ cat result.json | jq .
</details>
If you want to include vulnerabilities, you can enable vulnerability scanning via `--security-checks vuln`.
If you want to include vulnerabilities, you can enable vulnerability scanning via `--scanners vuln`.
```
$ trivy image --security-checks vuln --format cyclonedx --output result.json alpine:3.15
$ trivy image --scanners vuln --format cyclonedx --output result.json alpine:3.15
```
## Scanning

View File

@@ -48,10 +48,10 @@ aws-account-id
```
## Disable secret scanning
If you need vulnerability scanning only, you can disable secret scanning via the `--security-checks` flag.
If you need vulnerability scanning only, you can disable secret scanning via the `--scanners` flag.
``` shell
$ trivy image --security-checks vuln alpine:3.15
$ trivy image --scanners vuln alpine:3.15
```
## With configuration file

View File

@@ -106,10 +106,10 @@ All rules are disabled except for the ones you specify, so it runs very fast.
On the other hand, you should use `disable-rules` if you just want to disable some built-in rules.
See the [enable-rules][enable-rules] and [disable-rules][disable-rules] sections for the detail.
If you don't need secret scanning, you can disable it via the `--security-checks` flag.
If you don't need secret scanning, you can disable it via the `--scanners` flag.
```shell
$ trivy image --security-checks vuln alpine:3.15
$ trivy image --scanners vuln alpine:3.15
```

View File

@@ -19,11 +19,11 @@ $ trivy vm ami:${your_ami_id}
### Example
```shell
$ trivy vm --security-checks vuln ami:ami-0123456789abcdefg
$ trivy vm --scanners vuln ami:ami-0123456789abcdefg
```
!!! tip
The scanning could be faster if you enable only vulnerability scanning (`--security-checks vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
The scanning could be faster if you enable only vulnerability scanning (`--scanners vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
If you want to scan a AMI of non-default setting region, you can set any region via `--aws-region` option.
@@ -52,11 +52,11 @@ $ trivy vm ebs:${your_ebs_snapshot_id}
### Example
```shell
$ trivy vm --security-checks vuln ebs:snap-0123456789abcdefg
$ trivy vm --scanners vuln ebs:snap-0123456789abcdefg
```
!!! tip
The scanning could be faster if you enable only vulnerability scanning (`--security-checks vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
The scanning could be faster if you enable only vulnerability scanning (`--scanners vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
If you want to scan an EBS Snapshot of non-default setting region, you can set any region via `--aws-region` option.

View File

@@ -16,7 +16,7 @@ To scan VM images, you can use the `vm` subcommand.
Pass the path to your local VM image file.
```bash
$ trivy vm --security-checks vuln disk.vmdk
$ trivy vm --scanners vuln disk.vmdk
```
<details>

View File

@@ -40,7 +40,7 @@ The following table provides an outline of the features Trivy offers.
33.25 MiB / 33.25 MiB [------------------------------] 100.00% 4.20 MiB p/s 8.1s
2022-07-27T09:30:21.756Z INFO Vulnerability scanning is enabled
2022-07-27T09:30:21.756Z INFO Secret scanning is enabled
2022-07-27T09:30:21.756Z INFO If your scanning is slow, please try '--security-checks vuln' to disable secret scanning
2022-07-27T09:30:21.756Z INFO If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2022-07-27T09:30:21.756Z INFO Please see also https://aquasecurity.github.io/trivy/v0.30.4/docs/secret/scanning/#recommendation for faster secret detection
2022-07-27T09:30:22.205Z INFO Detected OS: cbl-mariner
2022-07-27T09:30:22.205Z INFO Detecting CBL-Mariner vulnerabilities...

View File

@@ -37,7 +37,7 @@ $ trivy image --platform=linux/arm alpine:3.16.1
```
2022-10-25T21:00:50.972+0300 INFO Vulnerability scanning is enabled
2022-10-25T21:00:50.972+0300 INFO Secret scanning is enabled
2022-10-25T21:00:50.972+0300 INFO If your scanning is slow, please try '--security-checks vuln' to disable secret scanning
2022-10-25T21:00:50.972+0300 INFO If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2022-10-25T21:00:50.972+0300 INFO Please see also https://aquasecurity.github.io/trivy/dev/docs/secret/scanning/#recommendation for faster secret detection
2022-10-25T21:00:56.190+0300 INFO Detected OS: alpine
2022-10-25T21:00:56.190+0300 INFO Detecting Alpine vulnerabilities...

View File

@@ -58,7 +58,7 @@ Trivy is integrated with many popular platforms and applications. The complete l
### General usage
```bash
trivy <target> [--security-checks <scanner1,scanner2>] <subject>
trivy <target> [--scanners <scanner1,scanner2>] <subject>
```
Examples:
@@ -80,7 +80,7 @@ trivy image python:3.4-alpine
</details>
```bash
trivy fs --security-checks vuln,secret,config myproject/
trivy fs --scanners vuln,secret,config myproject/
```
<details>

View File

@@ -150,7 +150,7 @@ trivy:
# Image report
- ./trivy image --exit-code 0 --format template --template "@contrib/gitlab-codequality.tpl" -o gl-codeclimate-image.json $IMAGE
# Filesystem report
- ./trivy filesystem --security-checks config,vuln --exit-code 0 --format template --template "@contrib/gitlab-codequality.tpl" -o gl-codeclimate-fs.json .
- ./trivy filesystem --scanners config,vuln --exit-code 0 --format template --template "@contrib/gitlab-codequality.tpl" -o gl-codeclimate-fs.json .
# Combine report
- apk update && apk add jq
- jq -s 'add' gl-codeclimate-image.json gl-codeclimate-fs.json > gl-codeclimate.json

View File

@@ -14,7 +14,7 @@ scan:
- /usr/lib
- /usr/include
security-checks:
scanners:
- vuln
- secret
vulnerability:

View File

@@ -11,11 +11,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/types"
)
func TestFilesystem(t *testing.T) {
type args struct {
securityChecks string
scanners string
severity []string
ignoreIDs []string
policyPaths []string
@@ -39,7 +41,7 @@ func TestFilesystem(t *testing.T) {
{
name: "gomod",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/gomod",
},
golden: "testdata/gomod.json.golden",
@@ -47,7 +49,7 @@ func TestFilesystem(t *testing.T) {
{
name: "gomod with skip files",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/gomod",
skipFiles: []string{"testdata/fixtures/fs/gomod/submod2/go.mod"},
},
@@ -56,7 +58,7 @@ func TestFilesystem(t *testing.T) {
{
name: "gomod with skip dirs",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/gomod",
skipDirs: []string{"testdata/fixtures/fs/gomod/submod2"},
},
@@ -65,7 +67,7 @@ func TestFilesystem(t *testing.T) {
{
name: "nodejs",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/nodejs",
listAllPkgs: true,
},
@@ -74,7 +76,7 @@ func TestFilesystem(t *testing.T) {
{
name: "yarn",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/yarn",
listAllPkgs: true,
},
@@ -83,7 +85,7 @@ func TestFilesystem(t *testing.T) {
{
name: "pnpm",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/pnpm",
},
golden: "testdata/pnpm.json.golden",
@@ -91,7 +93,7 @@ func TestFilesystem(t *testing.T) {
{
name: "pip",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/pip",
},
@@ -100,7 +102,7 @@ func TestFilesystem(t *testing.T) {
{
name: "pom",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/pom",
},
golden: "testdata/pom.json.golden",
@@ -108,7 +110,7 @@ func TestFilesystem(t *testing.T) {
{
name: "gradle",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
input: "testdata/fixtures/fs/gradle",
},
golden: "testdata/gradle.json.golden",
@@ -116,7 +118,7 @@ func TestFilesystem(t *testing.T) {
{
name: "conan",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/conan",
},
@@ -125,7 +127,7 @@ func TestFilesystem(t *testing.T) {
{
name: "nuget",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/nuget",
},
@@ -134,7 +136,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dotnet",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/dotnet",
},
@@ -143,7 +145,7 @@ func TestFilesystem(t *testing.T) {
{
name: "cocoapods",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/cocoapods",
},
@@ -152,7 +154,7 @@ func TestFilesystem(t *testing.T) {
{
name: "pubspec.lock",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/pubspec",
},
@@ -161,7 +163,7 @@ func TestFilesystem(t *testing.T) {
{
name: "mix.lock",
args: args{
securityChecks: "vuln",
scanners: types.VulnerabilityScanner,
listAllPkgs: true,
input: "testdata/fixtures/fs/mixlock",
},
@@ -170,7 +172,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dockerfile",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/dockerfile",
namespaces: []string{"testing"},
},
@@ -179,7 +181,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dockerfile with custom file pattern",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/dockerfile_file_pattern",
namespaces: []string{"testing"},
filePatterns: []string{"dockerfile:Customfile"},
@@ -189,7 +191,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dockerfile with rule exception",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
policyPaths: []string{"testdata/fixtures/fs/rule-exception/policy"},
input: "testdata/fixtures/fs/rule-exception",
},
@@ -198,7 +200,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dockerfile with namespace exception",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
policyPaths: []string{"testdata/fixtures/fs/namespace-exception/policy"},
input: "testdata/fixtures/fs/namespace-exception",
},
@@ -207,7 +209,7 @@ func TestFilesystem(t *testing.T) {
{
name: "dockerfile with custom policies",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
policyPaths: []string{"testdata/fixtures/fs/custom-policy/policy"},
namespaces: []string{"user"},
input: "testdata/fixtures/fs/custom-policy",
@@ -217,7 +219,7 @@ func TestFilesystem(t *testing.T) {
{
name: "tarball helm chart scanning with builtin policies",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/helm",
},
golden: "testdata/helm.json.golden",
@@ -225,7 +227,7 @@ func TestFilesystem(t *testing.T) {
{
name: "helm chart directory scanning with builtin policies",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/helm_testchart",
},
golden: "testdata/helm_testchart.json.golden",
@@ -233,7 +235,7 @@ func TestFilesystem(t *testing.T) {
{
name: "helm chart directory scanning with value overrides using set",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/helm_testchart",
helmSet: []string{"securityContext.runAsUser=0"},
},
@@ -242,7 +244,7 @@ func TestFilesystem(t *testing.T) {
{
name: "helm chart directory scanning with value overrides using value file",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/helm_testchart",
helmValuesFile: []string{"testdata/fixtures/fs/helm_values/values.yaml"},
},
@@ -251,7 +253,7 @@ func TestFilesystem(t *testing.T) {
{
name: "helm chart directory scanning with builtin policies and non string Chart name",
args: args{
securityChecks: "config",
scanners: types.MisconfigScanner,
input: "testdata/fixtures/fs/helm_badname",
},
golden: "testdata/helm_badname.json.golden",
@@ -259,7 +261,7 @@ func TestFilesystem(t *testing.T) {
{
name: "secrets",
args: args{
securityChecks: "vuln,secret",
scanners: "vuln,secret",
input: "testdata/fixtures/fs/secrets",
secretConfig: "testdata/fixtures/fs/secrets/trivy-secret.yaml",
},
@@ -305,12 +307,19 @@ func TestFilesystem(t *testing.T) {
}
osArgs := []string{
"-q", "--cache-dir", cacheDir, command, "--skip-db-update", "--skip-policy-update",
"--format", format, "--offline-scan",
"-q",
"--cache-dir",
cacheDir,
command,
"--skip-db-update",
"--skip-policy-update",
"--format",
format,
"--offline-scan",
}
if tt.args.securityChecks != "" {
osArgs = append(osArgs, "--security-checks", tt.args.securityChecks)
if tt.args.scanners != "" {
osArgs = append(osArgs, "--scanners", tt.args.scanners)
}
if len(tt.args.policyPaths) != 0 {

View File

@@ -75,8 +75,15 @@ func TestVM(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osArgs := []string{
"--cache-dir", cacheDir, "vm", "--security-checks", "vuln", "-q", "--skip-db-update",
"--format", tt.args.format,
"--cache-dir",
cacheDir,
"vm",
"--scanners",
"vuln",
"-q",
"--skip-db-update",
"--format",
tt.args.format,
}
tmpDir := t.TempDir()

View File

@@ -581,7 +581,7 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
options.DisabledAnalyzers = append(analyzer.TypeOSes, analyzer.TypeLanguages...)
// Scan only for misconfigurations
options.SecurityChecks = []string{types.SecurityCheckConfig}
options.Scanners = []string{types.MisconfigScanner}
return artifact.Run(cmd.Context(), options, artifact.TargetFilesystem)
},
@@ -743,15 +743,15 @@ func NewModuleCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
scanFlags := flag.NewScanFlagGroup()
securityChecks := flag.SecurityChecksFlag
securityChecks.Value = fmt.Sprintf( // overwrite the default value
scanners := flag.ScannersFlag
scanners.Value = fmt.Sprintf( // overwrite the default value
"%s,%s,%s,%s",
types.SecurityCheckVulnerability,
types.SecurityCheckConfig,
types.SecurityCheckSecret,
types.SecurityCheckRbac,
types.VulnerabilityScanner,
types.MisconfigScanner,
types.SecretScanner,
types.RBACScanner,
)
scanFlags.SecurityChecks = &securityChecks
scanFlags.Scanners = &scanners
reportFlagGroup := flag.NewReportFlagGroup()
compliance := flag.ComplianceFlag
@@ -908,7 +908,7 @@ func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
Aliases: []string{},
Short: "[EXPERIMENTAL] Scan a virtual machine image",
Example: ` # Scan your AWS AMI
$ trivy vm --security-checks vuln ami:${your_ami_id}
$ trivy vm --scanners vuln ami:${your_ami_id}
# Scan your AWS EBS snapshot
$ trivy vm ebs:${your_ebs_snapshot_id}
@@ -949,7 +949,7 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
reportFlagGroup.ReportFormat = nil // TODO: support --report summary
scanFlags := flag.NewScanFlagGroup()
scanFlags.SecurityChecks = nil // disable '--security-checks' as it always scans for vulnerabilities
scanFlags.Scanners = nil // disable '--scanners' as it always scans for vulnerabilities
sbomFlags := &flag.Flags{
CacheFlagGroup: flag.NewCacheFlagGroup(),
@@ -989,7 +989,7 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
}
// Scan vulnerabilities
options.SecurityChecks = []string{types.SecurityCheckVulnerability}
options.Scanners = []string{types.VulnerabilityScanner}
return artifact.Run(cmd.Context(), options, artifact.TargetSBOM)
},

View File

@@ -46,7 +46,11 @@ const (
)
var (
defaultPolicyNamespaces = []string{"appshield", "defsec", "builtin"}
defaultPolicyNamespaces = []string{
"appshield",
"defsec",
"builtin",
}
SkipScan = errors.New("skip subsequent processes")
)
@@ -293,7 +297,7 @@ func (r *runner) Report(opts flag.Options, report types.Report) error {
func (r *runner) initDB(opts flag.Options) error {
// When scanning config files or running as client mode, it doesn't need to download the vulnerability database.
if opts.ServerAddr != "" || !slices.Contains(opts.SecurityChecks, types.SecurityCheckVulnerability) {
if opts.ServerAddr != "" || !slices.Contains(opts.Scanners, types.VulnerabilityScanner) {
return nil
}
@@ -448,19 +452,19 @@ func disabledAnalyzers(opts flag.Options) []analyzer.Type {
}
// Do not perform secret scanning when it is not specified.
if !slices.Contains(opts.SecurityChecks, types.SecurityCheckSecret) {
if !slices.Contains(opts.Scanners, types.SecretScanner) {
analyzers = append(analyzers, analyzer.TypeSecret)
}
// Do not perform misconfiguration scanning when it is not specified.
if !slices.Contains(opts.SecurityChecks, types.SecurityCheckConfig) &&
!slices.Contains(opts.SecurityChecks, types.SecurityCheckRbac) {
if !slices.Contains(opts.Scanners, types.MisconfigScanner) &&
!slices.Contains(opts.Scanners, types.RBACScanner) {
analyzers = append(analyzers, analyzer.TypeConfigFiles...)
}
// Scanning file headers and license files is expensive.
// It is performed only when '--security-checks license' and '--license-full' are specified.
if !slices.Contains(opts.SecurityChecks, types.SecurityCheckLicense) || !opts.LicenseFull {
// It is performed only when '--scanners license' and '--license-full' are specified.
if !slices.Contains(opts.Scanners, types.LicenseScanner) || !opts.LicenseFull {
analyzers = append(analyzers, analyzer.TypeLicenseFile)
}
@@ -479,7 +483,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
scanOptions := types.ScanOptions{
VulnType: opts.VulnType,
SecurityChecks: opts.SecurityChecks,
Scanners: opts.Scanners,
ScanRemovedPackages: opts.ScanRemovedPkgs, // this is valid only for 'image' subcommand
Platform: opts.Platform, // this is valid only for 'image' subcommand
ListAllPackages: opts.ListAllPkgs,
@@ -487,7 +491,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
FilePatterns: opts.FilePatterns,
}
if slices.Contains(opts.SecurityChecks, types.SecurityCheckVulnerability) {
if slices.Contains(opts.Scanners, types.VulnerabilityScanner) {
log.Logger.Info("Vulnerability scanning is enabled")
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)
}
@@ -506,7 +510,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
// ScannerOption is filled only when config scanning is enabled.
var configScannerOptions config.ScannerOption
if slices.Contains(opts.SecurityChecks, types.SecurityCheckConfig) {
if slices.Contains(opts.Scanners, types.MisconfigScanner) {
log.Logger.Info("Misconfiguration scanning is enabled")
configScannerOptions = config.ScannerOption{
Trace: opts.Trace,
@@ -523,16 +527,16 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
}
// Do not load config file for secret scanning
if slices.Contains(opts.SecurityChecks, types.SecurityCheckSecret) {
if slices.Contains(opts.Scanners, types.SecretScanner) {
ver := canonicalVersion(opts.AppVersion)
log.Logger.Info("Secret scanning is enabled")
log.Logger.Info("If your scanning is slow, please try '--security-checks vuln' to disable secret scanning")
log.Logger.Info("If your scanning is slow, please try '--scanners vuln' to disable secret scanning")
log.Logger.Infof("Please see also https://aquasecurity.github.io/trivy/%s/docs/secret/scanning/#recommendation for faster secret detection", ver)
} else {
opts.SecretConfigPath = ""
}
if slices.Contains(opts.SecurityChecks, types.SecurityCheckLicense) {
if slices.Contains(opts.Scanners, types.LicenseScanner) {
if opts.LicenseFull {
log.Logger.Info("Full license scanning is enabled")
} else {

View File

@@ -61,13 +61,13 @@ const (
WarnStatus ControlStatus = "WARN"
)
// SecurityChecks reads spec control and determines the scanners by check ID prefix
func (cs *ComplianceSpec) SecurityChecks() ([]types.SecurityCheck, error) {
scannerTypes := map[types.SecurityCheck]struct{}{}
// Scanners reads spec control and determines the scanners by check ID prefix
func (cs *ComplianceSpec) Scanners() ([]types.Scanner, error) {
scannerTypes := map[types.Scanner]struct{}{}
for _, control := range cs.Spec.Controls {
for _, check := range control.Checks {
scannerType := securityCheckByCheckID(check.ID)
if scannerType == types.SecurityCheckUnknown {
scannerType := scannerByCheckID(check.ID)
if scannerType == types.ScannerUnknown {
return nil, xerrors.Errorf("unsupported check ID: %s", check.ID)
}
scannerTypes[scannerType] = struct{}{}
@@ -77,26 +77,26 @@ func (cs *ComplianceSpec) SecurityChecks() ([]types.SecurityCheck, error) {
}
// CheckIDs return list of compliance check IDs
func (cs *ComplianceSpec) CheckIDs() map[types.SecurityCheck][]string {
checkIDsMap := map[types.SecurityCheck][]string{}
func (cs *ComplianceSpec) CheckIDs() map[types.Scanner][]string {
checkIDsMap := map[types.Scanner][]string{}
for _, control := range cs.Spec.Controls {
for _, check := range control.Checks {
scannerType := securityCheckByCheckID(check.ID)
scannerType := scannerByCheckID(check.ID)
checkIDsMap[scannerType] = append(checkIDsMap[scannerType], check.ID)
}
}
return checkIDsMap
}
func securityCheckByCheckID(checkID string) types.SecurityCheck {
func scannerByCheckID(checkID string) types.Scanner {
checkID = strings.ToLower(checkID)
switch {
case strings.HasPrefix(checkID, "cve-") || strings.HasPrefix(checkID, "dla-"):
return types.SecurityCheckVulnerability
return types.VulnerabilityScanner
case strings.HasPrefix(checkID, "avd-"):
return types.SecurityCheckConfig
return types.MisconfigScanner
default:
return types.SecurityCheckUnknown
return types.ScannerUnknown
}
}

View File

@@ -11,11 +11,11 @@ import (
"github.com/aquasecurity/trivy/pkg/types"
)
func TestComplianceSpec_SecurityChecks(t *testing.T) {
func TestComplianceSpec_Scanners(t *testing.T) {
tests := []struct {
name string
spec spec.Spec
want []types.SecurityCheck
want []types.Scanner
wantErr assert.ErrorAssertionFunc
}{
{
@@ -48,7 +48,7 @@ func TestComplianceSpec_SecurityChecks(t *testing.T) {
},
},
},
want: []types.SecurityCheck{types.SecurityCheckConfig},
want: []types.Scanner{types.MisconfigScanner},
wantErr: assert.NoError,
},
{
@@ -89,7 +89,10 @@ func TestComplianceSpec_SecurityChecks(t *testing.T) {
},
},
},
want: []types.SecurityCheck{types.SecurityCheckConfig, types.SecurityCheckVulnerability},
want: []types.Scanner{
types.MisconfigScanner,
types.VulnerabilityScanner,
},
wantErr: assert.NoError,
},
{
@@ -120,12 +123,12 @@ func TestComplianceSpec_SecurityChecks(t *testing.T) {
cs := &spec.ComplianceSpec{
Spec: tt.spec,
}
got, err := cs.SecurityChecks()
if !tt.wantErr(t, err, fmt.Sprintf("SecurityChecks()")) {
got, err := cs.Scanners()
if !tt.wantErr(t, err, fmt.Sprintf("Scanners()")) {
return
}
sort.Strings(got) // for consistency
assert.Equalf(t, tt.want, got, "SecurityChecks()")
assert.Equalf(t, tt.want, got, "Scanners()")
})
}
}
@@ -134,7 +137,7 @@ func TestComplianceSpec_CheckIDs(t *testing.T) {
tests := []struct {
name string
spec spec.Spec
want map[types.SecurityCheck][]string
want map[types.Scanner][]string
}{
{
name: "get config scanner type by check id prefix",
@@ -166,8 +169,8 @@ func TestComplianceSpec_CheckIDs(t *testing.T) {
},
},
},
want: map[types.SecurityCheck][]string{
types.SecurityCheckConfig: {
want: map[types.Scanner][]string{
types.MisconfigScanner: {
"AVD-KSV012",
"AVD-1.2.31",
"AVD-1.2.32",
@@ -212,13 +215,13 @@ func TestComplianceSpec_CheckIDs(t *testing.T) {
},
},
},
want: map[types.SecurityCheck][]string{
types.SecurityCheckConfig: {
want: map[types.Scanner][]string{
types.MisconfigScanner: {
"AVD-KSV012",
"AVD-1.2.31",
"AVD-1.2.32",
},
types.SecurityCheckVulnerability: {
types.VulnerabilityScanner: {
"CVE-9999-9999",
},
},

View File

@@ -7,11 +7,11 @@ import (
)
// MapSpecCheckIDToFilteredResults map spec check id to filtered scan results
func MapSpecCheckIDToFilteredResults(result types.Result, checkIDs map[types.SecurityCheck][]string) map[string]types.Results {
func MapSpecCheckIDToFilteredResults(result types.Result, checkIDs map[types.Scanner][]string) map[string]types.Results {
mapCheckByID := make(map[string]types.Results)
for _, vuln := range result.Vulnerabilities {
// Skip irrelevant check IDs
if !slices.Contains(checkIDs[types.SecurityCheckVulnerability], vuln.GetID()) {
if !slices.Contains(checkIDs[types.VulnerabilityScanner], vuln.GetID()) {
continue
}
mapCheckByID[vuln.GetID()] = append(mapCheckByID[vuln.GetID()], types.Result{
@@ -23,7 +23,7 @@ func MapSpecCheckIDToFilteredResults(result types.Result, checkIDs map[types.Sec
}
for _, m := range result.Misconfigurations {
// Skip irrelevant check IDs
if !slices.Contains(checkIDs[types.SecurityCheckConfig], m.GetID()) {
if !slices.Contains(checkIDs[types.MisconfigScanner], m.GetID()) {
continue
}

View File

@@ -11,19 +11,19 @@ import (
)
func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
checkIDs := map[types.SecurityCheck][]string{
types.SecurityCheckConfig: {
checkIDs := map[types.Scanner][]string{
types.MisconfigScanner: {
"AVD-KSV012",
"AVD-1.2.31",
"AVD-1.2.32",
},
types.SecurityCheckVulnerability: {
types.VulnerabilityScanner: {
"CVE-9999-9999",
},
}
tests := []struct {
name string
checkIDs map[types.SecurityCheck][]string
checkIDs map[types.Scanner][]string
result types.Result
want map[string]types.Results
}{
@@ -35,9 +35,18 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
Class: types.ClassConfig,
Type: ftypes.Kubernetes,
Misconfigurations: []types.DetectedMisconfiguration{
{AVDID: "AVD-KSV012", Status: types.StatusFailure},
{AVDID: "AVD-KSV013", Status: types.StatusFailure},
{AVDID: "AVD-1.2.31", Status: types.StatusFailure},
{
AVDID: "AVD-KSV012",
Status: types.StatusFailure,
},
{
AVDID: "AVD-KSV013",
Status: types.StatusFailure,
},
{
AVDID: "AVD-1.2.31",
Status: types.StatusFailure,
},
},
},
want: map[string]types.Results{
@@ -46,9 +55,16 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
Target: "target",
Class: types.ClassConfig,
Type: ftypes.Kubernetes,
MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0},
MisconfSummary: &types.MisconfSummary{
Successes: 0,
Failures: 1,
Exceptions: 0,
},
Misconfigurations: []types.DetectedMisconfiguration{
{AVDID: "AVD-KSV012", Status: types.StatusFailure},
{
AVDID: "AVD-KSV012",
Status: types.StatusFailure,
},
},
},
},
@@ -57,9 +73,16 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
Target: "target",
Class: types.ClassConfig,
Type: ftypes.Kubernetes,
MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0},
MisconfSummary: &types.MisconfSummary{
Successes: 0,
Failures: 1,
Exceptions: 0,
},
Misconfigurations: []types.DetectedMisconfiguration{
{AVDID: "AVD-1.2.31", Status: types.StatusFailure},
{
AVDID: "AVD-1.2.31",
Status: types.StatusFailure,
},
},
},
},

View File

@@ -11,7 +11,7 @@ var (
Name: "include-non-failures",
ConfigName: "misconfiguration.include-non-failures",
Value: false,
Usage: "include successes and exceptions, available with '--security-checks config'",
Usage: "include successes and exceptions, available with '--scanners config'",
}
HelmValuesFileFlag = Flag{
Name: "helm-values",

View File

@@ -94,14 +94,14 @@ type Options struct {
// Align takes consistency of options
func (o *Options) Align() {
if o.Format == report.FormatSPDX || o.Format == report.FormatSPDXJSON {
log.Logger.Info(`"--format spdx" and "--format spdx-json" disable security checks`)
o.SecurityChecks = nil
log.Logger.Info(`"--format spdx" and "--format spdx-json" disable security scanning`)
o.Scanners = nil
}
// Vulnerability scanning is disabled by default for CycloneDX.
if o.Format == report.FormatCycloneDX && !viper.IsSet(SecurityChecksFlag.ConfigName) {
log.Logger.Info(`"--format cyclonedx" disables security checks. Specify "--security-checks vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.`)
o.SecurityChecks = nil
if o.Format == report.FormatCycloneDX && !viper.IsSet(ScannersFlag.ConfigName) {
log.Logger.Info(`"--format cyclonedx" disables security scanning. Specify "--scanners vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.`)
o.Scanners = nil
}
}
@@ -415,6 +415,8 @@ func flagNameNormalize(f *pflag.FlagSet, name string) pflag.NormalizedName {
name = PolicyNamespaceFlag.Name
case "ctx":
name = ClusterContextFlag.Name
case "security-checks":
name = ScannersFlag.Name
}
return pflag.NormalizedName(name)
}

View File

@@ -24,30 +24,42 @@ func Test_getStringSlice(t *testing.T) {
}{
{
name: "happy path. Empty value",
flag: &SecurityChecksFlag,
flag: &ScannersFlag,
flagValue: "",
want: nil,
},
{
name: "happy path. String value",
flag: &SecurityChecksFlag,
flag: &ScannersFlag,
flagValue: "license,vuln",
want: []string{types.SecurityCheckLicense, types.SecurityCheckVulnerability},
want: []string{
types.LicenseScanner,
types.VulnerabilityScanner,
},
},
{
name: "happy path. Slice value",
flag: &SecurityChecksFlag,
flagValue: []string{"license", "secret"},
want: []string{types.SecurityCheckLicense, types.SecurityCheckSecret},
flag: &ScannersFlag,
flagValue: []string{
"license",
"secret",
},
want: []string{
types.LicenseScanner,
types.SecretScanner,
},
},
{
name: "happy path. Env value",
flag: &SecurityChecksFlag,
flag: &ScannersFlag,
env: env{
key: "TRIVY_SECURITY_CHECKS",
value: "rbac,config",
},
want: []string{types.SecurityCheckRbac, types.SecurityCheckConfig},
want: []string{
types.RBACScanner,
types.MisconfigScanner,
},
},
}

View File

@@ -26,10 +26,13 @@ var (
Value: false,
Usage: "do not issue API requests to identify dependencies",
}
SecurityChecksFlag = Flag{
Name: "security-checks",
ConfigName: "scan.security-checks",
Value: []string{types.SecurityCheckVulnerability, types.SecurityCheckSecret},
ScannersFlag = Flag{
Name: "scanners",
ConfigName: "scan.scanners",
Value: []string{
types.VulnerabilityScanner,
types.SecretScanner,
},
Usage: "comma-separated list of what security issues to detect (vuln,config,secret,license)",
}
FilePatternsFlag = Flag{
@@ -62,7 +65,7 @@ type ScanFlagGroup struct {
SkipDirs *Flag
SkipFiles *Flag
OfflineScan *Flag
SecurityChecks *Flag
Scanners *Flag
FilePatterns *Flag
Slow *Flag
SBOMSources *Flag
@@ -74,7 +77,7 @@ type ScanOptions struct {
SkipDirs []string
SkipFiles []string
OfflineScan bool
SecurityChecks []string
Scanners []string
FilePatterns []string
Slow bool
SBOMSources []string
@@ -86,7 +89,7 @@ func NewScanFlagGroup() *ScanFlagGroup {
SkipDirs: &SkipDirsFlag,
SkipFiles: &SkipFilesFlag,
OfflineScan: &OfflineScanFlag,
SecurityChecks: &SecurityChecksFlag,
Scanners: &ScannersFlag,
FilePatterns: &FilePatternsFlag,
Slow: &SlowFlag,
SBOMSources: &SBOMSourcesFlag,
@@ -99,8 +102,16 @@ func (f *ScanFlagGroup) Name() string {
}
func (f *ScanFlagGroup) Flags() []*Flag {
return []*Flag{f.SkipDirs, f.SkipFiles, f.OfflineScan, f.SecurityChecks, f.FilePatterns,
f.Slow, f.SBOMSources, f.RekorURL}
return []*Flag{
f.SkipDirs,
f.SkipFiles,
f.OfflineScan,
f.Scanners,
f.FilePatterns,
f.Slow,
f.SBOMSources,
f.RekorURL,
}
}
func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
@@ -108,9 +119,9 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
if len(args) == 1 {
target = args[0]
}
securityChecks, err := parseSecurityCheck(getStringSlice(f.SecurityChecks))
scanners, err := parseScanners(getStringSlice(f.Scanners))
if err != nil {
return ScanOptions{}, xerrors.Errorf("unable to parse security checks: %w", err)
return ScanOptions{}, xerrors.Errorf("unable to parse scanners: %w", err)
}
sbomSources := getStringSlice(f.SBOMSources)
@@ -123,7 +134,7 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
SkipDirs: getStringSlice(f.SkipDirs),
SkipFiles: getStringSlice(f.SkipFiles),
OfflineScan: getBool(f.OfflineScan),
SecurityChecks: securityChecks,
Scanners: scanners,
FilePatterns: getStringSlice(f.FilePatterns),
Slow: getBool(f.Slow),
SBOMSources: sbomSources,
@@ -131,15 +142,15 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
}, nil
}
func parseSecurityCheck(securityCheck []string) ([]string, error) {
var securityChecks []string
for _, v := range securityCheck {
if !slices.Contains(types.SecurityChecks, v) {
return nil, xerrors.Errorf("unknown security check: %s", v)
func parseScanners(scanner []string) ([]string, error) {
var scanners []string
for _, v := range scanner {
if !slices.Contains(types.Scanners, v) {
return nil, xerrors.Errorf("unknown scanner: %s", v)
}
securityChecks = append(securityChecks, v)
scanners = append(scanners, v)
}
return securityChecks, nil
return scanners, nil
}
func validateSBOMSources(sbomSources []string) error {

View File

@@ -16,7 +16,7 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
skipDirs []string
skipFiles []string
offlineScan bool
securityChecks string
scanners string
}
tests := []struct {
name string
@@ -38,22 +38,22 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
name: "happy path for configs",
args: []string{"alpine:latest"},
fields: fields{
securityChecks: "config",
scanners: "config",
},
want: flag.ScanOptions{
Target: "alpine:latest",
SecurityChecks: []string{types.SecurityCheckConfig},
Scanners: []string{types.MisconfigScanner},
},
assertion: require.NoError,
},
{
name: "with wrong security check",
name: "with wrong scanner",
fields: fields{
securityChecks: "vuln,WRONG-CHECK",
scanners: "vuln,WRONG-CHECK",
},
want: flag.ScanOptions{},
assertion: func(t require.TestingT, err error, msgs ...interface{}) {
require.ErrorContains(t, err, "unknown security check: WRONG-CHECK")
require.ErrorContains(t, err, "unknown scanner: WRONG-CHECK")
},
},
{
@@ -65,7 +65,10 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
},
{
name: "with two or more targets (args)",
args: []string{"alpine:latest", "nginx:latest"},
args: []string{
"alpine:latest",
"nginx:latest",
},
fields: fields{},
want: flag.ScanOptions{},
assertion: require.NoError,
@@ -73,20 +76,32 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
{
name: "skip two files",
fields: fields{
skipFiles: []string{"file1", "file2"},
skipFiles: []string{
"file1",
"file2",
},
},
want: flag.ScanOptions{
SkipFiles: []string{"file1", "file2"},
SkipFiles: []string{
"file1",
"file2",
},
},
assertion: require.NoError,
},
{
name: "skip two folders",
fields: fields{
skipDirs: []string{"dir1", "dir2"},
skipDirs: []string{
"dir1",
"dir2",
},
},
want: flag.ScanOptions{
SkipDirs: []string{"dir1", "dir2"},
SkipDirs: []string{
"dir1",
"dir2",
},
},
assertion: require.NoError,
},
@@ -107,14 +122,14 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
viper.Set(flag.SkipDirsFlag.ConfigName, tt.fields.skipDirs)
viper.Set(flag.SkipFilesFlag.ConfigName, tt.fields.skipFiles)
viper.Set(flag.OfflineScanFlag.ConfigName, tt.fields.offlineScan)
viper.Set(flag.SecurityChecksFlag.ConfigName, tt.fields.securityChecks)
viper.Set(flag.ScannersFlag.ConfigName, tt.fields.scanners)
// Assert options
f := &flag.ScanFlagGroup{
SkipDirs: &flag.SkipDirsFlag,
SkipFiles: &flag.SkipFilesFlag,
OfflineScan: &flag.OfflineScanFlag,
SecurityChecks: &flag.SecurityChecksFlag,
Scanners: &flag.ScannersFlag,
}
got, err := f.ToOptions(tt.args)

View File

@@ -51,7 +51,10 @@ type runner struct {
}
func newRunner(flagOpts flag.Options, cluster string) *runner {
return &runner{flagOpts, cluster}
return &runner{
flagOpts,
cluster,
}
}
func (r *runner) run(ctx context.Context, artifacts []*artifacts.Artifact) error {
@@ -90,11 +93,11 @@ func (r *runner) run(ctx context.Context, artifacts []*artifacts.Artifact) error
if err = yaml.Unmarshal(cs, &complianceSpec); err != nil {
return xerrors.Errorf("yaml unmarshal error: %w", err)
}
securityChecks, err := complianceSpec.SecurityChecks()
scanners, err := complianceSpec.Scanners()
if err != nil {
return xerrors.Errorf("security check error: %w", err)
return xerrors.Errorf("scanner error: %w", err)
}
r.flagOpts.ScanOptions.SecurityChecks = securityChecks
r.flagOpts.ScanOptions.Scanners = scanners
}
rpt, err := s.Scan(ctx, artifacts)
@@ -117,7 +120,8 @@ func (r *runner) run(ctx context.Context, artifacts []*artifacts.Artifact) error
return cr.Write(complianceReport, cr.Option{
Format: r.flagOpts.Format,
Report: r.flagOpts.ReportFormat,
Output: r.flagOpts.Output})
Output: r.flagOpts.Output,
})
}
if err := report.Write(rpt, report.Option{
@@ -126,7 +130,7 @@ func (r *runner) run(ctx context.Context, artifacts []*artifacts.Artifact) error
Output: r.flagOpts.Output,
Severities: r.flagOpts.Severities,
Components: r.flagOpts.Components,
SecurityChecks: r.flagOpts.ScanOptions.SecurityChecks,
Scanners: r.flagOpts.ScanOptions.Scanners,
}); err != nil {
return xerrors.Errorf("unable to write results: %w", err)
}

View File

@@ -34,7 +34,7 @@ type Option struct {
Output io.Writer
Severities []dbTypes.Severity
ColumnHeading []string
SecurityChecks []string
Scanners []string
Components []string
}
@@ -135,10 +135,13 @@ func Write(report Report, option Option) error {
switch option.Format {
case jsonFormat:
jwriter := JSONWriter{Output: option.Output, Report: option.Report}
jwriter := JSONWriter{
Output: option.Output,
Report: option.Report,
}
return jwriter.Write(report)
case tableFormat:
separatedReports := separateMisconfigReports(report, option.SecurityChecks, option.Components)
separatedReports := separateMisconfigReports(report, option.Scanners, option.Components)
if option.Report == summaryReport {
target := fmt.Sprintf("Summary Report for %s", report.ClusterName)
@@ -150,7 +153,7 @@ func Write(report Report, option Option) error {
Output: option.Output,
Report: option.Report,
Severities: option.Severities,
ColumnHeading: ColumnHeading(option.SecurityChecks, option.Components, r.columns),
ColumnHeading: ColumnHeading(option.Scanners, option.Components, r.columns),
}
if err := writer.Write(r.report); err != nil {
@@ -169,11 +172,11 @@ type reports struct {
columns []string
}
// separateMisconfigReports returns 3 reports based on securityChecks and components flags,
// separateMisconfigReports returns 3 reports based on scanners and components flags,
// - misconfiguration report
// - rbac report
// - infra checks report
func separateMisconfigReports(k8sReport Report, securityChecks, components []string) []reports {
func separateMisconfigReports(k8sReport Report, scanners, components []string) []reports {
workloadMisconfig := make([]Resource, 0)
infraMisconfig := make([]Resource, 0)
@@ -181,7 +184,7 @@ func separateMisconfigReports(k8sReport Report, securityChecks, components []str
for _, misConfig := range k8sReport.Misconfigurations {
switch {
case slices.Contains(securityChecks, types.SecurityCheckRbac) && rbacResource(misConfig):
case slices.Contains(scanners, types.RBACScanner) && rbacResource(misConfig):
rbacAssessment = append(rbacAssessment, misConfig)
case infraResource(misConfig):
workload, infra := splitInfraAndWorkloadResources(misConfig)
@@ -194,7 +197,7 @@ func separateMisconfigReports(k8sReport Report, securityChecks, components []str
workloadMisconfig = append(workloadMisconfig, workload)
}
case slices.Contains(securityChecks, types.SecurityCheckConfig) && !rbacResource(misConfig):
case slices.Contains(scanners, types.MisconfigScanner) && !rbacResource(misConfig):
if slices.Contains(components, workloadComponent) {
workloadMisconfig = append(workloadMisconfig, misConfig)
}
@@ -203,7 +206,7 @@ func separateMisconfigReports(k8sReport Report, securityChecks, components []str
r := make([]reports, 0)
if shouldAddWorkloadReport(securityChecks) {
if shouldAddWorkloadReport(scanners) {
workloadReport := Report{
SchemaVersion: 0,
ClusterName: k8sReport.ClusterName,
@@ -215,11 +218,14 @@ func separateMisconfigReports(k8sReport Report, securityChecks, components []str
if (slices.Contains(components, workloadComponent) &&
len(workloadMisconfig) > 0) ||
len(k8sReport.Vulnerabilities) > 0 {
r = append(r, reports{report: workloadReport, columns: WorkloadColumns()})
r = append(r, reports{
report: workloadReport,
columns: WorkloadColumns(),
})
}
}
if slices.Contains(securityChecks, types.SecurityCheckRbac) && len(rbacAssessment) > 0 {
if slices.Contains(scanners, types.RBACScanner) && len(rbacAssessment) > 0 {
r = append(r, reports{
report: Report{
SchemaVersion: 0,
@@ -231,7 +237,7 @@ func separateMisconfigReports(k8sReport Report, securityChecks, components []str
})
}
if slices.Contains(securityChecks, types.SecurityCheckConfig) &&
if slices.Contains(scanners, types.MisconfigScanner) &&
slices.Contains(components, infraComponent) &&
len(infraMisconfig) > 0 {
@@ -357,8 +363,8 @@ func copyResult(r types.Result, misconfigs []types.DetectedMisconfiguration) typ
}
}
func shouldAddWorkloadReport(securityChecks []string) bool {
return slices.Contains(securityChecks, types.SecurityCheckConfig) ||
slices.Contains(securityChecks, types.SecurityCheckVulnerability) ||
slices.Contains(securityChecks, types.SecurityCheckSecret)
func shouldAddWorkloadReport(scanners []string) bool {
return slices.Contains(scanners, types.MisconfigScanner) ||
slices.Contains(scanners, types.VulnerabilityScanner) ||
slices.Contains(scanners, types.SecretScanner)
}

View File

@@ -19,15 +19,45 @@ var (
Kind: "Deploy",
Name: "orion",
Results: types.Results{
{Misconfigurations: []types.DetectedMisconfiguration{
{ID: "ID100", Status: types.StatusFailure, Severity: "LOW"},
{ID: "ID101", Status: types.StatusFailure, Severity: "MEDIUM"},
{ID: "ID102", Status: types.StatusFailure, Severity: "HIGH"},
{ID: "ID103", Status: types.StatusFailure, Severity: "CRITICAL"},
{ID: "ID104", Status: types.StatusFailure, Severity: "UNKNOWN"},
{ID: "ID105", Status: types.StatusFailure, Severity: "LOW"},
{ID: "ID106", Status: types.StatusFailure, Severity: "HIGH"},
}},
{
Misconfigurations: []types.DetectedMisconfiguration{
{
ID: "ID100",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "ID101",
Status: types.StatusFailure,
Severity: "MEDIUM",
},
{
ID: "ID102",
Status: types.StatusFailure,
Severity: "HIGH",
},
{
ID: "ID103",
Status: types.StatusFailure,
Severity: "CRITICAL",
},
{
ID: "ID104",
Status: types.StatusFailure,
Severity: "UNKNOWN",
},
{
ID: "ID105",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "ID106",
Status: types.StatusFailure,
Severity: "HIGH",
},
},
},
},
}
@@ -36,15 +66,38 @@ var (
Kind: "Deploy",
Name: "orion",
Results: types.Results{
{Vulnerabilities: []types.DetectedVulnerability{
{VulnerabilityID: "CVE-2022-1111", Vulnerability: dbTypes.Vulnerability{Severity: "LOW"}},
{VulnerabilityID: "CVE-2022-2222", Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}},
{VulnerabilityID: "CVE-2022-3333", Vulnerability: dbTypes.Vulnerability{Severity: "HIGH"}},
{VulnerabilityID: "CVE-2022-4444", Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"}},
{VulnerabilityID: "CVE-2022-5555", Vulnerability: dbTypes.Vulnerability{Severity: "UNKNOWN"}},
{VulnerabilityID: "CVE-2022-6666", Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"}},
{VulnerabilityID: "CVE-2022-7777", Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}},
}},
{
Vulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2022-1111",
Vulnerability: dbTypes.Vulnerability{Severity: "LOW"},
},
{
VulnerabilityID: "CVE-2022-2222",
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
},
{
VulnerabilityID: "CVE-2022-3333",
Vulnerability: dbTypes.Vulnerability{Severity: "HIGH"},
},
{
VulnerabilityID: "CVE-2022-4444",
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
},
{
VulnerabilityID: "CVE-2022-5555",
Vulnerability: dbTypes.Vulnerability{Severity: "UNKNOWN"},
},
{
VulnerabilityID: "CVE-2022-6666",
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
},
{
VulnerabilityID: "CVE-2022-7777",
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
},
},
},
},
}
@@ -53,24 +106,77 @@ var (
Kind: "Deploy",
Name: "orion",
Results: types.Results{
{Misconfigurations: []types.DetectedMisconfiguration{
{ID: "ID100", Status: types.StatusFailure, Severity: "LOW"},
{ID: "ID101", Status: types.StatusFailure, Severity: "MEDIUM"},
{ID: "ID102", Status: types.StatusFailure, Severity: "HIGH"},
{ID: "ID103", Status: types.StatusFailure, Severity: "CRITICAL"},
{ID: "ID104", Status: types.StatusFailure, Severity: "UNKNOWN"},
{ID: "ID105", Status: types.StatusFailure, Severity: "LOW"},
{ID: "ID106", Status: types.StatusFailure, Severity: "HIGH"},
}},
{Vulnerabilities: []types.DetectedVulnerability{
{VulnerabilityID: "CVE-2022-1111", Vulnerability: dbTypes.Vulnerability{Severity: "LOW"}},
{VulnerabilityID: "CVE-2022-2222", Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}},
{VulnerabilityID: "CVE-2022-3333", Vulnerability: dbTypes.Vulnerability{Severity: "HIGH"}},
{VulnerabilityID: "CVE-2022-4444", Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"}},
{VulnerabilityID: "CVE-2022-5555", Vulnerability: dbTypes.Vulnerability{Severity: "UNKNOWN"}},
{VulnerabilityID: "CVE-2022-6666", Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"}},
{VulnerabilityID: "CVE-2022-7777", Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}},
}},
{
Misconfigurations: []types.DetectedMisconfiguration{
{
ID: "ID100",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "ID101",
Status: types.StatusFailure,
Severity: "MEDIUM",
},
{
ID: "ID102",
Status: types.StatusFailure,
Severity: "HIGH",
},
{
ID: "ID103",
Status: types.StatusFailure,
Severity: "CRITICAL",
},
{
ID: "ID104",
Status: types.StatusFailure,
Severity: "UNKNOWN",
},
{
ID: "ID105",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "ID106",
Status: types.StatusFailure,
Severity: "HIGH",
},
},
},
{
Vulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2022-1111",
Vulnerability: dbTypes.Vulnerability{Severity: "LOW"},
},
{
VulnerabilityID: "CVE-2022-2222",
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
},
{
VulnerabilityID: "CVE-2022-3333",
Vulnerability: dbTypes.Vulnerability{Severity: "HIGH"},
},
{
VulnerabilityID: "CVE-2022-4444",
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
},
{
VulnerabilityID: "CVE-2022-5555",
Vulnerability: dbTypes.Vulnerability{Severity: "UNKNOWN"},
},
{
VulnerabilityID: "CVE-2022-6666",
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
},
{
VulnerabilityID: "CVE-2022-7777",
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
},
},
},
},
}
@@ -97,9 +203,15 @@ var (
Kind: "Role",
Name: "system::leader-locking-kube-controller-manager",
Results: types.Results{
{Misconfigurations: []types.DetectedMisconfiguration{
{ID: "ID100", Status: types.StatusFailure, Severity: "MEDIUM"},
}},
{
Misconfigurations: []types.DetectedMisconfiguration{
{
ID: "ID100",
Status: types.StatusFailure,
Severity: "MEDIUM",
},
},
},
},
}
@@ -108,10 +220,18 @@ var (
Kind: "Deploy",
Name: "lua",
Results: types.Results{
{Secrets: []ftypes.SecretFinding{
{RuleID: "secret1", Severity: "CRITICAL"},
{RuleID: "secret2", Severity: "MEDIUM"},
}},
{
Secrets: []ftypes.SecretFinding{
{
RuleID: "secret1",
Severity: "CRITICAL",
},
{
RuleID: "secret2",
Severity: "MEDIUM",
},
},
},
},
}
@@ -120,14 +240,36 @@ var (
Kind: "Pod",
Name: "kube-apiserver",
Results: types.Results{
{Misconfigurations: []types.DetectedMisconfiguration{
{ID: "KSV-ID100", Status: types.StatusFailure, Severity: "LOW"},
{ID: "KSV-ID101", Status: types.StatusFailure, Severity: "MEDIUM"},
{ID: "KSV-ID102", Status: types.StatusFailure, Severity: "HIGH"},
{
Misconfigurations: []types.DetectedMisconfiguration{
{
ID: "KSV-ID100",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "KSV-ID101",
Status: types.StatusFailure,
Severity: "MEDIUM",
},
{
ID: "KSV-ID102",
Status: types.StatusFailure,
Severity: "HIGH",
},
{ID: "KCV-ID100", Status: types.StatusFailure, Severity: "LOW"},
{ID: "KCV-ID101", Status: types.StatusFailure, Severity: "MEDIUM"},
}},
{
ID: "KCV-ID100",
Status: types.StatusFailure,
Severity: "LOW",
},
{
ID: "KCV-ID101",
Status: types.StatusFailure,
Severity: "MEDIUM",
},
},
},
},
}
)
@@ -141,8 +283,14 @@ func TestReport_consolidate(t *testing.T) {
{
name: "report with both misconfigs and vulnerabilities",
report: Report{
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
Vulnerabilities: []Resource{
deployOrionWithVulns,
cronjobHelloWithVulns,
},
Misconfigurations: []Resource{
deployOrionWithMisconfigs,
podPrometheusWithMisconfigs,
},
},
expectedFindings: map[string]Resource{
"default/deploy/orion": deployOrionWithBothVulnsAndMisconfigs,
@@ -153,7 +301,10 @@ func TestReport_consolidate(t *testing.T) {
{
name: "report with only misconfigurations",
report: Report{
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
Misconfigurations: []Resource{
deployOrionWithMisconfigs,
podPrometheusWithMisconfigs,
},
},
expectedFindings: map[string]Resource{
"default/deploy/orion": deployOrionWithMisconfigs,
@@ -163,7 +314,10 @@ func TestReport_consolidate(t *testing.T) {
{
name: "report with only vulnerabilities",
report: Report{
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
Vulnerabilities: []Resource{
deployOrionWithVulns,
cronjobHelloWithVulns,
},
},
expectedFindings: map[string]Resource{
"default/deploy/orion": deployOrionWithVulns,
@@ -194,10 +348,22 @@ func TestResource_fullname(t *testing.T) {
expected string
resource Resource
}{
{"default/deploy/orion", deployOrionWithBothVulnsAndMisconfigs},
{"default/deploy/orion", deployOrionWithMisconfigs},
{"default/cronjob/hello", cronjobHelloWithVulns},
{"default/pod/prometheus", podPrometheusWithMisconfigs},
{
"default/deploy/orion",
deployOrionWithBothVulnsAndMisconfigs,
},
{
"default/deploy/orion",
deployOrionWithMisconfigs,
},
{
"default/cronjob/hello",
cronjobHelloWithVulns,
},
{
"default/pod/prometheus",
podPrometheusWithMisconfigs,
},
}
for _, tt := range tests {
@@ -216,22 +382,34 @@ func TestResourceFailed(t *testing.T) {
{
name: "report with both misconfigs and vulnerabilities",
report: Report{
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
Vulnerabilities: []Resource{
deployOrionWithVulns,
cronjobHelloWithVulns,
},
Misconfigurations: []Resource{
deployOrionWithMisconfigs,
podPrometheusWithMisconfigs,
},
},
expected: true,
},
{
name: "report with only misconfigurations",
report: Report{
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
Misconfigurations: []Resource{
deployOrionWithMisconfigs,
podPrometheusWithMisconfigs,
},
},
expected: true,
},
{
name: "report with only vulnerabilities",
report: Report{
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
Vulnerabilities: []Resource{
deployOrionWithVulns,
cronjobHelloWithVulns,
},
},
expected: true,
},
@@ -285,30 +463,49 @@ func Test_rbacResource(t *testing.T) {
}
func Test_separateMisconfigReports(t *testing.T) {
k8sReport := Report{Misconfigurations: []Resource{
k8sReport := Report{
Misconfigurations: []Resource{
{Kind: "Role"},
{Kind: "Deployment"},
{Kind: "StatefulSet"},
{Kind: "Pod", Namespace: "kube-system", Results: []types.Result{
{
Kind: "Pod",
Namespace: "kube-system",
Results: []types.Result{
{Misconfigurations: []types.DetectedMisconfiguration{{ID: "KCV-0001"}}},
{Misconfigurations: []types.DetectedMisconfiguration{{ID: "KSV-0001"}}},
}},
}}
},
},
},
}
tests := []struct {
name string
k8sReport Report
securityChecks []string
scanners []string
components []string
expectedReports []Report
}{
{
name: "Config, Rbac, and Infra Reports",
k8sReport: k8sReport,
securityChecks: []string{types.SecurityCheckConfig, types.SecurityCheckRbac},
components: []string{workloadComponent, infraComponent},
expectedReports: []Report{ // the order matter for the test
{Misconfigurations: []Resource{{Kind: "Deployment"}, {Kind: "StatefulSet"}, {Kind: "Pod"}}},
scanners: []string{
types.MisconfigScanner,
types.RBACScanner,
},
components: []string{
workloadComponent,
infraComponent,
},
expectedReports: []Report{
// the order matter for the test
{
Misconfigurations: []Resource{
{Kind: "Deployment"},
{Kind: "StatefulSet"},
{Kind: "Pod"},
},
},
{Misconfigurations: []Resource{{Kind: "Role"}}},
{Misconfigurations: []Resource{{Kind: "Pod"}}},
},
@@ -316,17 +513,27 @@ func Test_separateMisconfigReports(t *testing.T) {
{
name: "Config and Infra for the same resource",
k8sReport: k8sReport,
securityChecks: []string{types.SecurityCheckConfig},
components: []string{workloadComponent, infraComponent},
expectedReports: []Report{ // the order matter for the test
{Misconfigurations: []Resource{{Kind: "Deployment"}, {Kind: "StatefulSet"}, {Kind: "Pod"}}},
scanners: []string{types.MisconfigScanner},
components: []string{
workloadComponent,
infraComponent,
},
expectedReports: []Report{
// the order matter for the test
{
Misconfigurations: []Resource{
{Kind: "Deployment"},
{Kind: "StatefulSet"},
{Kind: "Pod"},
},
},
{Misconfigurations: []Resource{{Kind: "Pod"}}},
},
},
{
name: "Role Report Only",
k8sReport: k8sReport,
securityChecks: []string{types.SecurityCheckRbac},
scanners: []string{types.RBACScanner},
expectedReports: []Report{
{Misconfigurations: []Resource{{Kind: "Role"}}},
},
@@ -334,16 +541,22 @@ func Test_separateMisconfigReports(t *testing.T) {
{
name: "Config Report Only",
k8sReport: k8sReport,
securityChecks: []string{types.SecurityCheckConfig},
scanners: []string{types.MisconfigScanner},
components: []string{workloadComponent},
expectedReports: []Report{
{Misconfigurations: []Resource{{Kind: "Deployment"}, {Kind: "StatefulSet"}, {Kind: "Pod"}}},
{
Misconfigurations: []Resource{
{Kind: "Deployment"},
{Kind: "StatefulSet"},
{Kind: "Pod"},
},
},
},
},
{
name: "Infra Report Only",
k8sReport: k8sReport,
securityChecks: []string{types.SecurityCheckConfig},
scanners: []string{types.MisconfigScanner},
components: []string{infraComponent},
expectedReports: []Report{
{Misconfigurations: []Resource{{Kind: "Pod"}}},
@@ -355,7 +568,7 @@ func Test_separateMisconfigReports(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reports := separateMisconfigReports(tt.k8sReport, tt.securityChecks, tt.components)
reports := separateMisconfigReports(tt.k8sReport, tt.scanners, tt.components)
assert.Equal(t, len(tt.expectedReports), len(reports))
for i := range reports {
@@ -381,7 +594,7 @@ func TestReportWrite_Summary(t *testing.T) {
name string
report Report
opt Option
securityChecks []string
scanners []string
components []string
severities []dbTypes.Severity
expectedOutput string
@@ -392,7 +605,7 @@ func TestReportWrite_Summary(t *testing.T) {
ClusterName: "test",
Misconfigurations: []Resource{deployOrionWithMisconfigs},
},
securityChecks: []string{types.SecurityCheckConfig},
scanners: []string{types.MisconfigScanner},
components: []string{workloadComponent},
severities: allSeverities,
expectedOutput: `Summary Report for test
@@ -414,7 +627,7 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
ClusterName: "test",
Vulnerabilities: []Resource{deployOrionWithVulns},
},
securityChecks: []string{types.SecurityCheckVulnerability},
scanners: []string{types.VulnerabilityScanner},
severities: allSeverities,
expectedOutput: `Summary Report for test
=======================
@@ -435,7 +648,7 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
ClusterName: "test",
Misconfigurations: []Resource{roleWithMisconfig},
},
securityChecks: []string{types.SecurityCheckRbac},
scanners: []string{types.RBACScanner},
severities: allSeverities,
expectedOutput: `Summary Report for test
=======================
@@ -456,7 +669,7 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
ClusterName: "test",
Vulnerabilities: []Resource{deployLuaWithSecrets},
},
securityChecks: []string{types.SecurityCheckSecret},
scanners: []string{types.SecretScanner},
severities: allSeverities,
expectedOutput: `Summary Report for test
=======================
@@ -477,7 +690,7 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
ClusterName: "test",
Misconfigurations: []Resource{apiseverPodWithMisconfigAndInfra},
},
securityChecks: []string{types.SecurityCheckConfig},
scanners: []string{types.MisconfigScanner},
components: []string{infraComponent},
severities: allSeverities,
expectedOutput: `Summary Report for test
@@ -499,7 +712,11 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
ClusterName: "test",
Misconfigurations: []Resource{apiseverPodWithMisconfigAndInfra},
},
securityChecks: []string{types.SecurityCheckVulnerability, types.SecurityCheckConfig, types.SecurityCheckSecret},
scanners: []string{
types.VulnerabilityScanner,
types.MisconfigScanner,
types.SecretScanner,
},
components: []string{workloadComponent},
severities: allSeverities,
expectedOutput: `Summary Report for test
@@ -516,14 +733,21 @@ Workload Assessment
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
},
{
name: "apiserver, all security-checks and serverities",
name: "apiserver, all scanners and serverities",
report: Report{
ClusterName: "test",
Misconfigurations: []Resource{apiseverPodWithMisconfigAndInfra},
},
securityChecks: []string{types.SecurityCheckConfig, types.SecurityCheckVulnerability,
types.SecurityCheckRbac, types.SecurityCheckSecret},
components: []string{workloadComponent, infraComponent},
scanners: []string{
types.MisconfigScanner,
types.VulnerabilityScanner,
types.RBACScanner,
types.SecretScanner,
},
components: []string{
workloadComponent,
infraComponent,
},
severities: allSeverities,
expectedOutput: `Summary Report for test
=======================
@@ -559,7 +783,7 @@ Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
Format: "table",
Report: "summary",
Output: &output,
SecurityChecks: tc.securityChecks,
Scanners: tc.scanners,
Severities: tc.severities,
Components: tc.components,
}

View File

@@ -35,24 +35,27 @@ func NewSummaryWriter(output io.Writer, requiredSevs []dbTypes.Severity, columnH
}
}
func ColumnHeading(securityChecks, components, availableColumns []string) []string {
columns := []string{NamespaceColumn, ResourceColumn}
func ColumnHeading(scanners, components, availableColumns []string) []string {
columns := []string{
NamespaceColumn,
ResourceColumn,
}
securityOptions := make(map[string]interface{}, 0)
//maintain column order (vuln,config,secret)
for _, check := range securityChecks {
for _, check := range scanners {
switch check {
case types.SecurityCheckVulnerability:
case types.VulnerabilityScanner:
securityOptions[VulnerabilitiesColumn] = nil
case types.SecurityCheckConfig:
case types.MisconfigScanner:
if slices.Contains(components, workloadComponent) {
securityOptions[MisconfigurationsColumn] = nil
}
if slices.Contains(components, infraComponent) {
securityOptions[InfraAssessmentColumn] = nil
}
case types.SecurityCheckSecret:
case types.SecretScanner:
securityOptions[SecretsColumn] = nil
case types.SecurityCheckRbac:
case types.RBACScanner:
securityOptions[RbacAssessmentColumn] = nil
}
}
@@ -94,7 +97,10 @@ func (s SummaryWriter) Write(report Report) error {
}
vCount, mCount, sCount := accumulateSeverityCounts(finding)
name := fmt.Sprintf("%s/%s", finding.Kind, finding.Name)
rowParts := []string{finding.Namespace, name}
rowParts := []string{
finding.Namespace,
name,
}
if slices.Contains(s.ColumnsHeading, VulnerabilitiesColumn) {
rowParts = append(rowParts, s.generateSummary(vCount)...)
@@ -140,9 +146,13 @@ func (s SummaryWriter) generateSummary(sevCount map[string]int) []string {
}
func getRequiredSeverities(requiredSevs []dbTypes.Severity) ([]string, []string) {
requiredSevOrder := []dbTypes.Severity{dbTypes.SeverityCritical,
dbTypes.SeverityHigh, dbTypes.SeverityMedium,
dbTypes.SeverityLow, dbTypes.SeverityUnknown}
requiredSevOrder := []dbTypes.Severity{
dbTypes.SeverityCritical,
dbTypes.SeverityHigh,
dbTypes.SeverityMedium,
dbTypes.SeverityLow,
dbTypes.SeverityUnknown,
}
var severities []string
var severityHeadings []string
for _, sev := range requiredSevOrder {
@@ -178,11 +188,20 @@ func accumulateSeverityCounts(finding Resource) (map[string]int, map[string]int,
func configureHeader(s SummaryWriter, t *table.Table, columnHeading []string) {
sevCount := len(s.Severities)
if len(columnHeading) > 2 {
headerRow := []string{columnHeading[0], columnHeading[1]}
headerRow := []string{
columnHeading[0],
columnHeading[1],
}
// vulnerabilities headings
count := len(columnHeading) - len(headerRow)
colSpan := []int{1, 1}
headerAlignment := []table.Alignment{table.AlignLeft, table.AlignLeft}
colSpan := []int{
1,
1,
}
headerAlignment := []table.Alignment{
table.AlignLeft,
table.AlignLeft,
}
for i := 0; i < count; i++ {
headerRow = append(headerRow, s.SeverityHeadings...)
colSpan = append(colSpan, sevCount)

View File

@@ -10,67 +10,102 @@ import (
)
func TestReport_ColumnHeading(t *testing.T) {
allSecurityChecks := []string{
types.SecurityCheckVulnerability,
types.SecurityCheckConfig,
types.SecurityCheckSecret,
types.SecurityCheckRbac,
allScanners := []string{
types.VulnerabilityScanner,
types.MisconfigScanner,
types.SecretScanner,
types.RBACScanner,
}
tests := []struct {
name string
securityChecks []string
scanners []string
components []string
availableColumns []string
want []string
}{
{
name: "filter workload columns",
securityChecks: allSecurityChecks,
scanners: allScanners,
availableColumns: WorkloadColumns(),
components: []string{workloadComponent, infraComponent},
want: []string{NamespaceColumn, ResourceColumn, VulnerabilitiesColumn, MisconfigurationsColumn, SecretsColumn},
components: []string{
workloadComponent,
infraComponent,
},
want: []string{
NamespaceColumn,
ResourceColumn,
VulnerabilitiesColumn,
MisconfigurationsColumn,
SecretsColumn,
},
},
{
name: "filter rbac columns",
securityChecks: allSecurityChecks,
scanners: allScanners,
components: []string{},
availableColumns: RoleColumns(),
want: []string{NamespaceColumn, ResourceColumn, RbacAssessmentColumn},
want: []string{
NamespaceColumn,
ResourceColumn,
RbacAssessmentColumn,
},
},
{
name: "filter infra columns",
securityChecks: allSecurityChecks,
components: []string{workloadComponent, infraComponent},
scanners: allScanners,
components: []string{
workloadComponent,
infraComponent,
},
availableColumns: InfraColumns(),
want: []string{NamespaceColumn, ResourceColumn, InfraAssessmentColumn},
want: []string{
NamespaceColumn,
ResourceColumn,
InfraAssessmentColumn,
},
},
{
name: "config column only",
securityChecks: []string{types.SecurityCheckConfig},
components: []string{workloadComponent, infraComponent},
scanners: []string{types.MisconfigScanner},
components: []string{
workloadComponent,
infraComponent,
},
availableColumns: WorkloadColumns(),
want: []string{NamespaceColumn, ResourceColumn, MisconfigurationsColumn},
want: []string{
NamespaceColumn,
ResourceColumn,
MisconfigurationsColumn,
},
},
{
name: "secret column only",
securityChecks: []string{types.SecurityCheckSecret},
scanners: []string{types.SecretScanner},
components: []string{},
availableColumns: WorkloadColumns(),
want: []string{NamespaceColumn, ResourceColumn, SecretsColumn},
want: []string{
NamespaceColumn,
ResourceColumn,
SecretsColumn,
},
},
{
name: "vuln column only",
securityChecks: []string{types.SecurityCheckVulnerability},
scanners: []string{types.VulnerabilityScanner},
components: []string{},
availableColumns: WorkloadColumns(),
want: []string{NamespaceColumn, ResourceColumn, VulnerabilitiesColumn},
want: []string{
NamespaceColumn,
ResourceColumn,
VulnerabilitiesColumn,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
column := ColumnHeading(tt.securityChecks, tt.components, tt.availableColumns)
column := ColumnHeading(tt.scanners, tt.components, tt.availableColumns)
if !assert.Equal(t, column, tt.want) {
t.Error(fmt.Errorf("TestReport_ColumnHeading want %v got %v", tt.want, column))
}

View File

@@ -24,7 +24,11 @@ type Scanner struct {
}
func NewScanner(cluster string, runner cmd.Runner, opts flag.Options) *Scanner {
return &Scanner{cluster, runner, opts}
return &Scanner{
cluster,
runner,
opts,
}
}
func (s *Scanner) Scan(ctx context.Context, artifacts []*artifacts.Artifact) (report.Report, error) {
@@ -59,7 +63,7 @@ func (s *Scanner) Scan(ctx context.Context, artifacts []*artifacts.Artifact) (re
for _, artifact := range artifacts {
bar.Increment()
if shouldScanVulnsOrSecrets(s.opts.SecurityChecks) {
if shouldScanVulnsOrSecrets(s.opts.Scanners) {
resources, err := s.scanVulns(ctx, artifact)
if err != nil {
return report.Report{}, xerrors.Errorf("scanning vulnerabilities error: %w", err)
@@ -67,7 +71,7 @@ func (s *Scanner) Scan(ctx context.Context, artifacts []*artifacts.Artifact) (re
vulns = append(vulns, resources...)
}
if local.ShouldScanMisconfigOrRbac(s.opts.SecurityChecks) {
if local.ShouldScanMisconfigOrRbac(s.opts.Scanners) {
resource, err := s.scanMisconfigs(ctx, artifact)
if err != nil {
return report.Report{}, xerrors.Errorf("scanning misconfigurations error: %w", err)
@@ -137,7 +141,7 @@ func (s *Scanner) filter(ctx context.Context, r types.Report, artifact *artifact
return report.CreateResource(artifact, r, nil), nil
}
func shouldScanVulnsOrSecrets(securityChecks []string) bool {
return slices.Contains(securityChecks, types.SecurityCheckVulnerability) ||
slices.Contains(securityChecks, types.SecurityCheckSecret)
func shouldScanVulnsOrSecrets(scanners []string) bool {
return slices.Contains(scanners, types.VulnerabilityScanner) ||
slices.Contains(scanners, types.SecretScanner)
}

View File

@@ -57,7 +57,10 @@ func NewScanner(scannerOptions ScannerOption, opts ...Option) Scanner {
opt(o)
}
return Scanner{customHeaders: scannerOptions.CustomHeaders, client: o.rpcClient}
return Scanner{
customHeaders: scannerOptions.CustomHeaders,
client: o.rpcClient,
}
}
// Scan scans the image
@@ -79,7 +82,7 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
BlobIds: blobKeys,
Options: &rpc.ScanOptions{
VulnType: opts.VulnType,
SecurityChecks: opts.SecurityChecks,
Scanners: opts.Scanners,
ListAllPackages: opts.ListAllPackages,
LicenseCategories: licenseCategories,
},

View File

@@ -44,7 +44,7 @@ func teeError(err error) error {
func (s *ScanServer) Scan(ctx context.Context, in *rpcScanner.ScanRequest) (*rpcScanner.ScanResponse, error) {
options := types.ScanOptions{
VulnType: in.Options.VulnType,
SecurityChecks: in.Options.SecurityChecks,
Scanners: in.Options.Scanners,
ListAllPackages: in.Options.ListAllPackages,
}
results, os, err := s.localScanner.Scan(ctx, in.Target, in.ArtifactId, in.BlobIds, options)
@@ -95,7 +95,10 @@ func (s *CacheServer) MissingBlobs(_ context.Context, in *rpcCache.MissingBlobsR
if err != nil {
return nil, teeError(xerrors.Errorf("failed to get missing blobs: %w", err))
}
return &rpcCache.MissingBlobsResponse{MissingArtifact: missingArtifact, MissingBlobIds: blobIDs}, nil
return &rpcCache.MissingBlobsResponse{
MissingArtifact: missingArtifact,
MissingBlobIds: blobIDs,
}, nil
}
// DeleteBlobs removes blobs by IDs

View File

@@ -114,7 +114,7 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
}
// Scan packages for vulnerabilities
if slices.Contains(options.SecurityChecks, types.SecurityCheckVulnerability) {
if slices.Contains(options.Scanners, types.VulnerabilityScanner) {
var vulnResults types.Results
vulnResults, eosl, err = s.scanVulnerabilities(target, artifactDetail, options)
if err != nil {
@@ -132,19 +132,19 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
}
// Scan IaC config files
if ShouldScanMisconfigOrRbac(options.SecurityChecks) {
if ShouldScanMisconfigOrRbac(options.Scanners) {
configResults := s.MisconfsToResults(artifactDetail.Misconfigurations)
results = append(results, configResults...)
}
// Scan secrets
if slices.Contains(options.SecurityChecks, types.SecurityCheckSecret) {
if slices.Contains(options.Scanners, types.SecretScanner) {
secretResults := s.secretsToResults(artifactDetail.Secrets)
results = append(results, secretResults...)
}
// Scan licenses
if slices.Contains(options.SecurityChecks, types.SecurityCheckLicense) {
if slices.Contains(options.Scanners, types.LicenseScanner) {
licenseResults := s.scanLicenses(artifactDetail, options.LicenseCategories)
results = append(results, licenseResults...)
}
@@ -538,7 +538,7 @@ func mergePkgs(pkgs, pkgsFromCommands []ftypes.Package) []ftypes.Package {
return pkgs
}
func ShouldScanMisconfigOrRbac(securityChecks []string) bool {
return slices.Contains(securityChecks, types.SecurityCheckConfig) ||
slices.Contains(securityChecks, types.SecurityCheckRbac)
func ShouldScanMisconfigOrRbac(scanners []string) bool {
return slices.Contains(scanners, types.MisconfigScanner) ||
slices.Contains(scanners, types.RBACScanner)
}

View File

@@ -42,8 +42,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -149,8 +152,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
ListAllPackages: true,
},
},
@@ -297,8 +303,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
ListAllPackages: true,
},
},
@@ -403,8 +412,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -483,8 +495,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -563,8 +578,11 @@ func TestScanner_Scan(t *testing.T) {
target: "fedora:27",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -636,8 +654,11 @@ func TestScanner_Scan(t *testing.T) {
target: "busybox:latest",
layerIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -658,7 +679,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -767,7 +788,7 @@ func TestScanner_Scan(t *testing.T) {
target: "/app/configs",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
SecurityChecks: []string{types.SecurityCheckConfig},
Scanners: []string{types.MisconfigScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -916,8 +937,11 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeOS, types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
VulnType: []string{
types.VulnTypeOS,
types.VulnTypeLibrary,
},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/happy.yaml"},
@@ -938,7 +962,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
VulnType: []string{types.VulnTypeLibrary},
SecurityChecks: []string{types.SecurityCheckVulnerability},
Scanners: []string{types.VulnerabilityScanner},
},
},
fixtures: []string{"testdata/fixtures/sad.yaml"},

View File

@@ -7,7 +7,7 @@ import (
// ScanOptions holds the attributes for scanning vulnerabilities
type ScanOptions struct {
VulnType []string
SecurityChecks []string
Scanners []string
ScanRemovedPackages bool
Platform string
ListAllPackages bool

View File

@@ -3,8 +3,8 @@ package types
// VulnType represents vulnerability type
type VulnType = string
// SecurityCheck represents the type of security check
type SecurityCheck = string
// Scanner represents the type of security scanning
type Scanner = string
const (
// VulnTypeUnknown is a vulnerability type of unknown
@@ -16,29 +16,35 @@ const (
// VulnTypeLibrary is a vulnerability type of programming language dependencies
VulnTypeLibrary = VulnType("library")
// SecurityCheckUnknown is a security check of unknown
SecurityCheckUnknown = SecurityCheck("unknown")
// ScannerUnknown is the scanner of unknown
ScannerUnknown = Scanner("unknown")
// SecurityCheckVulnerability is a security check of vulnerabilities
SecurityCheckVulnerability = SecurityCheck("vuln")
// VulnerabilityScanner is the scanner of vulnerabilities
VulnerabilityScanner = Scanner("vuln")
// SecurityCheckConfig is a security check of misconfigurations
SecurityCheckConfig = SecurityCheck("config")
// MisconfigScanner is the scanner of misconfigurations
MisconfigScanner = Scanner("config")
// SecurityCheckSecret is a security check of secrets
SecurityCheckSecret = SecurityCheck("secret")
// SecretScanner is the scanner of secrets
SecretScanner = Scanner("secret")
// SecurityCheckRbac is a security check of rbac assessment
SecurityCheckRbac = SecurityCheck("rbac")
// RBACScanner is the scanner of rbac assessment
RBACScanner = Scanner("rbac")
// SecurityCheckLicense is the security check of licenses
SecurityCheckLicense = SecurityCheck("license")
// LicenseScanner is the scanner of licenses
LicenseScanner = Scanner("license")
)
var (
VulnTypes = []string{VulnTypeOS, VulnTypeLibrary}
SecurityChecks = []string{
SecurityCheckVulnerability, SecurityCheckConfig, SecurityCheckRbac,
SecurityCheckSecret, SecurityCheckLicense,
VulnTypes = []string{
VulnTypeOS,
VulnTypeLibrary,
}
Scanners = []string{
VulnerabilityScanner,
MisconfigScanner,
RBACScanner,
SecretScanner,
LicenseScanner,
}
)

View File

@@ -7,15 +7,13 @@
package cache
import (
reflect "reflect"
sync "sync"
common "github.com/aquasecurity/trivy/rpc/common"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
common "github.com/aquasecurity/trivy/rpc/common"
reflect "reflect"
sync "sync"
)
const (

View File

@@ -3,40 +3,26 @@
package cache
import (
context "context"
fmt "fmt"
import context "context"
import fmt "fmt"
import http "net/http"
import ioutil "io/ioutil"
import json "encoding/json"
import strconv "strconv"
import strings "strings"
http "net/http"
import protojson "google.golang.org/protobuf/encoding/protojson"
import proto "google.golang.org/protobuf/proto"
import twirp "github.com/twitchtv/twirp"
import ctxsetters "github.com/twitchtv/twirp/ctxsetters"
ioutil "io/ioutil"
import google_protobuf2 "google.golang.org/protobuf/types/known/emptypb"
json "encoding/json"
strconv "strconv"
strings "strings"
protojson "google.golang.org/protobuf/encoding/protojson"
proto "google.golang.org/protobuf/proto"
twirp "github.com/twitchtv/twirp"
ctxsetters "github.com/twitchtv/twirp/ctxsetters"
google_protobuf2 "google.golang.org/protobuf/types/known/emptypb"
bytes "bytes"
errors "errors"
io "io"
path "path"
url "net/url"
)
import bytes "bytes"
import errors "errors"
import io "io"
import path "path"
import url "net/url"
// Version compatibility assertion.
// If the constant is not defined in the package, that likely means

View File

@@ -7,13 +7,11 @@
package scanner
import (
reflect "reflect"
sync "sync"
common "github.com/aquasecurity/trivy/rpc/common"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
common "github.com/aquasecurity/trivy/rpc/common"
reflect "reflect"
sync "sync"
)
const (
@@ -94,7 +92,8 @@ func (x *ScanRequest) GetOptions() *ScanOptions {
return nil
}
// cf. https://stackoverflow.com/questions/38886789/protobuf3-how-to-describe-map-of-repeated-string
// cf.
// https://stackoverflow.com/questions/38886789/protobuf3-how-to-describe-map-of-repeated-string
type Licenses struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -148,7 +147,7 @@ type ScanOptions struct {
unknownFields protoimpl.UnknownFields
VulnType []string `protobuf:"bytes,1,rep,name=vuln_type,json=vulnType,proto3" json:"vuln_type,omitempty"`
SecurityChecks []string `protobuf:"bytes,2,rep,name=security_checks,json=securityChecks,proto3" json:"security_checks,omitempty"`
Scanners []string `protobuf:"bytes,2,rep,name=scanners,proto3" json:"scanners,omitempty"`
ListAllPackages bool `protobuf:"varint,3,opt,name=list_all_packages,json=listAllPackages,proto3" json:"list_all_packages,omitempty"`
LicenseCategories map[string]*Licenses `protobuf:"bytes,4,rep,name=license_categories,json=licenseCategories,proto3" json:"license_categories,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
@@ -192,9 +191,9 @@ func (x *ScanOptions) GetVulnType() []string {
return nil
}
func (x *ScanOptions) GetSecurityChecks() []string {
func (x *ScanOptions) GetScanners() []string {
if x != nil {
return x.SecurityChecks
return x.Scanners
}
return nil
}
@@ -391,69 +390,68 @@ var file_rpc_scanner_service_proto_rawDesc = []byte{
0x53, 0x63, 0x61, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x22, 0x20, 0x0a, 0x08, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73,
0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xc6, 0x02, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f,
0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xb9, 0x02, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x75, 0x6c, 0x6e, 0x5f, 0x74,
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x76, 0x75, 0x6c, 0x6e, 0x54,
0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f,
0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65,
0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x2a, 0x0a, 0x11,
0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c,
0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61,
0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67,
0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x60, 0x0a,
0x16, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69,
0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79,
0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
0x64, 0x0a, 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x20, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x72,
0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f, 0x53, 0x52, 0x02, 0x6f,
0x73, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x9a, 0x03, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x45, 0x0a, 0x0f, 0x76, 0x75, 0x6c, 0x6e,
0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0f,
0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12,
0x54, 0x0a, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x72, 0x69,
0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74,
0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x06,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74,
0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
0x31, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
0x65, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74,
0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x75, 0x73, 0x74,
0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0f, 0x63, 0x75, 0x73, 0x74,
0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x73,
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74,
0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72,
0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65,
0x74, 0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x45, 0x0a,
0x04, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63,
0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61,
0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f,
0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65,
0x72, 0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12,
0x2a, 0x0a, 0x11, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b,
0x61, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6c, 0x69, 0x73, 0x74,
0x41, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x12, 0x6c,
0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e,
0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61,
0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6c,
0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73,
0x1a, 0x60, 0x0a, 0x16, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67,
0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72,
0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0x64, 0x0a, 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x20, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f, 0x53,
0x52, 0x02, 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63,
0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x9a, 0x03, 0x0a, 0x06, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x45, 0x0a, 0x0f, 0x76,
0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74,
0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69,
0x65, 0x73, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x74,
0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x61, 0x73,
0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x12,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79,
0x70, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63,
0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f,
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0f, 0x63,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x35,
0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53,
0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65,
0x63, 0x72, 0x65, 0x74, 0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72,
0x12, 0x45, 0x0a, 0x04, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79,
0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e,
0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61,
0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -24,7 +24,7 @@ message Licenses {
message ScanOptions {
repeated string vuln_type = 1;
repeated string security_checks = 2;
repeated string scanners = 2;
bool list_all_packages = 3;
map<string, Licenses> license_categories = 4;
}

View File

@@ -3,38 +3,24 @@
package scanner
import (
context "context"
fmt "fmt"
import context "context"
import fmt "fmt"
import http "net/http"
import ioutil "io/ioutil"
import json "encoding/json"
import strconv "strconv"
import strings "strings"
http "net/http"
import protojson "google.golang.org/protobuf/encoding/protojson"
import proto "google.golang.org/protobuf/proto"
import twirp "github.com/twitchtv/twirp"
import ctxsetters "github.com/twitchtv/twirp/ctxsetters"
ioutil "io/ioutil"
json "encoding/json"
strconv "strconv"
strings "strings"
protojson "google.golang.org/protobuf/encoding/protojson"
proto "google.golang.org/protobuf/proto"
twirp "github.com/twitchtv/twirp"
ctxsetters "github.com/twitchtv/twirp/ctxsetters"
bytes "bytes"
errors "errors"
io "io"
path "path"
url "net/url"
)
import bytes "bytes"
import errors "errors"
import io "io"
import path "path"
import url "net/url"
// Version compatibility assertion.
// If the constant is not defined in the package, that likely means
@@ -1108,45 +1094,44 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error)
}
var twirpFileDescriptor0 = []byte{
// 630 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0x6f, 0x6f, 0xd3, 0x3e,
0x10, 0xc7, 0xd5, 0x76, 0x6b, 0xbb, 0xcb, 0x4f, 0xbf, 0x76, 0x16, 0x4c, 0x59, 0xc7, 0x9f, 0xaa,
0x0f, 0xa0, 0xe2, 0x41, 0xca, 0x32, 0x10, 0x08, 0x1e, 0xc1, 0x18, 0x68, 0x12, 0x68, 0x93, 0x3b,
0xf1, 0x80, 0x27, 0xc1, 0x75, 0x6e, 0x9d, 0xb5, 0x34, 0xce, 0x6c, 0xa7, 0x52, 0xde, 0xca, 0x5e,
0x10, 0xaf, 0x0b, 0xd9, 0x49, 0xa6, 0xb5, 0xdb, 0x78, 0x14, 0xdf, 0xdd, 0xe7, 0xce, 0x67, 0xdf,
0x37, 0x86, 0x5d, 0x95, 0xf1, 0x89, 0xe6, 0x2c, 0x4d, 0x51, 0x4d, 0x34, 0xaa, 0xa5, 0xe0, 0x18,
0x64, 0x4a, 0x1a, 0x49, 0xfa, 0x46, 0x89, 0x65, 0x11, 0x54, 0xc1, 0x60, 0xb9, 0x3f, 0xf0, 0x2d,
0xcc, 0xe5, 0x62, 0x21, 0xd3, 0x55, 0x76, 0x74, 0xdd, 0x00, 0x6f, 0xca, 0x59, 0x4a, 0xf1, 0x2a,
0x47, 0x6d, 0xc8, 0x0e, 0xb4, 0x0d, 0x53, 0x73, 0x34, 0x7e, 0x63, 0xd8, 0x18, 0x6f, 0xd1, 0xca,
0x22, 0xcf, 0xc1, 0x63, 0xca, 0x88, 0x73, 0xc6, 0x4d, 0x24, 0x62, 0xbf, 0xe9, 0x82, 0x50, 0xbb,
0x8e, 0x63, 0xb2, 0x0b, 0xdd, 0x59, 0x22, 0x67, 0x91, 0x88, 0xb5, 0xdf, 0x1a, 0xb6, 0xc6, 0x5b,
0xb4, 0x63, 0xed, 0xe3, 0x58, 0x93, 0x77, 0xd0, 0x91, 0x99, 0x11, 0x32, 0xd5, 0xfe, 0xc6, 0xb0,
0x31, 0xf6, 0xc2, 0xa7, 0xc1, 0x7a, 0x87, 0x81, 0xed, 0xe1, 0xa4, 0x84, 0x68, 0x4d, 0x8f, 0x86,
0xd0, 0xfd, 0x2e, 0x38, 0xa6, 0x1a, 0x35, 0x79, 0x04, 0x9b, 0x29, 0x5b, 0xa0, 0xf6, 0x1b, 0xae,
0x78, 0x69, 0x8c, 0xfe, 0x34, 0xcb, 0xf6, 0xab, 0x54, 0xb2, 0x07, 0x5b, 0xcb, 0x3c, 0x49, 0x23,
0x53, 0x64, 0x58, 0x91, 0x5d, 0xeb, 0x38, 0x2b, 0x32, 0x24, 0x2f, 0xa1, 0xa7, 0x91, 0xe7, 0x4a,
0x98, 0x22, 0xe2, 0x17, 0xc8, 0x2f, 0xb5, 0xdf, 0x74, 0xc8, 0xff, 0xb5, 0xfb, 0xd0, 0x79, 0xc9,
0x2b, 0xd8, 0x4e, 0x84, 0x36, 0x11, 0x4b, 0x92, 0x28, 0x63, 0xfc, 0x92, 0xcd, 0xd1, 0x1e, 0xaa,
0x31, 0xee, 0xd2, 0x9e, 0x0d, 0x7c, 0x4a, 0x92, 0xd3, 0xca, 0x4d, 0x38, 0x90, 0xa4, 0xec, 0x31,
0xe2, 0xcc, 0xe0, 0x5c, 0x2a, 0x81, 0xf6, 0x9c, 0xad, 0xb1, 0x17, 0xbe, 0xf9, 0xe7, 0x39, 0x83,
0xea, 0x6c, 0x87, 0x37, 0x69, 0x47, 0xa9, 0x51, 0x05, 0xdd, 0x4e, 0xd6, 0xfd, 0x83, 0xdf, 0xb0,
0x73, 0x3f, 0x4c, 0xfa, 0xd0, 0xba, 0xc4, 0xa2, 0x1a, 0x96, 0x5d, 0x92, 0xd7, 0xb0, 0xb9, 0x64,
0x49, 0x8e, 0x6e, 0x46, 0x5e, 0x38, 0xb8, 0xdb, 0x43, 0x7d, 0xa7, 0xb4, 0x04, 0x3f, 0x34, 0xdf,
0x37, 0x46, 0x31, 0xfc, 0x57, 0xca, 0x40, 0x67, 0x32, 0xd5, 0x48, 0x86, 0xd0, 0x94, 0xda, 0x95,
0xf5, 0xc2, 0x7e, 0x55, 0xa2, 0x14, 0x50, 0x70, 0x32, 0xa5, 0x4d, 0xa9, 0x49, 0x08, 0x1d, 0x85,
0x3a, 0x4f, 0x4c, 0x39, 0x6f, 0x2f, 0xf4, 0xef, 0xee, 0x44, 0x1d, 0x40, 0x6b, 0x70, 0x74, 0xdd,
0x82, 0x76, 0xe9, 0x7b, 0x50, 0x68, 0x47, 0xd0, 0xb3, 0x03, 0x43, 0xc5, 0x66, 0x22, 0x11, 0xc6,
0x5e, 0x66, 0xd3, 0x95, 0xdf, 0x5b, 0xed, 0xe2, 0xe7, 0x2d, 0xa8, 0xa0, 0xeb, 0x39, 0xe4, 0x0c,
0xb6, 0x17, 0x42, 0x73, 0x99, 0x9e, 0x8b, 0x79, 0xae, 0x58, 0xad, 0x3e, 0x5b, 0xe8, 0xc5, 0x6a,
0xa1, 0x2f, 0x68, 0x90, 0x1b, 0x8c, 0x7f, 0xac, 0xe1, 0xf4, 0x6e, 0x01, 0x2b, 0x42, 0x9e, 0x30,
0xad, 0xfd, 0xb6, 0xeb, 0xb9, 0x34, 0x08, 0x81, 0x0d, 0xa7, 0xb7, 0x96, 0x73, 0xba, 0x35, 0xd9,
0x87, 0xee, 0x8d, 0x72, 0x36, 0xdd, 0xb6, 0x8f, 0x57, 0xb7, 0xad, 0x04, 0x44, 0x6f, 0x30, 0xf2,
0x0d, 0xfa, 0x3c, 0xd7, 0x46, 0x2e, 0x22, 0x85, 0x5a, 0xe6, 0x8a, 0xa3, 0xf6, 0x3b, 0x2e, 0xf5,
0xc9, 0x6a, 0xea, 0xa1, 0xa3, 0x68, 0x05, 0xd1, 0x1e, 0x5f, 0xb1, 0x35, 0x79, 0x0b, 0x1d, 0x8d,
0x5c, 0xa1, 0xd1, 0x7e, 0xf7, 0xbe, 0xab, 0x9b, 0xba, 0xe0, 0x57, 0x91, 0xc6, 0x22, 0x9d, 0xd3,
0x9a, 0x0d, 0x4f, 0xa1, 0x33, 0x2d, 0x47, 0x47, 0x8e, 0x60, 0xc3, 0x2e, 0xc9, 0x03, 0x3f, 0x6a,
0xf5, 0x58, 0x0c, 0x9e, 0x3d, 0x14, 0x2e, 0x45, 0xf4, 0xf9, 0xe0, 0xd7, 0xfe, 0x5c, 0x98, 0x8b,
0x7c, 0x66, 0x77, 0x9e, 0xb0, 0xab, 0x9c, 0xd5, 0x3f, 0xda, 0xc4, 0x25, 0x4e, 0x6e, 0xbd, 0x61,
0x1f, 0xab, 0xef, 0xac, 0xed, 0x1e, 0xa6, 0x83, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa6, 0xdf,
0x7a, 0xaf, 0xe1, 0x04, 0x00, 0x00,
// 617 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0x5f, 0x6f, 0xd3, 0x30,
0x10, 0xc0, 0xd5, 0x76, 0x6b, 0xb3, 0x0b, 0xd2, 0x3a, 0x0b, 0xa6, 0xac, 0xe3, 0x4f, 0xd5, 0x07,
0x54, 0xf1, 0x90, 0xb2, 0x0c, 0x04, 0x82, 0x27, 0x18, 0x03, 0x4d, 0x02, 0x6d, 0x72, 0x27, 0x1e,
0x78, 0x09, 0xae, 0x73, 0x2b, 0xd6, 0xd2, 0x38, 0xb3, 0x9d, 0x4a, 0xf9, 0x2a, 0xfb, 0x26, 0x7c,
0x3b, 0x64, 0x27, 0x99, 0xd6, 0x6e, 0xe3, 0x29, 0xbe, 0xbb, 0xdf, 0xfd, 0xf3, 0x5d, 0x0c, 0x7b,
0x2a, 0xe7, 0x13, 0xcd, 0x59, 0x96, 0xa1, 0x9a, 0x68, 0x54, 0x4b, 0xc1, 0x31, 0xcc, 0x95, 0x34,
0x92, 0xf4, 0x8d, 0x12, 0xcb, 0x32, 0xac, 0x8d, 0xe1, 0xf2, 0x60, 0x10, 0x58, 0x98, 0xcb, 0xc5,
0x42, 0x66, 0xab, 0xec, 0xe8, 0xba, 0x05, 0xfe, 0x94, 0xb3, 0x8c, 0xe2, 0x55, 0x81, 0xda, 0x90,
0x5d, 0xe8, 0x1a, 0xa6, 0xe6, 0x68, 0x82, 0xd6, 0xb0, 0x35, 0xde, 0xa2, 0xb5, 0x44, 0x5e, 0x80,
0xcf, 0x94, 0x11, 0x17, 0x8c, 0x9b, 0x58, 0x24, 0x41, 0xdb, 0x19, 0xa1, 0x51, 0x9d, 0x24, 0x64,
0x0f, 0xbc, 0x59, 0x2a, 0x67, 0xb1, 0x48, 0x74, 0xd0, 0x19, 0x76, 0xc6, 0x5b, 0xb4, 0x67, 0xe5,
0x93, 0x44, 0x93, 0x77, 0xd0, 0x93, 0xb9, 0x11, 0x32, 0xd3, 0xc1, 0xc6, 0xb0, 0x35, 0xf6, 0xa3,
0x67, 0xe1, 0x7a, 0x85, 0xa1, 0xad, 0xe1, 0xb4, 0x82, 0x68, 0x43, 0x8f, 0x86, 0xe0, 0x7d, 0x17,
0x1c, 0x33, 0x8d, 0x9a, 0x3c, 0x86, 0xcd, 0x8c, 0x2d, 0x50, 0x07, 0x2d, 0x17, 0xbc, 0x12, 0x46,
0x7f, 0xdb, 0x55, 0xf9, 0xb5, 0x2b, 0xd9, 0x87, 0xad, 0x65, 0x91, 0x66, 0xb1, 0x29, 0x73, 0xac,
0x49, 0xcf, 0x2a, 0xce, 0xcb, 0x1c, 0xc9, 0x00, 0xbc, 0x3a, 0xa3, 0x0e, 0xda, 0x95, 0xad, 0x91,
0xc9, 0x2b, 0xd8, 0x49, 0x85, 0x36, 0x31, 0x4b, 0xd3, 0x38, 0x67, 0xfc, 0x92, 0xcd, 0xd1, 0xf6,
0xd1, 0x1a, 0x7b, 0x74, 0xdb, 0x1a, 0x3e, 0xa5, 0xe9, 0x59, 0xad, 0x26, 0x1c, 0x48, 0x5a, 0x95,
0x15, 0x73, 0x66, 0x70, 0x2e, 0x95, 0x40, 0xdb, 0x5a, 0x67, 0xec, 0x47, 0x6f, 0xfe, 0xdb, 0x5a,
0x58, 0xb7, 0x73, 0x74, 0xe3, 0x76, 0x9c, 0x19, 0x55, 0xd2, 0x9d, 0x74, 0x5d, 0x3f, 0xf8, 0x0d,
0xbb, 0xf7, 0xc3, 0xa4, 0x0f, 0x9d, 0x4b, 0x2c, 0xeb, 0xf9, 0xd8, 0x23, 0x79, 0x0d, 0x9b, 0x4b,
0x96, 0x16, 0xe8, 0xc6, 0xe2, 0x47, 0x83, 0xbb, 0x35, 0x34, 0xd7, 0x48, 0x2b, 0xf0, 0x43, 0xfb,
0x7d, 0x6b, 0x94, 0xc0, 0xa3, 0x6a, 0xf2, 0x3a, 0x97, 0x99, 0x46, 0x32, 0x84, 0xb6, 0xd4, 0x2e,
0xac, 0x1f, 0xf5, 0xeb, 0x10, 0xd5, 0xce, 0x84, 0xa7, 0x53, 0xda, 0x96, 0x9a, 0x44, 0xd0, 0x53,
0xa8, 0x8b, 0xd4, 0x54, 0x23, 0xf6, 0xa3, 0xe0, 0x6e, 0x26, 0xea, 0x00, 0xda, 0x80, 0xa3, 0xeb,
0x0e, 0x74, 0x2b, 0xdd, 0x83, 0xbb, 0x75, 0x0c, 0xdb, 0x76, 0x46, 0xa8, 0xd8, 0x4c, 0xa4, 0xc2,
0xd8, 0xcb, 0x6c, 0xbb, 0xf0, 0xfb, 0xab, 0x55, 0xfc, 0xbc, 0x05, 0x95, 0x74, 0xdd, 0x87, 0x9c,
0xc3, 0xce, 0x42, 0x68, 0x2e, 0xb3, 0x0b, 0x31, 0x2f, 0x14, 0x6b, 0x16, 0xce, 0x06, 0x7a, 0xb9,
0x1a, 0xe8, 0x0b, 0x1a, 0xe4, 0x06, 0x93, 0x1f, 0x6b, 0x38, 0xbd, 0x1b, 0xc0, 0xee, 0x1d, 0x4f,
0x99, 0xd6, 0x41, 0xd7, 0xd5, 0x5c, 0x09, 0x84, 0xc0, 0x86, 0x5b, 0xb1, 0x8e, 0x53, 0xba, 0x33,
0x39, 0x00, 0xef, 0x66, 0x73, 0x36, 0x5d, 0xda, 0x27, 0xab, 0x69, 0xeb, 0x05, 0xa2, 0x37, 0x18,
0xf9, 0x06, 0x7d, 0x5e, 0x68, 0x23, 0x17, 0xb1, 0x42, 0x2d, 0x0b, 0xc5, 0x51, 0x07, 0x3d, 0xe7,
0xfa, 0x74, 0xd5, 0xf5, 0xc8, 0x51, 0xb4, 0x86, 0xe8, 0x36, 0x5f, 0x91, 0x35, 0x79, 0x0b, 0x3d,
0x8d, 0x5c, 0xa1, 0xd1, 0x81, 0x77, 0xdf, 0xd5, 0x4d, 0x9d, 0xf1, 0xab, 0xc8, 0x12, 0x91, 0xcd,
0x69, 0xc3, 0x46, 0x67, 0xd0, 0x9b, 0x56, 0xa3, 0x23, 0xc7, 0xb0, 0x61, 0x8f, 0xe4, 0x81, 0x7f,
0xb3, 0x7e, 0x1f, 0x06, 0xcf, 0x1f, 0x32, 0x57, 0x4b, 0xf4, 0xf9, 0xf0, 0xd7, 0xc1, 0x5c, 0x98,
0x3f, 0xc5, 0xcc, 0x66, 0x9e, 0xb0, 0xab, 0x82, 0x69, 0xe4, 0x85, 0x12, 0xa6, 0x9c, 0x38, 0xc7,
0xc9, 0xad, 0x67, 0xeb, 0x63, 0xfd, 0x9d, 0x75, 0xdd, 0x5b, 0x74, 0xf8, 0x2f, 0x00, 0x00, 0xff,
0xff, 0x18, 0xc4, 0x97, 0x86, 0xd4, 0x04, 0x00, 0x00,
}