Skip to content

Commit

Permalink
feat(misconf): enable --policy flag to accept directory and files both (
Browse files Browse the repository at this point in the history
aquasecurity#4777)

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

* fix test

* Revert "clarifying a dir path is required for custom policies (aquasecurity#4716)"

This reverts commit 8a1aa44.

* update doc

* update the flag description
  • Loading branch information
nikpivkin committed Jul 13, 2023
1 parent b43a3e6 commit d0d543b
Show file tree
Hide file tree
Showing 15 changed files with 81 additions and 26 deletions.
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
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_filesystem.md
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
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_kubernetes.md
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
2 changes: 1 addition & 1 deletion docs/docs/references/configuration/cli/trivy_repository.md
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

0 comments on commit d0d543b

Please sign in to comment.