diff --git a/docs/docs/coverage/language/python.md b/docs/docs/coverage/language/python.md index 15cadd6f96c3..7a697b87d250 100644 --- a/docs/docs/coverage/language/python.md +++ b/docs/docs/coverage/language/python.md @@ -42,7 +42,7 @@ Trivy parses your files generated by package managers in filesystem/repository s ### pip #### Dependency detection -Trivy only parses [version specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#id4) with `==` comparison operator and without `.*`. +Trivy only parses [version specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#id5) with `==` comparison operator and without `.*`. To convert unsupported version specifiers - use the `pip freeze` command. ```bash @@ -119,7 +119,7 @@ License detection is not supported for `Poetry`. ## Packaging Trivy parses the manifest files of installed packages in container image scanning and so on. -See [here](https://packaging.python.org/en/latest/discussions/wheel-vs-egg/) for the detail. +See [here](https://packaging.python.org/en/latest/discussions/package-formats/) for the detail. ### Egg Trivy looks for `*.egg-info`, `*.egg-info/PKG-INFO`, `*.egg` and `EGG-INFO/PKG-INFO` to identify Python packages. diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index 535a1b9e657e..b3876d6ad225 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -5,615 +5,605 @@ The config path can be overridden by the `--config` flag. An example is [here][example]. -## Global Options +These samples contain default values for flags. +## Global options ```yaml -# Same as '--quiet' -# Default is false -quiet: false +cache: + # Same as '--cache-dir' + dir: "/path/to/cache" # Same as '--debug' -# Default is false debug: false # Same as '--insecure' -# Default is false insecure: false +# Same as '--quiet' +quiet: false + # Same as '--timeout' -# Default is '5m' -timeout: 10m +timeout: 5m0s -# Same as '--cache-dir' -# Default is your system cache dir -cache: - dir: $HOME/.cache/trivy ``` - -## Report Options +## Cache options ```yaml -# Same as '--format' -# Default is 'table' -format: table +cache: + # Same as '--cache-backend' + backend: "fs" -# Same as '--report' (available with 'trivy k8s') -# Default is all -report: all + # Same as '--clear-cache' + clear: false -# Same as '--template' -# Default is empty -template: - -# Same as '--dependency-tree' -# Default is false -dependency-tree: false + redis: + # Same as '--redis-ca' + ca: "" -# Same as '--list-all-pkgs' -# Default is false -list-all-pkgs: false + # Same as '--redis-cert' + cert: "" -# Same as '--ignorefile' -# Default is '.trivyignore' -ignorefile: .trivyignore + # Same as '--redis-key' + key: "" -# Same as '--ignore-policy' -# Default is empty -ignore-policy: + # Same as '--redis-tls' + tls: false -# Same as '--exit-code' -# Default is 0 -exit-code: 0 + # Same as '--cache-ttl' + ttl: 0s -# Same as '--exit-on-eol' -# Default is 0 -exit-on-eol: 0 +``` +## Clean options -# Same as '--output' -# Default is empty (stdout) -output: +```yaml +clean: + # Same as '--all' + all: false -# Same as '--severity' -# Default is all severities -severity: - - UNKNOWN - - LOW - - MEDIUM - - HIGH - - CRITICAL - -# Same as '--pkg-types' -# Default is 'os,library' -pkg-types: - - os - - library - + # Same as '--checks-bundle' + checks-bundle: false -scan: - # Same as '--compliance' - # Default is empty - compliance: + # Same as '--java-db' + java-db: false - # Same as '--show-suppressed' - # Default is false - show-suppressed: false -``` + # Same as '--scan-cache' + scan-cache: false -## Scan Options -Available in client/server mode + # Same as '--vex-repo' + vex-repo: false -```yaml -scan: - # Same as '--file-patterns' - # Default is empty - file-patterns: - - + # Same as '--vuln-db' + vuln-db: false - # Same as '--skip-dirs' - # Default is empty - skip-dirs: - - usr/local/ - - etc/ +``` +## Client/Server options - # Same as '--skip-files' - # Default is empty - skip-files: - - package-dev.json +```yaml +server: + # Same as '--server' + addr: "" - # Same as '--offline-scan' - # Default is false - offline: false + # Same as '--custom-headers' + custom-headers: [] - # Same as '--scanners' - # Default depends on subcommand - scanners: - - vuln - - misconfig - - secret - - license - - - # Same as '--parallel' - # Default is 5 - parallel: 1 + # Same as '--listen' + listen: "localhost:4954" - # Same as '--sbom-sources' - # Default is empty - sbom-sources: - - oci - - rekor + # Same as '--token' + token: "" - # Same as '--rekor-url' - # Default is 'https://rekor.sigstore.dev' - rekor-url: https://rekor.sigstore.dev + # Same as '--token-header' + token-header: "Trivy-Token" - # Same as '--include-dev-deps' - # Default is false - include-dev-deps: false ``` - -## Cache Options +## DB options ```yaml -cache: - # Same as '--cache-backend' - # Default is 'fs' - backend: 'fs' - - # Same as '--cache-ttl' - # Default is 0 (no ttl) - ttl: 0 +db: + # Same as '--download-java-db-only' + download-java-only: false - # Redis options - redis: - # Same as '--redis-tls' - # Default is false - tls: - # Same as '--redis-ca' - # Default is empty - ca: + # Same as '--download-db-only' + download-only: false - # Same as '--redis-cert' - # Default is empty - cert: + # Same as '--java-db-repository' + java-repository: "ghcr.io/aquasecurity/trivy-java-db:1" - # Same as '--redis-key' - # Default is empty - key: -``` + # Same as '--skip-java-db-update' + java-skip-update: false -## DB Options + # Same as '--light' + light: false -```yaml -db: # Same as '--no-progress' - # Default is false no-progress: false - - # Same as '--skip-db-update' - # Default is false - skip-update: false # Same as '--db-repository' - # Default is 'ghcr.io/aquasecurity/trivy-db:2' - repository: ghcr.io/aquasecurity/trivy-db:2 + repository: "ghcr.io/aquasecurity/trivy-db:2" - # Same as '--skip-java-db-update' - # Default is false - java-skip-update: false + # Same as '--skip-db-update' + skip-update: false - # Same as '--java-db-repository' - # Default is 'ghcr.io/aquasecurity/trivy-java-db:1' - java-repository: ghcr.io/aquasecurity/trivy-java-db:1 -``` +# Same as '--reset' +reset: false -## Registry Options +``` +## Image options ```yaml -registry: - # Same as '--username' - # Default is empty - username: +image: + docker: + # Same as '--docker-host' + host: "" - # Same as '--password' - # Default is empty - password: - - # Same as '--registry-token' - # Default is empty - registry-token: -``` + # Same as '--image-config-scanners' + image-config-scanners: [] -## Image Options -Available with container image scanning + # Same as '--input' + input: "" -```yaml -image: - # Same as '--input' (available with 'trivy image') - # Default is empty - input: + # Same as '--platform' + platform: "" + + podman: + # Same as '--podman-host' + host: "" # Same as '--removed-pkgs' - # Default is false removed-pkgs: false - - # Same as '--platform' - # Default is empty - platform: # Same as '--image-src' - # Default is 'docker,containerd,podman,remote' source: - - podman - - docker - - # Same as '--image-config-scanners' - # Default is empty - image-config-scanners: - - misconfig - - secret - - docker: - # Same as '--docker-host' - # Default is empty - host: - - podman: - # Same as '--podman-host' - # Default is empty - host: -``` + - docker + - containerd + - podman + - remote -## Vulnerability Options -Available with vulnerability scanning +``` +## Kubernetes options ```yaml -vulnerability: - # Same as '--ignore-unfixed' - # Default is false - ignore-unfixed: false +kubernetes: + # Same as '--burst' + burst: 10 - # Same as '--ignore-unfixed' - # Default is empty - ignore-status: - - end_of_life + # Same as '--disable-node-collector' + disableNodeCollector: false - # Same as '--vex' - # Default is empty - vex: - - path/to/vex/file - - repo + exclude: + # Same as '--exclude-nodes' + nodes: [] - # Same as '--skip-vex-repo-update' - # Default is false - skip-vex-repo-update: true -``` + # Same as '--exclude-owned' + owned: false -## License Options -Available with license scanning + # Same as '--exclude-kinds' + excludeKinds: [] -```yaml -license: - # Same as '--license-full' - # Default is false - full: false + # Same as '--exclude-namespaces' + excludeNamespaces: [] - # Same as '--ignored-licenses' - # Default is empty - ignored: - - MPL-2.0 - - MIT + # Same as '--include-kinds' + includeKinds: [] + # Same as '--include-namespaces' + includeNamespaces: [] + + # Same as '--k8s-version' + k8s-version: "" + + # Same as '--kubeconfig' + kubeconfig: "" + + node-collector: + # Same as '--node-collector-imageref' + imageref: "ghcr.io/aquasecurity/node-collector:0.3.1" + + # Same as '--node-collector-namespace' + namespace: "trivy-temp" + + # Same as '--qps' + qps: 5 + + # Same as '--skip-images' + skipImages: false + + # Same as '--tolerations' + tolerations: [] + +``` +## License options + +```yaml +license: # Same as '--license-confidence-level' - # Default is 0.9 confidenceLevel: 0.9 - # Set list of forbidden licenses - # Default is https://github.com/aquasecurity/trivy/blob/164b025413c5fb9c6759491e9a306b46b869be93/pkg/licensing/category.go#L171 forbidden: - - AGPL-1.0 - - AGPL-3.0 + - AGPL-1.0 + - AGPL-3.0 + - CC-BY-NC-1.0 + - CC-BY-NC-2.0 + - CC-BY-NC-2.5 + - CC-BY-NC-3.0 + - CC-BY-NC-4.0 + - CC-BY-NC-ND-1.0 + - CC-BY-NC-ND-2.0 + - CC-BY-NC-ND-2.5 + - CC-BY-NC-ND-3.0 + - CC-BY-NC-ND-4.0 + - CC-BY-NC-SA-1.0 + - CC-BY-NC-SA-2.0 + - CC-BY-NC-SA-2.5 + - CC-BY-NC-SA-3.0 + - CC-BY-NC-SA-4.0 + - Commons-Clause + - Facebook-2-Clause + - Facebook-3-Clause + - Facebook-Examples + - WTFPL - # Set list of restricted licenses - # Default is https://github.com/aquasecurity/trivy/blob/164b025413c5fb9c6759491e9a306b46b869be93/pkg/licensing/category.go#L199 - restricted: - - AGPL-1.0 - - AGPL-3.0 + # Same as '--license-full' + full: false - # Set list of reciprocal licenses - # Default is https://github.com/aquasecurity/trivy/blob/164b025413c5fb9c6759491e9a306b46b869be93/pkg/licensing/category.go#L238 - reciprocal: - - AGPL-1.0 - - AGPL-3.0 + # Same as '--ignored-licenses' + ignored: [] - # Set list of notice licenses - # Default is https://github.com/aquasecurity/trivy/blob/164b025413c5fb9c6759491e9a306b46b869be93/pkg/licensing/category.go#L260 notice: - - AGPL-1.0 - - AGPL-3.0 + - AFL-1.1 + - AFL-1.2 + - AFL-2.0 + - AFL-2.1 + - AFL-3.0 + - Apache-1.0 + - Apache-1.1 + - Apache-2.0 + - Artistic-1.0-cl8 + - Artistic-1.0-Perl + - Artistic-1.0 + - Artistic-2.0 + - BSL-1.0 + - BSD-2-Clause-FreeBSD + - BSD-2-Clause-NetBSD + - BSD-2-Clause + - BSD-3-Clause-Attribution + - BSD-3-Clause-Clear + - BSD-3-Clause-LBNL + - BSD-3-Clause + - BSD-4-Clause + - BSD-4-Clause-UC + - BSD-Protection + - CC-BY-1.0 + - CC-BY-2.0 + - CC-BY-2.5 + - CC-BY-3.0 + - CC-BY-4.0 + - FTL + - ISC + - ImageMagick + - Libpng + - Lil-1.0 + - Linux-OpenIB + - LPL-1.02 + - LPL-1.0 + - MS-PL + - MIT + - NCSA + - OpenSSL + - PHP-3.01 + - PHP-3.0 + - PIL + - Python-2.0 + - Python-2.0-complete + - PostgreSQL + - SGI-B-1.0 + - SGI-B-1.1 + - SGI-B-2.0 + - Unicode-DFS-2015 + - Unicode-DFS-2016 + - Unicode-TOU + - UPL-1.0 + - W3C-19980720 + - W3C-20150513 + - W3C + - X11 + - Xnet + - Zend-2.0 + - zlib-acknowledgement + - Zlib + - ZPL-1.1 + - ZPL-2.0 + - ZPL-2.1 + + permissive: [] - # Set list of permissive licenses - # Default is empty - permissive: - - AGPL-1.0 - - AGPL-3.0 + reciprocal: + - APSL-1.0 + - APSL-1.1 + - APSL-1.2 + - APSL-2.0 + - CDDL-1.0 + - CDDL-1.1 + - CPL-1.0 + - EPL-1.0 + - EPL-2.0 + - FreeImage + - IPL-1.0 + - MPL-1.0 + - MPL-1.1 + - MPL-2.0 + - Ruby + + restricted: + - BCL + - CC-BY-ND-1.0 + - CC-BY-ND-2.0 + - CC-BY-ND-2.5 + - CC-BY-ND-3.0 + - CC-BY-ND-4.0 + - CC-BY-SA-1.0 + - CC-BY-SA-2.0 + - CC-BY-SA-2.5 + - CC-BY-SA-3.0 + - CC-BY-SA-4.0 + - GPL-1.0 + - GPL-2.0 + - GPL-2.0-with-autoconf-exception + - GPL-2.0-with-bison-exception + - GPL-2.0-with-classpath-exception + - GPL-2.0-with-font-exception + - GPL-2.0-with-GCC-exception + - GPL-3.0 + - GPL-3.0-with-autoconf-exception + - GPL-3.0-with-GCC-exception + - LGPL-2.0 + - LGPL-2.1 + - LGPL-3.0 + - NPL-1.0 + - NPL-1.1 + - OSL-1.0 + - OSL-1.1 + - OSL-2.0 + - OSL-2.1 + - OSL-3.0 + - QPL-1.0 + - Sleepycat - # Set list of unencumbered licenses - # Default is https://github.com/aquasecurity/trivy/blob/164b025413c5fb9c6759491e9a306b46b869be93/pkg/licensing/category.go#L334 unencumbered: - - AGPL-1.0 - - AGPL-3.0 -``` + - CC0-1.0 + - Unlicense + - 0BSD -## Secret Options -Available with secret scanning +``` +## Misconfiguration options ```yaml -secret: - # Same as '--secret-config' - # Default is 'trivy-secret.yaml' - config: config/trivy/secret.yaml -``` +misconfiguration: + # Same as '--checks-bundle-repository' + checks-bundle-repository: "ghcr.io/aquasecurity/trivy-checks:0" -## Rego Options + cloudformation: + # Same as '--cf-params' + params: [] -```yaml -rego: - # Same as '--trace' - # Default is false - trace: false + helm: + # Same as '--helm-api-versions' + api-versions: [] - # Same as '--skip-check-update' - # Default is false - skip-check-update: false + # Same as '--helm-kube-version' + kube-version: "" - # Same as '--config-policy' - # Default is empty - policy: - - policy/repository - - policy/custom - - policy/some-policy.rego + # Same as '--helm-set' + set: [] - # Same as '--config-data' - # Default is empty - data: - - data/ - - # Same as '--policy-namespaces' - # Default is empty - namespaces: - - opa.examples - - users -``` + # Same as '--helm-set-file' + set-file: [] -## Misconfiguration Options -Available with misconfiguration scanning + # Same as '--helm-set-string' + set-string: [] + + # Same as '--helm-values' + values: [] -```yaml -misconfiguration: # Same as '--include-non-failures' - # Default is false include-non-failures: false - - # Same as '--include-deprecated-checks' - # Default is false - include-deprecated-checks: false - # Same as '--check-bundle-repository' and '--policy-bundle-repository' - # Default is 'ghcr.io/aquasecurity/trivy-checks:0' - check-bundle-repository: ghcr.io/aquasecurity/trivy-checks:0 - - # Same as '--miconfig-scanners' - # Default is all scanners + # Same as '--reset-checks-bundle' + reset-checks-bundle: false + + # Same as '--misconfig-scanners' scanners: - - dockerfile - - terraform + - azure-arm + - cloudformation + - dockerfile + - helm + - kubernetes + - terraform + - terraformplan-json + - terraformplan-snapshot - # helm value override configurations - helm: - # set individual values - set: - - securityContext.runAsUser=10001 + terraform: + # Same as '--tf-exclude-downloaded-modules' + exclude-downloaded-modules: false - # set values with file - values: - - overrides.yaml + # Same as '--tf-vars' + vars: [] - # set specific values from specific files - set-file: - - image=dev-overrides.yaml +``` +## Module options - # set as string and preserve type - set-string: - - name=true +```yaml +module: + # Same as '--module-dir' + dir: "$HOME/.trivy/modules" - # Available API versions used for Capabilities.APIVersions. This flag is the same as the api-versions flag of the helm template command. - api-versions: - - policy/v1/PodDisruptionBudget - - apps/v1/Deployment + # Same as '--enable-modules' + enable-modules: [] - # Kubernetes version used for Capabilities.KubeVersion. This flag is the same as the kube-version flag of the helm template command. - kube-version: "v1.21.0" +``` +## Registry options - # terraform tfvars overrrides - terraform: - vars: - - dev-terraform.tfvars - - common-terraform.tfvars - - # Same as '--tf-exclude-downloaded-modules' - # Default is false - exclude-downloaded-modules: false +```yaml +registry: + # Same as '--password' + password: [] + + # Same as '--registry-token' + token: "" + + # Same as '--username' + username: [] - # Same as '--cf-params' - # Default is false - cloudformation: - params: - - params.json ``` +## Rego options -## Kubernetes Options -Available with Kubernetes scanning +```yaml +rego: + # Same as '--config-check' + check: [] + + # Same as '--config-data' + data: [] + + # Same as '--include-deprecated-checks' + include-deprecated-checks: false + + # Same as '--check-namespaces' + namespaces: [] + + # Same as '--skip-check-update' + skip-check-update: false + + # Same as '--trace' + trace: false + +``` +## Report options ```yaml -kubernetes: - # Same as '--context' - # Default is empty - context: +# Same as '--dependency-tree' +dependency-tree: false + +# Same as '--exit-code' +exit-code: 0 - # Same as '--namespace' - # Default is empty - namespace: +# Same as '--exit-on-eol' +exit-on-eol: 0 - # Same as '--kubeconfig' - # Default is empty - kubeconfig: ~/.kube/config2 +# Same as '--format' +format: "table" - # Same as '--components' - # Default is 'workload,infra' - components: - - workload - - infra +# Same as '--ignore-policy' +ignore-policy: "" - # Same as '--k8s-version' - # Default is empty - k8s-version: 1.21.0 +# Same as '--ignorefile' +ignorefile: ".trivyignore" - # Same as '--tolerations' - # Default is empty - tolerations: - - key1=value1:NoExecute - - key2=value2:NoSchedule +# Same as '--list-all-pkgs' +list-all-pkgs: false - # Same as '--all-namespaces' - # Default is false - all-namespaces: false +# Same as '--output' +output: "" - node-collector: - # Same as '--node-collector-namespace' - # Default is 'trivy-temp' - namespace: ~/.kube/config2 +# Same as '--output-plugin-arg' +output-plugin-arg: "" - # Same as '--node-collector-imageref' - # Default is 'ghcr.io/aquasecurity/node-collector:0.0.9' - imageref: ghcr.io/aquasecurity/node-collector:0.0.9 +# Same as '--report' +report: "all" - exclude: - # Same as '--exclude-owned' - # Default is false - owned: true +scan: + # Same as '--compliance' + compliance: "" - # Same as '--exclude-nodes' - # Default is empty - nodes: - - kubernetes.io/arch:arm64 - - team:dev + # Same as '--show-suppressed' + show-suppressed: false - # Same as '--qps' - # Default is 5.0 - qps: 5.0 +# Same as '--severity' +severity: + - UNKNOWN + - LOW + - MEDIUM + - HIGH + - CRITICAL - # Same as '--burst' - # Default is 10 - burst: 10 -``` +# Same as '--template' +template: "" -## Repository Options -Available with git repository scanning (`trivy repo`) +``` +## Repository options ```yaml repository: # Same as '--branch' - # Default is empty - branch: + branch: "" # Same as '--commit' - # Default is empty - commit: + commit: "" # Same as '--tag' - # Default is empty - tag: -``` + tag: "" -## Client/Server Options -Available in client/server mode +``` +## Scan options ```yaml -server: - # Same as '--server' (available in client mode) - # Default is empty - addr: http://localhost:4954 +scan: + # Same as '--detection-priority' + detection-priority: "precise" - # Same as '--token' - # Default is empty - token: "something-secret" + # Same as '--file-patterns' + file-patterns: [] - # Same as '--token-header' - # Default is 'Trivy-Token' - token-header: 'My-Token-Header' + # Same as '--offline-scan' + offline: false - # Same as '--custom-headers' - # Default is empty - custom-headers: - - scanner: trivy - - x-api-token: xxx - - # Same as '--listen' (available in server mode) - # Default is 'localhost:4954' - listen: 0.0.0.0:10000 -``` + # Same as '--parallel' + parallel: 5 + + # Same as '--rekor-url' + rekor-url: "https://rekor.sigstore.dev" -## Cloud Options + # Same as '--sbom-sources' + sbom-sources: [] -Available for cloud scanning (currently only `trivy aws`) + # Same as '--scanners' + scanners: + - vuln + - secret -```yaml -cloud: - # whether to force a cache update for every scan - update-cache: false - - # how old cached results can be before being invalidated - max-cache-age: 24h - - # aws-specific cloud settings - aws: - # the aws region to use - region: us-east-1 - - # the aws endpoint to use (not required for general use) - endpoint: https://my.custom.aws.endpoint - - # the aws account to use (this will be determined from your environment when not set) - account: 123456789012 - - # the aws specific services - service: - - s3 - - ec2 - - # the aws specific arn - arn: arn:aws:s3:::example-bucket - - # skip the aws specific services - skip-service: - - s3 - - ec2 -``` + # Same as '--skip-dirs' + skip-dirs: [] + + # Same as '--skip-files' + skip-files: [] -## Module Options -Available for modules + # Same as '--slow' + slow: false + +``` +## Secret options ```yaml -module: - # Same as '--module-dir' - # Default is '$HOME/.trivy/modules' - dir: $HOME/.trivy/modules +secret: + # Same as '--secret-config' + config: "trivy-secret.yaml" - # Same as '--enable-modules' - # Default is empty - enable-modules: - - trivy-module-spring4shell - - trivy-module-wordpress ``` +## Vulnerability options + +```yaml +vulnerability: + # Same as '--ignore-status' + ignore-status: [] -[example]: https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/examples/trivy-conf/trivy.yaml + # Same as '--ignore-unfixed' + ignore-unfixed: false + + # Same as '--skip-vex-repo-update' + skip-vex-repo-update: false + + # Same as '--vex' + vex: [] + +``` +[example]: https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/examples/trivy-conf/trivy.yaml \ No newline at end of file diff --git a/docs/docs/references/modes/client-server.md b/docs/docs/references/modes/client-server.md index 518fe45efc8a..7aa90abf0b22 100644 --- a/docs/docs/references/modes/client-server.md +++ b/docs/docs/references/modes/client-server.md @@ -2,9 +2,22 @@ Trivy has client/server mode. Trivy server has vulnerability database and Trivy client doesn't have to download vulnerability database. It is useful if you want to scan images or files at multiple locations and do not want to download the database at every location. -| Client/Server Mode | Image | Rootfs | Filesystem | Repository | Config | AWS | K8s | -|:---------------------:|:-----:|:------:|:----------:|:----------:|:------:|:---:|:---:| -| Supported | ✅ | ✅ | ✅ | ✅ | ✅ | X | X | +| Client/Server Mode | Image | Rootfs | Filesystem | Repository | Config | K8s | +|:------------------:|:-----:|:------:|:----------:|:----------:|:------:|:---:| +| Supported | ✅ | ✅ | ✅ | ✅ | - | - | + +Some scanners run on the client side, even in client/server mode. + +| Scanner | Run on Client or Server | +|:----------------:|:-----------------------:| +| Vulnerability | Server | +| Misconfiguration | Client[^1] | +| Secret | Client[^2] | +| License | Server | + +!!! note + Scanning of misconfigurations and licenses is performed on the client side (as in standalone mode). + Otherwise, the client would need to send files to the server that may contain sensitive information. ## Server At first, you need to launch Trivy server. It downloads vulnerability database automatically and continue to fetch the latest DB in the background. @@ -338,3 +351,5 @@ Returns the `200 OK` status if the request was successful. ![architecture](../../../imgs/client-server.png) +[^1]: The checks bundle is also downloaded on the client side. +[^2]: The scan result with masked secrets is sent to the server \ No newline at end of file diff --git a/go.mod b/go.mod index 70277514b22a..ac6f232878bc 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( github.com/aws/aws-sdk-go-v2 v1.30.3 github.com/aws/aws-sdk-go-v2/config v1.27.27 github.com/aws/aws-sdk-go-v2/credentials v1.17.27 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.172.0 - github.com/aws/aws-sdk-go-v2/service/ecr v1.30.3 - github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0 + github.com/aws/aws-sdk-go-v2/service/ecr v1.31.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3 github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect github.com/aws/smithy-go v1.20.3 github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c @@ -62,7 +62,7 @@ require ( github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/hashicorp/hc-install v0.7.0 + github.com/hashicorp/hc-install v0.8.0 github.com/hashicorp/hcl/v2 v2.21.0 github.com/hashicorp/terraform-exec v0.21.0 github.com/in-toto/in-toto-golang v0.9.0 @@ -88,7 +88,7 @@ require ( github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/buildkit v0.15.1 - github.com/open-policy-agent/opa v0.66.0 + github.com/open-policy-agent/opa v0.67.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/openvex/discovery v0.1.0 @@ -119,9 +119,9 @@ require ( go.etcd.io/bbolt v1.3.10 golang.org/x/crypto v0.25.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/mod v0.19.0 + golang.org/x/mod v0.20.0 golang.org/x/net v0.27.0 - golang.org/x/sync v0.7.0 + golang.org/x/sync v0.8.0 golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 golang.org/x/vuln v1.1.3 @@ -184,7 +184,7 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/briandowns/spinner v1.23.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/cgroups/v3 v3.0.2 // indirect @@ -261,7 +261,6 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect @@ -368,12 +367,11 @@ require ( go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect - go.opentelemetry.io/otel v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect @@ -384,9 +382,9 @@ require ( golang.org/x/tools v0.23.0 // indirect google.golang.org/api v0.172.0 // indirect google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect - google.golang.org/grpc v1.64.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index a5dde364799f..a24b98453b2c 100644 --- a/go.sum +++ b/go.sum @@ -381,10 +381,10 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 h1:CRzzXjmgx9p362yO39D6hbZULdMI23gaKqSxijJCXHM= github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7/go.mod h1:wnsHqpi3RgDwklS5SPHUgjcUUpontGPKJ+GJYOdV7pY= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.172.0 h1:lJjLKG92RyKIIYujVvulR3JpVjr3yxaU34nwXCq8K2o= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.172.0/go.mod h1:o6QDjdVKpP5EF0dp/VlvqckzuSDATr1rLdHt3A5m0YY= -github.com/aws/aws-sdk-go-v2/service/ecr v1.30.3 h1:+v2hv29pWaVDASIScHuUhDC93nqJGVlGf6cujrJMHZE= -github.com/aws/aws-sdk-go-v2/service/ecr v1.30.3/go.mod h1:RhaP7Wil0+uuuhiE4FzOOEFZwkmFAk1ZflXzK+O3ptU= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0 h1:ta62lid9JkIpKZtZZXSj6rP2AqY5x1qYGq53ffxqD9Q= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0/go.mod h1:o6QDjdVKpP5EF0dp/VlvqckzuSDATr1rLdHt3A5m0YY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.31.0 h1:vi/MwojjLGATEEUFn2GEdLiom7CFlB+qCIx4tDWqKfQ= +github.com/aws/aws-sdk-go-v2/service/ecr v1.31.0/go.mod h1:RhaP7Wil0+uuuhiE4FzOOEFZwkmFAk1ZflXzK+O3ptU= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 h1:PpbXaecV3sLAS6rjQiaKw4/jyq3Z8gNzmoJupHAoBp0= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2/go.mod h1:fUHpGXr4DrXkEDpGAjClPsviWf+Bszeb0daKE0blxv8= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8= @@ -393,8 +393,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrx github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2 h1:sZXIzO38GZOU+O0C+INqbH7C2yALwfMWpd64tONS/NE= -github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2/go.mod h1:Lcxzg5rojyVPU/0eFwLtcyTaek/6Mtic5B1gJo7e/zE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3 h1:hT8ZAZRIfqBqHbzKTII+CIiY8G2oC9OpLedkZ51DWl8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3/go.mod h1:Lcxzg5rojyVPU/0eFwLtcyTaek/6Mtic5B1gJo7e/zE= github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM= github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE= @@ -445,8 +445,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= @@ -714,8 +714,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -864,6 +864,7 @@ github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= @@ -901,8 +902,8 @@ github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= -github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= +github.com/hashicorp/hc-install v0.8.0 h1:LdpZeXkZYMQhoKPCecJHlKvUkQFixN/nvyR1CdfOLjI= +github.com/hashicorp/hc-install v0.8.0/go.mod h1:+MwJYjDfCruSD/udvBmRB22Nlkwwkwf5sAB6uTIhSaU= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14= @@ -1142,8 +1143,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/open-policy-agent/opa v0.66.0 h1:DbrvfJQja0FBRcPOB3Z/BOckocN+M4ApNWyNhSRJt0w= -github.com/open-policy-agent/opa v0.66.0/go.mod h1:EIgNnJcol7AvQR/IcWLwL13k64gHVbNAVG46b2G+/EY= +github.com/open-policy-agent/opa v0.67.0 h1:FOdsO9yNhfmrh+72oVK7ImWmzruG+VSpfbr5IBqEWVs= +github.com/open-policy-agent/opa v0.67.0/go.mod h1:aqKlHc8E2VAAylYE9x09zJYr/fYzGX+JKne89UGqFzk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -1426,25 +1427,25 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.step.sm/crypto v0.44.2 h1:t3p3uQ7raP2jp2ha9P6xkQF85TJZh+87xmjSLaib+jk= @@ -1512,8 +1513,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1619,8 +1620,8 @@ golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1980,10 +1981,10 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 h1:ImUcDPHjTrAqNhlOkSocDLfG9rrNHH7w7uoKWPaWZ8s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7/go.mod h1:/3XmxOjePkvmKrHuBy4zNFw7IzxJXtAgdpXi8Ll990U= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -2019,8 +2020,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/magefiles/docs.go b/magefiles/docs.go index 1a59007de229..7d09d37e1092 100644 --- a/magefiles/docs.go +++ b/magefiles/docs.go @@ -3,7 +3,11 @@ package main import ( + "cmp" + "fmt" "os" + "slices" + "strings" "github.com/spf13/cobra/doc" @@ -12,6 +16,15 @@ import ( "github.com/aquasecurity/trivy/pkg/log" ) +const ( + title = "Config file" + description = "Trivy can be customized by tweaking a `trivy.yaml` file.\n" + + "The config path can be overridden by the `--config` flag.\n\n" + + "An example is [here][example].\n\n" + + "These samples contain default values for flags." + footer = "[example]: https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/examples/trivy-conf/trivy.yaml" +) + // Generate CLI references func main() { // Set a dummy path for the documents @@ -26,4 +39,116 @@ func main() { if err := doc.GenMarkdownTree(cmd, "./docs/docs/references/configuration/cli"); err != nil { log.Fatal("Fatal error", log.Err(err)) } + if err := generateConfigDocs("./docs/docs/references/configuration/config-file.md"); err != nil { + log.Fatal("Fatal error in config file generation", log.Err(err)) + } +} + +// generateConfigDocs creates markdown file for Trivy config. +func generateConfigDocs(filename string) error { + // remoteFlags should contain Client and Server flags. + // NewClientFlags doesn't initialize `Listen` field + remoteFlags := flag.NewClientFlags() + remoteFlags.Listen = flag.ServerListenFlag.Clone() + + // These flags don't work from config file. + // Clear configName to skip them later. + globalFlags := flag.NewGlobalFlagGroup() + globalFlags.ConfigFile.ConfigName = "" + globalFlags.ShowVersion.ConfigName = "" + globalFlags.GenerateDefaultConfig.ConfigName = "" + + var allFlagGroups = []flag.FlagGroup{ + globalFlags, + flag.NewCacheFlagGroup(), + flag.NewCleanFlagGroup(), + remoteFlags, + flag.NewDBFlagGroup(), + flag.NewImageFlagGroup(), + flag.NewK8sFlagGroup(), + flag.NewLicenseFlagGroup(), + flag.NewMisconfFlagGroup(), + flag.NewModuleFlagGroup(), + flag.NewRegistryFlagGroup(), + flag.NewRegoFlagGroup(), + flag.NewReportFlagGroup(), + flag.NewRepoFlagGroup(), + flag.NewScanFlagGroup(), + flag.NewSecretFlagGroup(), + flag.NewVulnerabilityFlagGroup(), + } + + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + f.WriteString("# " + title + "\n\n") + f.WriteString(description + "\n") + + for _, group := range allFlagGroups { + f.WriteString("## " + group.Name() + " options\n") + writeFlags(group, f) + } + + f.WriteString(footer) + return nil +} + +func writeFlags(group flag.FlagGroup, w *os.File) { + flags := group.Flags() + // Sort flags to avoid duplicates of non-last parts of config file + slices.SortFunc(flags, func(a, b flag.Flagger) int { + return cmp.Compare(a.GetConfigName(), b.GetConfigName()) + }) + w.WriteString("\n```yaml\n") + + var lastParts []string + for _, flg := range flags { + if flg.GetConfigName() == "" { + continue + } + // We need to split the config name on `.` to make the indentations needed in yaml. + parts := strings.Split(flg.GetConfigName(), ".") + for i := range parts { + // Skip already added part + if len(lastParts) >= i+1 && parts[i] == lastParts[i] { + continue + } + ind := strings.Repeat(" ", i) + // We need to add a comment and example values only for the last part of the config name. + isLastPart := i == len(parts)-1 + if isLastPart { + // Some `Flags` don't support flag for CLI. (e.g.`LicenseForbidden`). + if flg.GetName() != "" { + fmt.Fprintf(w, "%s# Same as '--%s'\n", ind, flg.GetName()) + } + } + w.WriteString(ind + parts[i] + ":") + if isLastPart { + writeFlagValue(flg.GetDefaultValue(), ind, w) + } + w.WriteString("\n") + } + lastParts = parts + } + w.WriteString("```\n") +} + +func writeFlagValue(val any, ind string, w *os.File) { + switch v := val.(type) { + case []string: + if len(v) > 0 { + w.WriteString("\n") + for _, vv := range v { + fmt.Fprintf(w, "%s - %s\n", ind, vv) + } + } else { + w.WriteString(" []\n") + } + case string: + fmt.Fprintf(w, " %q\n", v) + default: + fmt.Fprintf(w, " %v\n", v) + } } diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 6528ec2c3d36..3cd1b9af74b5 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -40,7 +40,6 @@ const ( TargetFilesystem TargetKind = "fs" TargetRootfs TargetKind = "rootfs" TargetRepository TargetKind = "repo" - TargetImageArchive TargetKind = "archive" TargetSBOM TargetKind = "sbom" TargetVM TargetKind = "vm" ) @@ -345,6 +344,15 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err } }() + if opts.ServerAddr != "" && opts.Scanners.AnyEnabled(types.MisconfigScanner, types.SecretScanner) { + log.WarnContext(ctx, + fmt.Sprintf( + "Trivy runs in client/server mode, but misconfiguration and license scanning will be done on the client side, see %s", + doc.URL("/docs/references/modes/client-server", ""), + ), + ) + } + if opts.GenerateDefaultConfig { log.Info("Writing the default config to trivy-default.yaml...") return viper.SafeWriteConfigAs("trivy-default.yaml") @@ -359,32 +367,23 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err } defer r.Close(ctx) - var report types.Report - switch targetKind { - case TargetContainerImage, TargetImageArchive: - if report, err = r.ScanImage(ctx, opts); err != nil { - return xerrors.Errorf("image scan error: %w", err) - } - case TargetFilesystem: - if report, err = r.ScanFilesystem(ctx, opts); err != nil { - return xerrors.Errorf("filesystem scan error: %w", err) - } - case TargetRootfs: - if report, err = r.ScanRootfs(ctx, opts); err != nil { - return xerrors.Errorf("rootfs scan error: %w", err) - } - case TargetRepository: - if report, err = r.ScanRepository(ctx, opts); err != nil { - return xerrors.Errorf("repository scan error: %w", err) - } - case TargetSBOM: - if report, err = r.ScanSBOM(ctx, opts); err != nil { - return xerrors.Errorf("sbom scan error: %w", err) - } - case TargetVM: - if report, err = r.ScanVM(ctx, opts); err != nil { - return xerrors.Errorf("vm scan error: %w", err) - } + scans := map[TargetKind]func(context.Context, flag.Options) (types.Report, error){ + TargetContainerImage: r.ScanImage, + TargetFilesystem: r.ScanFilesystem, + TargetRootfs: r.ScanRootfs, + TargetRepository: r.ScanRepository, + TargetSBOM: r.ScanSBOM, + TargetVM: r.ScanVM, + } + + scanFunction, exists := scans[targetKind] + if !exists { + return xerrors.Errorf("unknown target kind: %s", targetKind) + } + + report, err := scanFunction(ctx, opts) + if err != nil { + return xerrors.Errorf("%s scan error: %w", targetKind, err) } report, err = r.Filter(ctx, opts, report) diff --git a/pkg/flag/global_flags.go b/pkg/flag/global_flags.go index ebd79bd5a06c..2d20611b8b72 100644 --- a/pkg/flag/global_flags.go +++ b/pkg/flag/global_flags.go @@ -106,7 +106,7 @@ func NewGlobalFlagGroup() *GlobalFlagGroup { } func (f *GlobalFlagGroup) Name() string { - return "global" + return "Global" } func (f *GlobalFlagGroup) Flags() []Flagger { diff --git a/pkg/flag/options.go b/pkg/flag/options.go index e5c46c81c64f..9bbcef79690b 100644 --- a/pkg/flag/options.go +++ b/pkg/flag/options.go @@ -196,6 +196,14 @@ func (f *Flag[T]) GetName() string { return f.Name } +func (f *Flag[T]) GetConfigName() string { + return f.ConfigName +} + +func (f *Flag[T]) GetDefaultValue() any { + return f.Default +} + func (f *Flag[T]) GetAliases() []Alias { return f.Aliases } @@ -302,6 +310,8 @@ type FlagGroup interface { type Flagger interface { GetName() string + GetConfigName() string + GetDefaultValue() any GetAliases() []Alias Parse() error diff --git a/pkg/iac/adapters/cloudformation/aws/s3/bucket.go b/pkg/iac/adapters/cloudformation/aws/s3/bucket.go index 5f5329fc6714..ec56894dbee4 100644 --- a/pkg/iac/adapters/cloudformation/aws/s3/bucket.go +++ b/pkg/iac/adapters/cloudformation/aws/s3/bucket.go @@ -7,7 +7,9 @@ import ( "strings" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/liamg/iamgo" + "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/s3" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" @@ -37,6 +39,7 @@ func getBuckets(cfFile parser.FileContext) []s3.Bucket { Website: getWebsite(r), BucketLocation: iacTypes.String("", r.Metadata()), Objects: nil, + BucketPolicies: getBucketPolicies(cfFile, r), } buckets = append(buckets, s3b) @@ -156,3 +159,35 @@ func getWebsite(r *parser.Resource) *s3.Website { } } } + +func getBucketPolicies(fctx parser.FileContext, r *parser.Resource) []iam.Policy { + + var policies []iam.Policy + for _, bucketPolicy := range fctx.GetResourcesByType("AWS::S3::BucketPolicy") { + bucket := bucketPolicy.GetStringProperty("Bucket") + if bucket.NotEqualTo(r.GetStringProperty("BucketName").Value()) && bucket.NotEqualTo(r.ID()) { + continue + } + + doc := bucketPolicy.GetProperty("PolicyDocument") + if doc.IsNil() { + continue + } + + parsed, err := iamgo.Parse(doc.GetJsonBytes()) + if err != nil { + continue + } + policies = append(policies, iam.Policy{ + Metadata: doc.Metadata(), + Name: iacTypes.StringDefault("", doc.Metadata()), + Document: iam.Document{ + Metadata: doc.Metadata(), + Parsed: *parsed, + }, + Builtin: iacTypes.Bool(false, doc.Metadata()), + }) + } + + return policies +} diff --git a/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go b/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go index ee8fffb39f75..707aae028f7f 100644 --- a/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go +++ b/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go @@ -3,7 +3,10 @@ package s3 import ( "testing" + "github.com/liamg/iamgo" + "github.com/aquasecurity/trivy/pkg/iac/adapters/cloudformation/testutil" + "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/s3" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -57,6 +60,19 @@ Resources: Status: Enabled WebsiteConfiguration: IndexDocument: index.html + SampleBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref Bucket + PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - 's3:GetObject' + Effect: Allow + Resource: !Join + - 'arn:aws:s3:::testbucket/*' + Principal: '*' `, expected: s3.S3{ Buckets: []s3.Bucket{ @@ -91,6 +107,23 @@ Resources: Enabled: types.BoolTest(true), }, Website: &s3.Website{}, + BucketPolicies: []iam.Policy{ + { + Document: iam.Document{ + Parsed: iamgo.NewPolicyBuilder(). + WithStatement( + iamgo.NewStatementBuilder(). + WithActions([]string{"s3:GetObject"}). + WithAllPrincipals(true). + WithEffect("Allow"). + WithResources([]string{"arn:aws:s3:::testbucket/*"}). + Build(), + ). + WithVersion("2012-10-17T00:00:00Z"). + Build(), + }, + }, + }, }, }, }, diff --git a/pkg/iac/adapters/terraform/aws/cloudfront/adapt.go b/pkg/iac/adapters/terraform/aws/cloudfront/adapt.go index a981241a83a4..721ecf991d55 100644 --- a/pkg/iac/adapters/terraform/aws/cloudfront/adapt.go +++ b/pkg/iac/adapters/terraform/aws/cloudfront/adapt.go @@ -33,7 +33,7 @@ func adaptDistribution(resource *terraform.Block) cloudfront.Distribution { }, DefaultCacheBehaviour: cloudfront.CacheBehaviour{ Metadata: resource.GetMetadata(), - ViewerProtocolPolicy: types.String("allow-all", resource.GetMetadata()), + ViewerProtocolPolicy: types.StringDefault("", resource.GetMetadata()), }, OrdererCacheBehaviours: nil, ViewerCertificate: cloudfront.ViewerCertificate{ @@ -53,13 +53,13 @@ func adaptDistribution(resource *terraform.Block) cloudfront.Distribution { if defaultCacheBlock := resource.GetBlock("default_cache_behavior"); defaultCacheBlock.IsNotNil() { distribution.DefaultCacheBehaviour.Metadata = defaultCacheBlock.GetMetadata() viewerProtocolPolicyAttr := defaultCacheBlock.GetAttribute("viewer_protocol_policy") - distribution.DefaultCacheBehaviour.ViewerProtocolPolicy = viewerProtocolPolicyAttr.AsStringValueOrDefault("allow-all", defaultCacheBlock) + distribution.DefaultCacheBehaviour.ViewerProtocolPolicy = viewerProtocolPolicyAttr.AsStringValueOrDefault("", defaultCacheBlock) } orderedCacheBlocks := resource.GetBlocks("ordered_cache_behavior") for _, orderedCacheBlock := range orderedCacheBlocks { viewerProtocolPolicyAttr := orderedCacheBlock.GetAttribute("viewer_protocol_policy") - viewerProtocolPolicyVal := viewerProtocolPolicyAttr.AsStringValueOrDefault("allow-all", orderedCacheBlock) + viewerProtocolPolicyVal := viewerProtocolPolicyAttr.AsStringValueOrDefault("", orderedCacheBlock) distribution.OrdererCacheBehaviours = append(distribution.OrdererCacheBehaviours, cloudfront.CacheBehaviour{ Metadata: orderedCacheBlock.GetMetadata(), ViewerProtocolPolicy: viewerProtocolPolicyVal, diff --git a/pkg/iac/adapters/terraform/aws/cloudfront/adapt_test.go b/pkg/iac/adapters/terraform/aws/cloudfront/adapt_test.go index d20520cd4651..fd1bf65e9cc5 100644 --- a/pkg/iac/adapters/terraform/aws/cloudfront/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/cloudfront/adapt_test.go @@ -83,7 +83,7 @@ func Test_adaptDistribution(t *testing.T) { }, DefaultCacheBehaviour: cloudfront.CacheBehaviour{ Metadata: iacTypes.NewTestMetadata(), - ViewerProtocolPolicy: iacTypes.String("allow-all", iacTypes.NewTestMetadata()), + ViewerProtocolPolicy: iacTypes.String("", iacTypes.NewTestMetadata()), }, ViewerCertificate: cloudfront.ViewerCertificate{ diff --git a/pkg/iac/adapters/terraform/aws/s3/adapt_test.go b/pkg/iac/adapters/terraform/aws/s3/adapt_test.go index 1cd1dec76270..ea12206f312b 100644 --- a/pkg/iac/adapters/terraform/aws/s3/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/s3/adapt_test.go @@ -149,6 +149,15 @@ func Test_Adapt(t *testing.T) { resource "aws_s3_bucket_acl" "example" { bucket = aws_s3_bucket.example.id acl = "private" + access_control_policy { + grant { + grantee { + type = "Group" + uri = "http://acs.amazonaws.com/groups/s3/LogDelivery" + } + permission = "READ_ACP" + } + } } resource "aws_s3_bucket_server_side_encryption_configuration" "example" { @@ -250,6 +259,51 @@ func Test_Adapt(t *testing.T) { TargetBucket: iacTypes.String("aws_s3_bucket.example", iacTypes.NewTestMetadata()), }, ACL: iacTypes.String("private", iacTypes.NewTestMetadata()), + Grants: []s3.Grant{ + { + Metadata: iacTypes.NewTestMetadata(), + Grantee: s3.Grantee{ + Type: iacTypes.StringTest("Group"), + URI: iacTypes.StringTest("http://acs.amazonaws.com/groups/s3/LogDelivery"), + }, + Permissions: iacTypes.StringValueList{ + iacTypes.StringTest("READ_ACP"), + }, + }, + }, + }, + }, + }, + }, + { + name: "bucket with grants", + terraform: ` +resource "aws_s3_bucket" "this" { + bucket = "test" + + grant { + type = "Group" + uri = "http://acs.amazonaws.com/groups/s3/LogDelivery" + permissions = ["FULL_CONTROL"] + } +} +`, + expected: s3.S3{ + Buckets: []s3.Bucket{ + { + Name: iacTypes.StringTest("test"), + ACL: iacTypes.StringTest("private"), + Grants: []s3.Grant{ + { + Grantee: s3.Grantee{ + Type: iacTypes.StringTest("Group"), + URI: iacTypes.StringTest("http://acs.amazonaws.com/groups/s3/LogDelivery"), + }, + Permissions: iacTypes.StringValueList{ + iacTypes.StringTest("FULL_CONTROL"), + }, + }, + }, }, }, }, diff --git a/pkg/iac/adapters/terraform/aws/s3/bucket.go b/pkg/iac/adapters/terraform/aws/s3/bucket.go index 5ecf7e9ba21b..206b0cbdabdf 100644 --- a/pkg/iac/adapters/terraform/aws/s3/bucket.go +++ b/pkg/iac/adapters/terraform/aws/s3/bucket.go @@ -26,6 +26,7 @@ func (a *adapter) adaptBuckets() []s3.Bucket { Versioning: getVersioning(block, a), Logging: getLogging(block, a), ACL: getBucketAcl(block, a), + Grants: getGrants(block, a), AccelerateConfigurationStatus: getAccelerateStatus(block, a), BucketLocation: block.GetAttribute("region").AsStringValueOrDefault("", block), LifecycleConfiguration: getLifecycle(block, a), @@ -193,6 +194,55 @@ func getBucketAcl(block *terraform.Block, a *adapter) iacTypes.StringValue { return iacTypes.StringDefault("private", block.GetMetadata()) } +func getGrants(block *terraform.Block, a *adapter) []s3.Grant { + if val, ok := applyForBucketRelatedResource(a, block, "aws_s3_bucket_acl", func(resource *terraform.Block) []s3.Grant { + var grants []s3.Grant + + if acessControlPolicy := resource.GetBlock("access_control_policy"); acessControlPolicy.IsNotNil() { + for _, grantBlock := range acessControlPolicy.GetBlocks("grant") { + grant := s3.Grant{ + Metadata: grantBlock.GetMetadata(), + Permissions: iacTypes.StringValueList{ + grantBlock.GetAttribute("permission").AsStringValueOrDefault("", grantBlock), + }, + } + + if granteeBlock := grantBlock.GetBlock("grantee"); granteeBlock.IsNotNil() { + grant.Grantee = s3.Grantee{ + Metadata: granteeBlock.GetMetadata(), + Type: granteeBlock.GetAttribute("type").AsStringValueOrDefault("", granteeBlock), + URI: granteeBlock.GetAttribute("uri").AsStringValueOrDefault("", granteeBlock), + } + } + + grants = append(grants, grant) + } + } + + return grants + + }); ok { + return val + } + + var grants []s3.Grant + for _, grantBlock := range block.GetBlocks("grant") { + grant := s3.Grant{ + Metadata: grantBlock.GetMetadata(), + Permissions: grantBlock.GetAttribute("permissions").AsStringValueSliceOrEmpty(), + Grantee: s3.Grantee{ + Metadata: grantBlock.GetMetadata(), + Type: grantBlock.GetAttribute("type").AsStringValueOrDefault("", grantBlock), + URI: grantBlock.GetAttribute("uri").AsStringValueOrDefault("", grantBlock), + }, + } + + grants = append(grants, grant) + } + + return grants +} + func isEncrypted(sseConfgihuration *terraform.Block) iacTypes.BoolValue { return terraform.MapNestedAttribute( sseConfgihuration, diff --git a/pkg/iac/detection/detect.go b/pkg/iac/detection/detect.go index 787b82cb0b6a..cec90a79cdca 100644 --- a/pkg/iac/detection/detect.go +++ b/pkg/iac/detection/detect.go @@ -45,8 +45,8 @@ func init() { return true } - var content any - return json.NewDecoder(r).Decode(&content) == nil + b, err := io.ReadAll(r) + return err == nil && json.Valid(b) } matchers[FileTypeYAML] = func(name string, r io.ReadSeeker) bool { @@ -221,15 +221,15 @@ func init() { } data := buf.Bytes() - marker := "\n---\n" - altMarker := "\r\n---\r\n" - if bytes.Contains(data, []byte(altMarker)) { + marker := []byte("\n---\n") + altMarker := []byte("\r\n---\r\n") + if bytes.Contains(data, altMarker) { marker = altMarker } - for _, partial := range strings.Split(string(data), marker) { + for _, partial := range bytes.Split(data, marker) { var result map[string]any - if err := yaml.Unmarshal([]byte(partial), &result); err != nil { + if err := yaml.Unmarshal(partial, &result); err != nil { continue } match := true diff --git a/pkg/iac/providers/aws/s3/bucket.go b/pkg/iac/providers/aws/s3/bucket.go index e884bbd4a7ff..ccabe6974c99 100755 --- a/pkg/iac/providers/aws/s3/bucket.go +++ b/pkg/iac/providers/aws/s3/bucket.go @@ -14,6 +14,7 @@ type Bucket struct { Versioning Versioning Logging Logging ACL iacTypes.StringValue + Grants []Grant BucketLocation iacTypes.StringValue AccelerateConfigurationStatus iacTypes.StringValue LifecycleConfiguration []Rules @@ -65,3 +66,15 @@ type Contents struct { type Website struct { Metadata iacTypes.Metadata } + +type Grant struct { + Metadata iacTypes.Metadata + Grantee Grantee + Permissions iacTypes.StringValueList +} + +type Grantee struct { + Metadata iacTypes.Metadata + URI iacTypes.StringValue + Type iacTypes.StringValue +} diff --git a/pkg/iac/rego/schemas/cloud.json b/pkg/iac/rego/schemas/cloud.json index ad81b6488ae8..a4bab9423d38 100644 --- a/pkg/iac/rego/schemas/cloud.json +++ b/pkg/iac/rego/schemas/cloud.json @@ -3647,6 +3647,13 @@ "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Encryption" }, + "grants": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Grant" + } + }, "lifecycleconfiguration": { "type": "array", "items": { @@ -3713,6 +3720,43 @@ } } }, + "github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Grant": { + "type": "object", + "properties": { + "__defsec_metadata": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.Metadata" + }, + "grantee": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Grantee" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" + } + } + } + }, + "github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Grantee": { + "type": "object", + "properties": { + "__defsec_metadata": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.Metadata" + }, + "type": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" + }, + "uri": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" + } + } + }, "github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.aws.s3.Logging": { "type": "object", "properties": { diff --git a/pkg/iac/scanners/terraform/parser/evaluator.go b/pkg/iac/scanners/terraform/parser/evaluator.go index bf3e4f4ffc13..0e26103e8c96 100644 --- a/pkg/iac/scanners/terraform/parser/evaluator.go +++ b/pkg/iac/scanners/terraform/parser/evaluator.go @@ -340,6 +340,18 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool ctx.Set(idx, block.TypeLabel(), "key") ctx.Set(val, block.TypeLabel(), "value") + if isDynamic { + if iterAttr := block.GetAttribute("iterator"); iterAttr.IsNotNil() { + refs := iterAttr.AllReferences() + if len(refs) == 1 { + ctx.Set(idx, refs[0].TypeLabel(), "key") + ctx.Set(val, refs[0].TypeLabel(), "value") + } else { + e.debug.Log("Ignoring iterator attribute in dynamic block, expected one reference but got %d", len(refs)) + } + } + } + forEachFiltered = append(forEachFiltered, clone) values := clone.Values() diff --git a/pkg/iac/scanners/terraform/parser/parser_test.go b/pkg/iac/scanners/terraform/parser/parser_test.go index 10232b007fd9..e7a8041aa7ff 100644 --- a/pkg/iac/scanners/terraform/parser/parser_test.go +++ b/pkg/iac/scanners/terraform/parser/parser_test.go @@ -1745,3 +1745,78 @@ func TestTFVarsFileDoesNotExist(t *testing.T) { _, _, err := parser.EvaluateAll(context.TODO()) assert.ErrorContains(t, err, "file does not exist") } + +func TestDynamicWithIterator(t *testing.T) { + fsys := fstest.MapFS{ + "main.tf": &fstest.MapFile{ + Data: []byte(`resource "aws_s3_bucket" "this" { + dynamic versioning { + for_each = [true] + iterator = ver + + content { + enabled = ver.value + } + } +}`), + }, + } + + parser := New( + fsys, "", + OptionStopOnHCLError(true), + OptionWithDownloads(false), + ) + require.NoError(t, parser.ParseFS(context.TODO(), ".")) + + modules, _, err := parser.EvaluateAll(context.TODO()) + require.NoError(t, err) + + assert.Len(t, modules, 1) + + buckets := modules.GetResourcesByType("aws_s3_bucket") + assert.Len(t, buckets, 1) + + attr, _ := buckets[0].GetNestedAttribute("versioning.enabled") + + assert.True(t, attr.Value().True()) +} + +func Test_AWSRegionNameDefined(t *testing.T) { + + fs := testutil.CreateFS(t, map[string]string{ + "code/test.tf": ` +data "aws_region" "current" {} + +data "aws_region" "other" { + name = "us-east-2" +} + +resource "something" "blah" { + r1 = data.aws_region.current.name + r2 = data.aws_region.other.name +} +`, + }) + + parser := New(fs, "", OptionStopOnHCLError(true)) + require.NoError(t, parser.ParseFS(context.TODO(), "code")) + modules, _, err := parser.EvaluateAll(context.TODO()) + require.NoError(t, err) + require.Len(t, modules, 1) + rootModule := modules[0] + + blocks := rootModule.GetResourcesByType("something") + require.Len(t, blocks, 1) + block := blocks[0] + + r1 := block.GetAttribute("r1") + require.NotNil(t, r1) + assert.True(t, r1.IsResolvable()) + assert.Equal(t, "current-region", r1.Value().AsString()) + + r2 := block.GetAttribute("r2") + require.NotNil(t, r2) + assert.True(t, r2.IsResolvable()) + assert.Equal(t, "us-east-2", r2.Value().AsString()) +} diff --git a/pkg/iac/scanners/terraform/parser/resolvers/cache.go b/pkg/iac/scanners/terraform/parser/resolvers/cache.go index e08c43ff3ba0..c8b2f660ed33 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/cache.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/cache.go @@ -51,7 +51,7 @@ func (r *cacheResolver) Resolve(_ context.Context, _ fs.FS, opt Options) (filesy return nil, "", "", false, nil } - src := removeSubdirFromSource(opt.Source) + src, subdir := splitPackageSubdirRaw(opt.Source) key := cacheKey(src, opt.Version) opt.Debug("Trying to resolve: %s", key) @@ -62,7 +62,7 @@ func (r *cacheResolver) Resolve(_ context.Context, _ fs.FS, opt Options) (filesy return nil, "", "", true, err } - return os.DirFS(filepath.Join(cacheDir, key)), opt.OriginalSource, ".", true, nil + return os.DirFS(filepath.Join(cacheDir, key)), opt.OriginalSource, subdir, true, nil } return nil, "", "", false, nil } diff --git a/pkg/iac/scanners/terraform/parser/resolvers/cache_integration_test.go b/pkg/iac/scanners/terraform/parser/resolvers/cache_integration_test.go index a7c6704b6708..43ad7f06b15b 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/cache_integration_test.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/cache_integration_test.go @@ -21,9 +21,10 @@ func TestResolveModuleFromCache(t *testing.T) { } tests := []struct { - name string - opts resolvers.Options - firstResolver moduleResolver + name string + opts resolvers.Options + firstResolver moduleResolver + expectedSubdir string }{ { name: "registry", @@ -32,7 +33,8 @@ func TestResolveModuleFromCache(t *testing.T) { Source: "terraform-aws-modules/s3-bucket/aws", Version: "4.1.2", }, - firstResolver: resolvers.Registry, + firstResolver: resolvers.Registry, + expectedSubdir: ".", }, { name: "registry with subdir", @@ -41,7 +43,8 @@ func TestResolveModuleFromCache(t *testing.T) { Source: "terraform-aws-modules/s3-bucket/aws//modules/object", Version: "4.1.2", }, - firstResolver: resolvers.Registry, + firstResolver: resolvers.Registry, + expectedSubdir: "modules/object", }, { name: "remote", @@ -49,7 +52,8 @@ func TestResolveModuleFromCache(t *testing.T) { Name: "bucket", Source: "git::https://github.com/terraform-aws-modules/terraform-aws-s3-bucket.git?ref=v4.1.2", }, - firstResolver: resolvers.Remote, + firstResolver: resolvers.Remote, + expectedSubdir: ".", }, { name: "remote with subdir", @@ -57,7 +61,8 @@ func TestResolveModuleFromCache(t *testing.T) { Name: "object", Source: "git::https://github.com/terraform-aws-modules/terraform-aws-s3-bucket.git//modules/object?ref=v4.1.2", }, - firstResolver: resolvers.Remote, + firstResolver: resolvers.Remote, + expectedSubdir: "modules/object", }, } diff --git a/pkg/iac/scanners/terraform/parser/resolvers/registry.go b/pkg/iac/scanners/terraform/parser/resolvers/registry.go index bcdd4734974a..8f2ab2ecdde1 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/registry.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/registry.go @@ -45,7 +45,7 @@ func (r *registryResolver) Resolve(ctx context.Context, target fs.FS, opt Option } inputVersion := opt.Version - source := removeSubdirFromSource(opt.Source) + source, _ := splitPackageSubdirRaw(opt.Source) parts := strings.Split(source, "/") if len(parts) < 3 || len(parts) > 4 { return diff --git a/pkg/iac/scanners/terraform/parser/resolvers/remote.go b/pkg/iac/scanners/terraform/parser/resolvers/remote.go index df94c775da78..790b3509fd33 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/remote.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/remote.go @@ -38,7 +38,7 @@ func (r *remoteResolver) Resolve(ctx context.Context, _ fs.FS, opt Options) (fil return nil, "", "", false, nil } - src := removeSubdirFromSource(opt.OriginalSource) + src, subdir := splitPackageSubdirRaw(opt.OriginalSource) key := cacheKey(src, opt.OriginalVersion) opt.Debug("Storing with cache key %s", key) @@ -54,7 +54,7 @@ func (r *remoteResolver) Resolve(ctx context.Context, _ fs.FS, opt Options) (fil r.incrementCount(opt) opt.Debug("Successfully downloaded %s from %s", opt.Name, opt.Source) opt.Debug("Module '%s' resolved via remote download.", opt.Name) - return os.DirFS(cacheDir), opt.Source, filepath.Join(".", opt.RelativePath), true, nil + return os.DirFS(cacheDir), opt.Source, subdir, true, nil } func (r *remoteResolver) download(ctx context.Context, opt Options, dst string) error { diff --git a/pkg/iac/scanners/terraform/parser/resolvers/source.go b/pkg/iac/scanners/terraform/parser/resolvers/source.go index d7637ffaf8a5..ee5662d6c7d0 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/source.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/source.go @@ -2,7 +2,7 @@ package resolvers import "strings" -func removeSubdirFromSource(src string) string { +func splitPackageSubdirRaw(src string) (string, string) { stop := len(src) if idx := strings.Index(src, "?"); idx > -1 { stop = idx @@ -18,7 +18,7 @@ func removeSubdirFromSource(src string) string { // First see if we even have an explicit subdir idx := strings.Index(src[offset:stop], "//") if idx == -1 { - return src + return src, "." } idx += offset @@ -29,8 +29,9 @@ func removeSubdirFromSource(src string) string { // URL. if idx = strings.Index(subdir, "?"); idx > -1 { query := subdir[idx:] + subdir = subdir[:idx] src += query } - return src + return src, subdir } diff --git a/pkg/iac/scanners/terraform/parser/resolvers/source_test.go b/pkg/iac/scanners/terraform/parser/resolvers/source_test.go index 3f57ab68b6d3..46df7db700dc 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/source_test.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/source_test.go @@ -6,39 +6,45 @@ import ( "github.com/stretchr/testify/assert" ) -func TestRemoveSubdirFromSource(t *testing.T) { +func TestSplitPackageSubdirRaw(t *testing.T) { tests := []struct { - name string - source string - expected string + name string + source string + expectedPkg string + expectedSubdir string }{ { - name: "address with scheme and query string", - source: "git::https://github.com/aquasecurity/terraform-modules.git//modules/ecs-service?ref=v0.1.0", - expected: "git::https://github.com/aquasecurity/terraform-modules.git?ref=v0.1.0", + name: "address with scheme and query string", + source: "git::https://github.com/aquasecurity/terraform-modules.git//modules/ecs-service?ref=v0.1.0", + expectedPkg: "git::https://github.com/aquasecurity/terraform-modules.git?ref=v0.1.0", + expectedSubdir: "modules/ecs-service", }, { - name: "address with scheme", - source: "git::https://github.com/aquasecurity/terraform-modules.git//modules/ecs-service", - expected: "git::https://github.com/aquasecurity/terraform-modules.git", + name: "address with scheme", + source: "git::https://github.com/aquasecurity/terraform-modules.git//modules/ecs-service", + expectedPkg: "git::https://github.com/aquasecurity/terraform-modules.git", + expectedSubdir: "modules/ecs-service", }, { - name: "registry address", - source: "hashicorp/consul/aws//modules/consul-cluster", - expected: "hashicorp/consul/aws", + name: "registry address", + source: "hashicorp/consul/aws//modules/consul-cluster", + expectedPkg: "hashicorp/consul/aws", + expectedSubdir: "modules/consul-cluster", }, { - name: "without subdir", - source: `hashicorp/consul/aws`, - expected: `hashicorp/consul/aws`, + name: "without subdir", + source: `hashicorp/consul/aws`, + expectedPkg: `hashicorp/consul/aws`, + expectedSubdir: ".", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got := removeSubdirFromSource(test.source) - assert.Equal(t, test.expected, got) + pkgAddr, subdir := splitPackageSubdirRaw(test.source) + assert.Equal(t, test.expectedPkg, pkgAddr) + assert.Equal(t, test.expectedSubdir, subdir) }) } } diff --git a/pkg/iac/scanners/universal/scanner.go b/pkg/iac/scanners/universal/scanner.go deleted file mode 100644 index 3687da85fc3d..000000000000 --- a/pkg/iac/scanners/universal/scanner.go +++ /dev/null @@ -1,63 +0,0 @@ -package universal - -import ( - "context" - "io/fs" - - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners" - "github.com/aquasecurity/trivy/pkg/iac/scanners/azure/arm" - "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation" - "github.com/aquasecurity/trivy/pkg/iac/scanners/dockerfile" - "github.com/aquasecurity/trivy/pkg/iac/scanners/helm" - "github.com/aquasecurity/trivy/pkg/iac/scanners/json" - "github.com/aquasecurity/trivy/pkg/iac/scanners/kubernetes" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" - "github.com/aquasecurity/trivy/pkg/iac/scanners/toml" - "github.com/aquasecurity/trivy/pkg/iac/scanners/yaml" -) - -type nestableFSScanners interface { - scanners.FSScanner - options.ConfigurableScanner -} - -var _ scanners.FSScanner = (*Scanner)(nil) - -type Scanner struct { - fsScanners []nestableFSScanners -} - -func New(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - fsScanners: []nestableFSScanners{ - terraform.New(opts...), - cloudformation.New(opts...), - dockerfile.NewScanner(opts...), - kubernetes.NewScanner(opts...), - json.NewScanner(opts...), - yaml.NewScanner(opts...), - toml.NewScanner(opts...), - helm.New(opts...), - arm.New(opts...), - }, - } - return s -} - -func (s *Scanner) Name() string { - return "Universal" -} - -func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Results, error) { - var results scan.Results - for _, inner := range s.fsScanners { - innerResults, err := inner.ScanFS(ctx, fsys, dir) - if err != nil { - return nil, err - } - results = append(results, innerResults...) - } - return results, nil -} diff --git a/pkg/iac/scanners/yaml/parser/parser.go b/pkg/iac/scanners/yaml/parser/parser.go index d8b50faf2437..febcfb100008 100644 --- a/pkg/iac/scanners/yaml/parser/parser.go +++ b/pkg/iac/scanners/yaml/parser/parser.go @@ -6,7 +6,6 @@ import ( "io" "io/fs" "path/filepath" - "strings" "gopkg.in/yaml.v3" @@ -77,15 +76,15 @@ func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) ([]any, e var results []any - marker := "\n---\n" - altMarker := "\r\n---\r\n" - if bytes.Contains(contents, []byte(altMarker)) { + marker := []byte("\n---\n") + altMarker := []byte("\r\n---\r\n") + if bytes.Contains(contents, altMarker) { marker = altMarker } - for _, partial := range strings.Split(string(contents), marker) { + for _, partial := range bytes.Split(contents, marker) { var target any - if err := yaml.Unmarshal([]byte(partial), &target); err != nil { + if err := yaml.Unmarshal(partial, &target); err != nil { return nil, err } results = append(results, target) diff --git a/pkg/iac/terraform/presets.go b/pkg/iac/terraform/presets.go index d10d795a86d7..b29a5fc9c181 100644 --- a/pkg/iac/terraform/presets.go +++ b/pkg/iac/terraform/presets.go @@ -19,13 +19,16 @@ func createPresetValues(b *Block) map[string]cty.Value { presets["arn"] = cty.StringVal(b.ID()) } - // workaround for weird iam feature switch b.TypeLabel() { + // workaround for weird iam feature case "aws_iam_policy_document": presets["json"] = cty.StringVal(b.ID()) // If the user leaves the name blank, Terraform will automatically generate a unique name case "aws_launch_template": presets["name"] = cty.StringVal(uuid.New().String()) + // allow referencing the current region name + case "aws_region": + presets["name"] = cty.StringVal("current-region") } return presets