Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(misconf): enable --policy flag to accept directory and files both #4777

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ trivy aws [flags]
--arn string The AWS ARN to show results for. Useful to filter results once a scan is cached.
--compliance string compliance report to generate (aws-cis-1.2, aws-cis-1.4)
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--endpoint string AWS Endpoint override
--exit-code int specify exit code when any security issues are found
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ trivy config [flags] DIR
--clear-cache clear image caches without scanning
--compliance string compliance report to generate
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--enable-modules strings [EXPERIMENTAL] module names to enable
--exit-code int specify exit code when any security issues are found
--file-patterns strings specify config file patterns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ trivy filesystem [flags] PATH
--clear-cache clear image caches without scanning
--compliance string compliance report to generate
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ trivy image [flags] IMAGE_NAME
--clear-cache clear image caches without scanning
--compliance string compliance report to generate (docker-cis)
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ trivy kubernetes [flags] { cluster | all | specific resources like kubectl. eg:
--compliance string compliance report to generate (k8s-nsa,k8s-cis, k8s-pss-baseline, k8s-pss-restricted)
--components strings specify which components to scan (default [workload,infra])
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--context string specify a context to scan
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ trivy repository [flags] REPO_URL
--clear-cache clear image caches without scanning
--commit string pass the commit hash to be scanned
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_rootfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ trivy rootfs [flags] ROOTDIR
--cache-ttl duration cache TTL when using redis as cache backend
--clear-cache clear image caches without scanning
--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
--config-policy strings specify the paths to the Rego policy files or to the directories containing them, applying config files
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/config-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ rego
policy:
- policy/repository
- policy/custom
- policy/some-policy.rego

# Same as '--config-data'
# Default is empty
Expand Down
7 changes: 2 additions & 5 deletions docs/docs/scanner/misconfiguration/custom/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

## Overview
You can write custom policies in [Rego][rego].
Once you finish writing custom policies, you can pass the directory where those policies are stored with `--policy` option.
Once you finish writing custom policies, you can pass the policy files or the directory where those policies are stored with `--policy` option.

``` bash
trivy conf --policy /path/to/custom_policies --namespaces user /path/to/config_dir
trivy conf --policy /path/to/policy.rego --policy /path/to/custom_policies --namespaces user /path/to/config_dir
```

!!! Tip
Note: The `--policy` path always needs to refer to a directory. You cannot pass a specific policy file.

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

### File formats
Expand Down
3 changes: 1 addition & 2 deletions docs/docs/scanner/misconfiguration/custom/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ The policies can be placed in a structure as follows
└── barschema.json
```

To use such a policy with Trivy, use the `--config-policy` flag that points to the directory where the schemas and policies
are contained.
To use such a policy with Trivy, use the `--config-policy` flag that points to the policy file or to the directory where the schemas and policies are contained.

```bash
$ trivy --config-policy=/Users/user/my-custom-policies <path/to/iac>
Expand Down
9 changes: 4 additions & 5 deletions docs/docs/scanner/misconfiguration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,19 +316,18 @@ This section describes misconfiguration-specific configuration.
Other common options are documented [here](../../configuration/index.md).

### Pass custom policies
You can pass directories including your custom policies through `--policy` option.
This can be repeated for specifying multiple directories.
You can pass policy files or directories including your custom policies through `--policy` option.
This can be repeated for specifying multiple files or directories.

```bash
cd examplex/misconf/
trivy conf --policy custom-policy/policy --policy combine/policy --namespaces user misconf/mixed
trivy conf --policy custom-policy/policy --policy combine/policy --policy policy.rego --namespaces user misconf/mixed
```

For more details, see [Custom Policies](./custom/index.md).

!!! tip
You also need to specify `--namespaces` option.
Furthermore, the `--policy` path always needs to refer to a directory. You cannot pass a specific policy file.
You also need to specify `--namespaces` option.

### Pass custom data
You can pass directories including your custom data through `--data` option.
Expand Down
33 changes: 30 additions & 3 deletions pkg/fanal/cache/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"

"golang.org/x/mod/sumdb/dirhash"
"golang.org/x/xerrors"
Expand Down Expand Up @@ -36,12 +39,12 @@ func CalcKey(id string, analyzerVersions analyzer.Versions, hookVersions map[str
// Write policy and data contents
for _, paths := range [][]string{artifactOpt.MisconfScannerOption.PolicyPaths, artifactOpt.MisconfScannerOption.DataPaths} {
for _, p := range paths {
s, err := dirhash.HashDir(p, "", dirhash.DefaultHash)
hash, err := hashContents(p)
if err != nil {
return "", xerrors.Errorf("hash dir error (%s): %w", p, err)
return "", err
}

if _, err = h.Write([]byte(s)); err != nil {
if _, err := h.Write([]byte(hash)); err != nil {
return "", xerrors.Errorf("sha256 write error: %w", err)
}
}
Expand All @@ -51,3 +54,27 @@ func CalcKey(id string, analyzerVersions analyzer.Versions, hookVersions map[str

return fmt.Sprintf("sha256:%x", h.Sum(nil)), nil
}

func hashContents(path string) (string, error) {
fi, err := os.Stat(path)
if err != nil {
return "", xerrors.Errorf("file %q stat error: %w", path, err)
}

var hash string

if fi.IsDir() {
hash, err = dirhash.HashDir(path, "", dirhash.DefaultHash)
if err != nil {
return "", xerrors.Errorf("hash dir error (%s): %w", path, err)
}
} else {
hash, err = dirhash.DefaultHash([]string{filepath.Base(path)}, func(_ string) (io.ReadCloser, error) {
return os.Open(path)
})
if err != nil {
return "", xerrors.Errorf("hash file error (%s): %w", path, err)
}
}
return hash, nil
}
16 changes: 15 additions & 1 deletion pkg/fanal/cache/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,20 @@ func TestCalcKey(t *testing.T) {
},
want: "sha256:9602d5ef5af086112cc9fae8310390ed3fb79f4b309d8881b9807e379c8dfa57",
},
{
name: "with policy file",
args: args{
key: "sha256:5c534be56eca62e756ef2ef51523feda0f19cd7c15bb0c015e3d6e3ae090bf6e",
analyzerVersions: analyzer.Versions{
Analyzers: map[string]int{
"alpine": 1,
"debian": 1,
},
},
policy: []string{"testdata/policy/test.rego"},
},
want: "sha256:9602d5ef5af086112cc9fae8310390ed3fb79f4b309d8881b9807e379c8dfa57",
},
{
name: "skip files and dirs",
args: args{
Expand Down Expand Up @@ -173,7 +187,7 @@ func TestCalcKey(t *testing.T) {
},
policy: []string{"policydir"},
},
wantErr: "hash dir error",
wantErr: "file \"policydir\" stat error",
},
}
for _, tt := range tests {
Expand Down
2 changes: 1 addition & 1 deletion pkg/flag/rego_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var (
Name: "config-policy",
ConfigName: "rego.policy",
Value: []string{},
Usage: "specify paths to the Rego policy files directory, applying config files",
Usage: "specify the paths to the Rego policy files or to the directories containing them, applying config files",
Aliases: []Alias{
{Name: "policy"},
},
Expand Down
22 changes: 20 additions & 2 deletions pkg/misconf/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package misconf
import (
"context"
_ "embed"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
Expand Down Expand Up @@ -295,8 +297,24 @@ func createPolicyFS(policyPaths []string) (fs.FS, []string, error) {
if err != nil {
return nil, nil, xerrors.Errorf("failed to derive absolute path from '%s': %w", p, err)
}
if err = mfs.CopyFilesUnder(abs); err != nil {
return nil, nil, xerrors.Errorf("mapfs file copy error: %w", err)
fi, err := os.Stat(abs)
if errors.Is(err, os.ErrNotExist) {
return nil, nil, xerrors.Errorf("policy file %q not found", abs)
} else if err != nil {
return nil, nil, xerrors.Errorf("file %q stat error: %w", abs, err)
}

if fi.IsDir() {
if err = mfs.CopyFilesUnder(abs); err != nil {
return nil, nil, xerrors.Errorf("mapfs file copy error: %w", err)
}
} else {
if err := mfs.MkdirAll(filepath.Dir(abs), os.ModePerm); err != nil && !errors.Is(err, fs.ErrExist) {
return nil, nil, xerrors.Errorf("mapfs mkdir error: %w", err)
}
if err := mfs.WriteFile(abs, abs); err != nil {
return nil, nil, xerrors.Errorf("mapfs write error: %w", err)
}
}
}

Expand Down