diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9866e518d80f..f6f7d41ec07f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,8 +15,8 @@ pkg/cloud/ @simar7 @nikpivkin pkg/iac/ @simar7 @nikpivkin # Helm chart -helm/trivy/ @afdesk +helm/trivy/ @afdesk @simar7 # Kubernetes scanning -pkg/k8s/ @afdesk -docs/docs/target/kubernetes.md @afdesk +pkg/k8s/ @afdesk @simar7 +docs/docs/target/kubernetes.md @afdesk @simar7 diff --git a/.github/workflows/auto-update-labels.yaml b/.github/workflows/auto-update-labels.yaml index 0de6e41438b9..c8f8a2d3f45e 100644 --- a/.github/workflows/auto-update-labels.yaml +++ b/.github/workflows/auto-update-labels.yaml @@ -6,7 +6,7 @@ on: branches: - main env: - GO_VERSION: '1.22' + GO_VERSION: '1.23' jobs: deploy: name: Auto-update labels diff --git a/.github/workflows/release-pr-check.yaml b/.github/workflows/release-pr-check.yaml new file mode 100644 index 000000000000..a9662b1879ce --- /dev/null +++ b/.github/workflows/release-pr-check.yaml @@ -0,0 +1,19 @@ +name: Backport PR Check + +on: + pull_request: + branches: + - 'release/v*' + +jobs: + check-pr-author: + runs-on: ubuntu-latest + steps: + - name: Check PR author + id: check_author + run: | + if [ "${{ github.actor }}" != "aqua-bot" ]; then + echo "::error::This branch is intended for automated backporting by bot. Please refer to the documentation:" + echo "::error::https://trivy.dev/latest/community/maintainer/backporting/" + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/reusable-release.yaml b/.github/workflows/reusable-release.yaml index 54fa746f768f..133946b73aa4 100644 --- a/.github/workflows/reusable-release.yaml +++ b/.github/workflows/reusable-release.yaml @@ -14,7 +14,7 @@ on: env: GH_USER: "aqua-bot" - GO_VERSION: '1.22' + GO_VERSION: '1.23' jobs: release: diff --git a/.github/workflows/spdx-cron.yaml b/.github/workflows/spdx-cron.yaml new file mode 100644 index 000000000000..97abf087e85e --- /dev/null +++ b/.github/workflows/spdx-cron.yaml @@ -0,0 +1,33 @@ +name: SPDX licenses cron +on: + schedule: + - cron: '0 0 * * 0' # every Sunday at 00:00 + workflow_dispatch: + +jobs: + build: + name: Check if SPDX exceptions + runs-on: ubuntu-24.04 + steps: + - name: Check out code + uses: actions/checkout@v4.1.6 + + - name: Check if SPDX exceptions are up-to-date + run: | + mage spdx:updateLicenseExceptions + if [ -n "$(git status --porcelain)" ]; then + echo "Run 'mage spdx:updateLicenseExceptions' and push it" + exit 1 + fi + + - name: Microsoft Teams Notification + ## Until the PR with the fix for the AdaptivCard version is merged yet + ## https://github.com/Skitionek/notify-microsoft-teams/pull/96 + ## Use the aquasecurity fork + uses: aquasecurity/notify-microsoft-teams@master + if: failure() + with: + webhook_url: ${{ secrets.TRIVY_MSTEAMS_WEBHOOK }} + needs: ${{ toJson(needs) }} + job: ${{ toJson(job) }} + steps: ${{ toJson(steps) }} \ No newline at end of file diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9c6c2f10ffba..fb697957f37e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,7 +12,7 @@ on: workflow_dispatch: env: - GO_VERSION: '1.22' + GO_VERSION: '1.23' jobs: test: name: Test diff --git a/.gitignore b/.gitignore index 88070261a647..a2fc00ad08b6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ thumbs.db coverage.txt integration/testdata/fixtures/images integration/testdata/fixtures/vm-images +internal/gittest/testdata/test-repo # SBOMs generated during CI /bom.json diff --git a/.golangci.yaml b/.golangci.yaml index b6dbc299be20..1a033d51cb4a 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -81,6 +81,17 @@ linters-settings: - licence - optimise - simmilar + perfsprint: + # Optimizes even if it requires an int or uint type cast. + int-conversion: true + # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. + err-error: true + # Optimizes `fmt.Errorf`. + errorf: true + # Optimizes `fmt.Sprintf` with only one argument. + sprintf1: false + # Optimizes into strings concatenation. + strconcat: false revive: ignore-generated-header: true testifylint: @@ -100,6 +111,7 @@ linters: - govet - ineffassign - misspell + - perfsprint - revive - tenv - testifylint @@ -109,7 +121,7 @@ linters: - usestdlibvars run: - go: '1.22' + go: '1.23' timeout: 30m issues: @@ -140,5 +152,8 @@ issues: linters: - gocritic text: "importShadow:" + - linters: + - perfsprint + text: "fmt.Sprint" exclude-use-default: false max-same-issues: 0 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ac987fca1c0e..5e862745c686 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.58.0"} +{".":"0.59.0"} diff --git a/.vex/trivy.openvex.json b/.vex/trivy.openvex.json index 2dd1629ecc89..19f411950fb0 100644 --- a/.vex/trivy.openvex.json +++ b/.vex/trivy.openvex.json @@ -540,6 +540,65 @@ "status": "not_affected", "justification": "vulnerable_code_not_in_execute_path", "impact_statement": "Govulncheck determined that the vulnerable code isn't called" + }, + { + "vulnerability": { + "@id": "https://pkg.go.dev/vuln/GO-2024-3321", + "name": "GO-2024-3321", + "description": "Misuse of ServerConfig.PublicKeyCallback may cause authorization bypass in golang.org/x/crypto", + "aliases": [ + "CVE-2024-45337", + "GHSA-v778-237x-gjrc" + ] + }, + "products": [ + { + "@id": "pkg:golang/github.com/aquasecurity/trivy", + "identifiers": { + "purl": "pkg:golang/github.com/aquasecurity/trivy" + }, + "subcomponents": [ + { + "@id": "pkg:golang/golang.org/x/crypto", + "identifiers": { + "purl": "pkg:golang/golang.org/x/crypto" + } + } + ] + } + ], + "status": "not_affected", + "justification": "vulnerable_code_not_in_execute_path", + "impact_statement": "Govulncheck determined that the vulnerable code isn't called" + }, + { + "vulnerability": { + "@id": "https://pkg.go.dev/vuln/GO-2024-3333", + "name": "GO-2024-3333", + "description": "Non-linear parsing of case-insensitive content in golang.org/x/net/html", + "aliases": [ + "CVE-2024-45338" + ] + }, + "products": [ + { + "@id": "pkg:golang/github.com/aquasecurity/trivy", + "identifiers": { + "purl": "pkg:golang/github.com/aquasecurity/trivy" + }, + "subcomponents": [ + { + "@id": "pkg:golang/golang.org/x/net", + "identifiers": { + "purl": "pkg:golang/golang.org/x/net" + } + } + ] + } + ], + "status": "not_affected", + "justification": "vulnerable_code_not_in_execute_path", + "impact_statement": "Govulncheck determined that the vulnerable code isn't called" } ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 46f935238d4b..08948d1dfa41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,62 @@ # Changelog +## [0.59.0](https://github.com/aquasecurity/trivy/compare/v0.58.0...v0.59.0) (2025-01-30) + + +### Features + +* add `--distro` flag to manually specify OS distribution for vulnerability scanning ([#8070](https://github.com/aquasecurity/trivy/issues/8070)) ([da17dc7](https://github.com/aquasecurity/trivy/commit/da17dc72782cd68b5d2c4314a67936343462b75e)) +* add a examples field to check metadata ([#8068](https://github.com/aquasecurity/trivy/issues/8068)) ([6d84e0c](https://github.com/aquasecurity/trivy/commit/6d84e0cc0d48ae5c490cad868bb4e5e76392241c)) +* add support for registry mirrors ([#8244](https://github.com/aquasecurity/trivy/issues/8244)) ([4316bcb](https://github.com/aquasecurity/trivy/commit/4316bcbc5b9038eed21214a826981c49696bb27f)) +* **fs:** use git commit hash as cache key for clean repositories ([#8278](https://github.com/aquasecurity/trivy/issues/8278)) ([b5062f3](https://github.com/aquasecurity/trivy/commit/b5062f3ae20044d1452bf293f210a24cd1d419b3)) +* **image:** prevent scanning oversized container images ([#8178](https://github.com/aquasecurity/trivy/issues/8178)) ([509e030](https://github.com/aquasecurity/trivy/commit/509e03030c36d17f9427ab50a4e99fb1846ba65a)) +* **image:** return error early if total size of layers exceeds limit ([#8294](https://github.com/aquasecurity/trivy/issues/8294)) ([73bd20d](https://github.com/aquasecurity/trivy/commit/73bd20d6199a777d1ed7eb560e0184d8f1b4b550)) +* **k8s:** improve artifact selections for specific namespaces ([#8248](https://github.com/aquasecurity/trivy/issues/8248)) ([db9e57a](https://github.com/aquasecurity/trivy/commit/db9e57a34e460ac6934ee21dffaa2322db9fd56b)) +* **misconf:** generate placeholders for random provider resources ([#8051](https://github.com/aquasecurity/trivy/issues/8051)) ([ffe24e1](https://github.com/aquasecurity/trivy/commit/ffe24e18dc3dca816ec9ce5ccf66d5d7b5ea70d6)) +* **misconf:** support for ignoring by inline comments for Dockerfile ([#8115](https://github.com/aquasecurity/trivy/issues/8115)) ([c002327](https://github.com/aquasecurity/trivy/commit/c00232720a89df659c6cd0b56d99304d5ffea1a7)) +* **misconf:** support for ignoring by inline comments for Helm ([#8138](https://github.com/aquasecurity/trivy/issues/8138)) ([a0429f7](https://github.com/aquasecurity/trivy/commit/a0429f773b4f696fc613d91f1600cd0da38fb2c8)) +* **nodejs:** respect peer dependencies for dependency tree ([#7989](https://github.com/aquasecurity/trivy/issues/7989)) ([7389961](https://github.com/aquasecurity/trivy/commit/73899610e8eece670d2e5ddc1478fcc0a2a5760d)) +* **python:** add support for poetry dev dependencies ([#8152](https://github.com/aquasecurity/trivy/issues/8152)) ([774e04d](https://github.com/aquasecurity/trivy/commit/774e04d19dc2067725ac2e18ca871872f74082ab)) +* **python:** add support for uv ([#8080](https://github.com/aquasecurity/trivy/issues/8080)) ([c4a4a5f](https://github.com/aquasecurity/trivy/commit/c4a4a5fa971d73ae924afcf2259631f15e96e520)) +* **python:** add support for uv dev and optional dependencies ([#8134](https://github.com/aquasecurity/trivy/issues/8134)) ([49c54b4](https://github.com/aquasecurity/trivy/commit/49c54b49c6563590dd82007d52e425a7a4e07ac0)) + + +### Bug Fixes + +* CVE-2024-45337: Misuse of ServerConfig.PublicKeyCallback may cause authorization bypass ([#8088](https://github.com/aquasecurity/trivy/issues/8088)) ([d7ac286](https://github.com/aquasecurity/trivy/commit/d7ac286085077c969734225a789e6cc056d5c5f5)) +* CVE-2025-21613 and CVE-2025-21614 : go-git: argument injection via the URL field ([#8207](https://github.com/aquasecurity/trivy/issues/8207)) ([670fbf2](https://github.com/aquasecurity/trivy/commit/670fbf2d81ea20ea691a86e4ed25a7454baf08e5)) +* de-duplicate same `dpkg` packages with different filePaths from different layers ([#8298](https://github.com/aquasecurity/trivy/issues/8298)) ([846498d](https://github.com/aquasecurity/trivy/commit/846498dd23a80531881f803147077eee19004a50)) +* enable err-error and errorf rules from perfsprint linter ([#7859](https://github.com/aquasecurity/trivy/issues/7859)) ([156a2aa](https://github.com/aquasecurity/trivy/commit/156a2aa4c49386828c0446f8978473c8da7a8754)) +* **flag:** skip hidden flags for `--generate-default-config` command ([#8046](https://github.com/aquasecurity/trivy/issues/8046)) ([5e68bdc](https://github.com/aquasecurity/trivy/commit/5e68bdc9d08f96d22451d7b5dd93e79ca576eeb7)) +* **fs:** fix cache key generation to use UUID ([#8275](https://github.com/aquasecurity/trivy/issues/8275)) ([eafd810](https://github.com/aquasecurity/trivy/commit/eafd810d7cb366215efbd0ab3b72c4651d31c6a6)) +* handle `BLOW_UNKNOWN` error to download DBs ([#8060](https://github.com/aquasecurity/trivy/issues/8060)) ([51f2123](https://github.com/aquasecurity/trivy/commit/51f2123c5ccc4f7a37d1068830b6670b4ccf9ac8)) +* improve conversion of image config to Dockerfile ([#8308](https://github.com/aquasecurity/trivy/issues/8308)) ([2e8e38a](https://github.com/aquasecurity/trivy/commit/2e8e38a8c094f3392893693ab15a605ab0d378f9)) +* **java:** correctly overwrite version from depManagement if dependency uses `project.*` props ([#8050](https://github.com/aquasecurity/trivy/issues/8050)) ([9d9f80d](https://github.com/aquasecurity/trivy/commit/9d9f80d9791f38a0b4c727152166ae4d237a83a9)) +* **license:** always trim leading and trailing spaces for licenses ([#8095](https://github.com/aquasecurity/trivy/issues/8095)) ([f5e4291](https://github.com/aquasecurity/trivy/commit/f5e429179df1637de96962ab9c19e4336056bb5d)) +* **misconf:** allow null values only for tf variables ([#8112](https://github.com/aquasecurity/trivy/issues/8112)) ([23dc3a6](https://github.com/aquasecurity/trivy/commit/23dc3a67535b7458728b2939514a96bd3de3aa81)) +* **misconf:** correctly handle all YAML tags in K8S templates ([#8259](https://github.com/aquasecurity/trivy/issues/8259)) ([f12054e](https://github.com/aquasecurity/trivy/commit/f12054e669f9df93c6322ba2755036dbccacaa83)) +* **misconf:** disable git terminal prompt on tf module load ([#8026](https://github.com/aquasecurity/trivy/issues/8026)) ([bbc5a85](https://github.com/aquasecurity/trivy/commit/bbc5a85444ec86b7bb26d6db27803d199431a8e6)) +* **misconf:** handle heredocs in dockerfile instructions ([#8284](https://github.com/aquasecurity/trivy/issues/8284)) ([0a3887c](https://github.com/aquasecurity/trivy/commit/0a3887ca0350d7dabf5db7e08aaf8152201fdf0d)) +* **misconf:** use log instead of fmt for logging ([#8033](https://github.com/aquasecurity/trivy/issues/8033)) ([07b2d7f](https://github.com/aquasecurity/trivy/commit/07b2d7fbd7f8ef5473c2438c560fffc8bdadf913)) +* **oracle:** add architectures support for advisories ([#4809](https://github.com/aquasecurity/trivy/issues/4809)) ([90f1d8d](https://github.com/aquasecurity/trivy/commit/90f1d8d78aa20b47fafab2c8ecb07247f075ef45)) +* **python:** skip dev group's deps for poetry ([#8106](https://github.com/aquasecurity/trivy/issues/8106)) ([a034d26](https://github.com/aquasecurity/trivy/commit/a034d26443704601c1fe330a5cc1f019f6974524)) +* **redhat:** check `usr/share/buildinfo/` dir to detect content sets ([#8222](https://github.com/aquasecurity/trivy/issues/8222)) ([f352f6b](https://github.com/aquasecurity/trivy/commit/f352f6b66355fe3636c9e4e9f3edd089c551a81c)) +* **redhat:** correct rewriting of recommendations for the same vulnerability ([#8063](https://github.com/aquasecurity/trivy/issues/8063)) ([4202c4b](https://github.com/aquasecurity/trivy/commit/4202c4ba0d8fcff4b89499fe03050ef4efd37330)) +* respect GITHUB_TOKEN to download artifacts from GHCR ([#7580](https://github.com/aquasecurity/trivy/issues/7580)) ([21b68e1](https://github.com/aquasecurity/trivy/commit/21b68e18188f91935ac1055a78ee97a7f35a110d)) +* **sbom:** attach nested packages to Application ([#8144](https://github.com/aquasecurity/trivy/issues/8144)) ([735335f](https://github.com/aquasecurity/trivy/commit/735335f08f84936f3928cbbc3eb71af3a3a4918d)) +* **sbom:** fix wrong overwriting of applications obtained from different sbom files but having same app type ([#8052](https://github.com/aquasecurity/trivy/issues/8052)) ([fd07074](https://github.com/aquasecurity/trivy/commit/fd07074e8033530eee2732193b00e59f27c73096)) +* **sbom:** scan results of SBOMs generated from container images are missing layers ([#7635](https://github.com/aquasecurity/trivy/issues/7635)) ([f9fceb5](https://github.com/aquasecurity/trivy/commit/f9fceb58bf64657dee92302df1ed97e597e474c9)) +* **sbom:** use root package for `unknown` dependencies (if exists) ([#8104](https://github.com/aquasecurity/trivy/issues/8104)) ([7558df7](https://github.com/aquasecurity/trivy/commit/7558df7c227c769235e5441fbdd3f9f7efb1ff84)) +* **spdx:** use the `hasExtractedLicensingInfos` field for licenses that are not listed in the SPDX ([#8077](https://github.com/aquasecurity/trivy/issues/8077)) ([aec8885](https://github.com/aquasecurity/trivy/commit/aec8885bc7f7e3c5a2a68214dca9aff28accd122)) +* **suse:** SUSE - update OSType constants and references for compatility ([#8236](https://github.com/aquasecurity/trivy/issues/8236)) ([ae28398](https://github.com/aquasecurity/trivy/commit/ae283985c926ca828b25b69ad0338008be31e5fe)) +* Updated twitter icon ([#7772](https://github.com/aquasecurity/trivy/issues/7772)) ([2c41ac8](https://github.com/aquasecurity/trivy/commit/2c41ac83a95e9347605d36f483171a60ffce0fa2)) +* wasm module test ([#8099](https://github.com/aquasecurity/trivy/issues/8099)) ([2200f38](https://github.com/aquasecurity/trivy/commit/2200f3846d675c64ab9302af43224d663a67c944)) + + +### Performance Improvements + +* avoid heap allocation in applier findPackage ([#7883](https://github.com/aquasecurity/trivy/issues/7883)) ([9bd6ed7](https://github.com/aquasecurity/trivy/commit/9bd6ed73e5d49d52856c76124e84c268475c5456)) + ## [0.58.0](https://github.com/aquasecurity/trivy/compare/v0.57.0...v0.58.0) (2024-12-02) diff --git a/Dockerfile b/Dockerfile index 1113c80aa9d5..febdad178f56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.20.3 +FROM alpine:3.21.0 RUN apk --no-cache add ca-certificates git COPY trivy /usr/local/bin/trivy COPY contrib/*.tpl contrib/ diff --git a/Dockerfile.canary b/Dockerfile.canary index bd65bc46195d..913553c514c9 100644 --- a/Dockerfile.canary +++ b/Dockerfile.canary @@ -1,4 +1,4 @@ -FROM alpine:3.20.0 +FROM alpine:3.21.0 RUN apk --no-cache add ca-certificates git # binaries were created with GoReleaser diff --git a/Dockerfile.protoc b/Dockerfile.protoc index f87c333562b9..e356007d33f1 100644 --- a/Dockerfile.protoc +++ b/Dockerfile.protoc @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.22 +FROM --platform=linux/amd64 golang:1.23 # Set environment variable for protoc ENV PROTOC_ZIP=protoc-3.19.4-linux-x86_64.zip diff --git a/README.md b/README.md index 15a53e5310db..e17400713e9b 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ trivy k8s --report summary cluster ## Want more? Check out Aqua If you liked Trivy, you will love Aqua which builds on top of Trivy to provide even more enhanced capabilities for a complete security management offering. -You can find a high level comparison table specific to Trivy users [here](https://github.com/aquasecurity/resources/blob/main/trivy-aqua.md). +You can find a high level comparison table specific to Trivy users [here](https://trivy.dev/commercial/comparison). In addition check out the website for more information about our products and services. If you'd like to contact Aqua or request a demo, please use this form: diff --git a/aqua.yaml b/aqua.yaml index af251aeec167..c317555564ee 100644 --- a/aqua.yaml +++ b/aqua.yaml @@ -5,6 +5,6 @@ registries: - type: standard ref: v3.157.0 # renovate: depName=aquaproj/aqua-registry packages: -- name: tinygo-org/tinygo@v0.31.1 +- name: tinygo-org/tinygo@v0.33.0 - name: WebAssembly/binaryen@version_112 - name: magefile/mage@v1.14.0 diff --git a/cmd/trivy/main.go b/cmd/trivy/main.go index 6cbda13b9cf3..84d8879fbdbc 100644 --- a/cmd/trivy/main.go +++ b/cmd/trivy/main.go @@ -21,6 +21,12 @@ func main() { if errors.As(err, &exitError) { os.Exit(exitError.Code) } + + var userErr *types.UserError + if errors.As(err, &userErr) { + log.Fatal("Error", log.Err(userErr)) + } + log.Fatal("Fatal error", log.Err(err)) } } diff --git a/contrib/junit.tpl b/contrib/junit.tpl index 27b654b7b049..b351f62bb43e 100644 --- a/contrib/junit.tpl +++ b/contrib/junit.tpl @@ -44,5 +44,15 @@ {{- end }} +{{- if .Secrets }} + {{- $secrets := len .Secrets }} + {{ range .Secrets }} + + {{ escapeXML .Match }} + + {{- end }} + +{{- end }} + {{- end }} diff --git a/docs/commercial/compare.md b/docs/commercial/compare.md new file mode 100644 index 000000000000..eb16cc26812a --- /dev/null +++ b/docs/commercial/compare.md @@ -0,0 +1,86 @@ +# Aqua Security is the home of Trivy + +Trivy is proudly maintained by [Aqua Security](https://aquasec.com). +If you liked Trivy, you will love Aqua which builds on top of Trivy to provide even more enhanced capabilities for a complete security management offering. +In this page you can find a high level comparison between Trivy Open Source and Aqua's commercial product. +If you'd like to learn more or request a demo, [click here to contact us](./contact.md). + +## User experience + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Interface | CLI tool | CLI tool
Enterprise-grade web application
SaaS or on-prem | +| Search & Discover | - | Easily search for security issues across all workloads and infrastructure in your organization
Visually discover risks across your organization | +| User management | - | Multi account
Granular permissions (RBAC)
Single Sign On (SSO) | +| Support | Some skills required for setup and integration
Best effort community support | Personal onboarding by Aqua Customer Success
SLA backed professional support | +| Scalability & Availability | Single scan at a time | Centralized scanning service supports concurrent scans efficiently
Highly available production grade architecture | +| Rate limiting | Assets hosted on public free infrastructure and could be rate limited | Assets hosted on Aqua infrastructure and does not have limitations | + +## Vulnerability scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Vulnerabilities sources | Based on open source vulnerability feeds | Based on open source and commercial vulnerability feeds | +| New Vulnerabilities SLA | No SLA | Commercial level SLA | +| Package managers | Find packages in lock files | Find packages in lock files or reconstructed lock files | +| Vulnerability management | Manually ignore specific vulnerabilities by ID or property | Advanced vulnerability management solution
Vulnerability tracking and suppression
Incident lifecycle management | +| Vulnerability prioritization | Manually triage by severity | Multiple prioritization tools:
Accessibility of the affected resources
Exploitability of the vulnerability
Open Source packages health and trustworthiness score
Affected image layers | +| Reachability analysis | - | Analyze source code to eliminate vulnerabilities of unused dependencies | +| Contextual vulnerabilities | - | Reduce irrelevant vulnerabilities based on environmental factors (e.g. Spring4Shell not relevant due to JDK version) | +| Compiled binaries | Find embedded dependencies in Go and Rust binaries
Find SBOM by hash in public Sigstore | In addition, identify popular applications | + +## Container scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Windows containers | - | Support scanning windows containers | +| Scan container registries | - | Connect to any container registries and automatically scan it | +| Private registries | Standard registry authenticationCloud authentication with ECR, GCR, ACR | Supports registry specific authentication schemes | +| Layer cache | Local cache directory | Scalable Cloud cache | + +## Advanced scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Malware scanning | - | Scan container images for malware | +| Sandbox scanning | - | Use DTA (Dynamic threat analysis) to run and test container images' behavior to detect sophisticated threats | +| SAST (code scanning) | - | Analyze source code for security issues and vulnerabilities | + +## Policy and enforcement + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Kubernetes admission | - | Validating Kubernetes Admission based on automatic or user defined policy | +| CI/CD policies | Can fail the entire build on any finding | Granular policies to fail builds based on custom criteria | +| Container engine | - | Block incompliant images from running at container engine level | +| Block vulnerable packages | - | vShield – monitor and block usage of vulnerable packages | + +## Secrets scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Detected patterns | Basic patterns | Advanced patterns | +| Leaked secrets validation | - | Automatically checks if leaked secrets are valid and usable | + +## IaC/CSPM scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +| Infrastructure as Code (IaC) | Many popular languages as detailed [here](https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/policy/builtin/) | In addition, Build Pipeline configuration scanning | +| Checks customization | Create custom checks with Rego | Create custom checks in no-code interface
Customize existing checks with organizational preferences | +| Cloud scanning | AWS (subset of services) | AWS, Azure, GCP, Alibaba Cloud, Oracle Cloud | +| Compliance frameworks | CIS, NSA, vendor guides | More than 25 compliance programs | +| Custom compliance | Create in YAML | Create in a web UI | +| Remediation advice | Basic | AI powered specialized remediation guides | + +## Kubernetes scanning + +| Feature | Trivy OSS | Aqua | +| --- | --- | --- | +Scan initiation | CLI / Kubernetes Operator | Kubernetes Operator / Management web application | +Results consumption | kubectl / CRD / Prometheus exporter | In addition, Advanced UI dashboards, Automatic notifications and incident management flows | +Cluster discovery | Kubeconfig | Automatic discovery thorough cloud onboarding | +Workload image scanning | Scanning in cluster, requires capacity planning | Scanning offloaded to Aqua service, little impact on scanned clusters | +| Cluster scanning | CIS, NSA, PSS | More than 25 compliance programs | +| Scope | Single cluster | Multi cluster, Cloud relationship | +| Scalability | Reports limited by in-cluster etcd storage (size and number of reports) | Cloud-based storage (unlimited scalability) | diff --git a/docs/commercial/contact.md b/docs/commercial/contact.md new file mode 100644 index 000000000000..7dbc29ef5407 --- /dev/null +++ b/docs/commercial/contact.md @@ -0,0 +1,17 @@ + + + diff --git a/docs/community/principles.md b/docs/community/principles.md index 8f369429ced5..aecb34b00ba9 100644 --- a/docs/community/principles.md +++ b/docs/community/principles.md @@ -48,6 +48,6 @@ As mentioned in [the Core Principles](#detecting-unintended-states), detection o ### User Interface Trivy primarily operates via CLI for displaying results, with a richer UI available in [the commercial version][aqua]. -[trivy-aqua]: https://github.com/aquasecurity/resources/blob/main/trivy-aqua.md +[trivy-aqua]: ../commercial/compare.md [tracee]: https://github.com/aquasecurity/tracee [aqua]: https://www.aquasec.com/ \ No newline at end of file diff --git a/docs/docs/configuration/cache.md b/docs/docs/configuration/cache.md index 2ad5086d0e87..87618ddc02ca 100644 --- a/docs/docs/configuration/cache.md +++ b/docs/docs/configuration/cache.md @@ -51,9 +51,7 @@ It supports three types of backends for this cache: - TTL can be configured via `--cache-ttl` ### Local File System -The local file system backend is the default choice for container and VM image scans. -When scanning container images, it stores analysis results on a per-layer basis, using layer IDs as keys. -This approach enables faster scans of the same container image or different images that share layers. +The local file system backend is the default choice for container image, VM image and repository scans. !!! note Internally, this backend uses [BoltDB][boltdb], which has an important limitation: only one process can access the cache at a time. @@ -63,7 +61,7 @@ This approach enables faster scans of the same container image or different imag ### Memory The memory backend stores analysis results in memory, which means the cache is discarded when the process ends. This makes it useful in scenarios where caching is not required or desired. -It serves as the default for repository, filesystem and SBOM scans and can also be employed for container image scans when caching is unnecessary. +It serves as the default for filesystem and SBOM scans and can also be employed for container image scans when caching is unnecessary. To use the memory backend for a container image scan, you can use the following command: diff --git a/docs/docs/configuration/others.md b/docs/docs/configuration/others.md index 371350f07a96..a89171af5984 100644 --- a/docs/docs/configuration/others.md +++ b/docs/docs/configuration/others.md @@ -117,3 +117,46 @@ The following example will fail when a critical vulnerability is found or the OS ``` $ trivy image --exit-code 1 --exit-on-eol 1 --severity CRITICAL alpine:3.16.3 ``` + +## Mirror Registries + +!!! warning "EXPERIMENTAL" + This feature might change without preserving backwards compatibility. + +Trivy supports mirrors for [remote container images](../target/container_image.md#container-registry) and [databases](./db.md). + +To configure them, add a list of mirrors along with the host to the [trivy config file](../references/configuration/config-file.md#registry-options). + +!!! note + Use the `index.docker.io` host for images from `Docker Hub`, even if you don't use that prefix. + +Example for `index.docker.io`: +```yaml +registry: + mirrors: + index.docker.io: + - mirror.gcr.io +``` + +### Registry check procedure +Trivy uses the following registry order to get the image: + +- mirrors in the same order as they are specified in the configuration file +- source registry + +In cases where we can't get the image from the mirror registry (e.g. when authentication fails, image doesn't exist, etc.) - Trivy will check other mirrors (or the source registry if all mirrors have already been checked). + +Example: +```yaml +registry: + mirrors: + index.docker.io: + - mirror.with.bad.auth // We don't have credentials for this registry + - mirror.without.image // Registry doesn't have this image +``` + +When we want to get the image `alpine` with the settings above. The logic will be as follows: + +1. Try to get the image from `mirror.with.bad.auth/library/alpine`, but we get an error because there are no credentials for this registry. +2. Try to get the image from `mirror.without.image/library/alpine`, but we get an error because this registry doesn't have this image (but most likely it will be an error about authorization). +3. Get the image from `index.docker.io` (the original registry). diff --git a/docs/docs/configuration/reporting.md b/docs/docs/configuration/reporting.md index 636766692d11..c6ddc1727a71 100644 --- a/docs/docs/configuration/reporting.md +++ b/docs/docs/configuration/reporting.md @@ -58,6 +58,7 @@ The following languages are currently supported: | | [yarn.lock][yarn-lock] | | .NET | [packages.lock.json][dotnet-packages-lock] | | Python | [poetry.lock][poetry-lock] | +| | [uv.lock][uv-lock] | | Ruby | [Gemfile.lock][gemfile-lock] | | Rust | [cargo-auditable binaries][cargo-binaries] | | Go | [go.mod][go-mod] | @@ -120,15 +121,21 @@ Then, you can try to update **axios@0.21.4** and **cra-append-sw@2.7.0** to reso | License | ✓ | ``` -$ trivy image -f json -o results.json golang:1.12-alpine +$ trivy image -f json -o results.json alpine:latest ```
Result ``` -2019-05-16T01:46:31.777+0900 INFO Updating vulnerability database... -2019-05-16T01:47:03.007+0900 INFO Detecting Alpine vulnerabilities... +2024-12-26T22:01:18+05:30 INFO [vuln] Vulnerability scanning is enabled +2024-12-26T22:01:18+05:30 INFO [secret] Secret scanning is enabled +2024-12-26T22:01:18+05:30 INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning +2024-12-26T22:01:18+05:30 INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.58/docs/scanner/secret#recommendation for faster secret detection +2024-12-26T22:01:18+05:30 INFO Detected OS family="alpine" version="3.20.3" +2024-12-26T22:01:18+05:30 INFO [alpine] Detecting vulnerabilities... os_version="3.20" repository="3.20" pkg_num=14 +2024-12-26T22:01:18+05:30 INFO Number of language-specific files num=0 +2024-12-26T22:01:18+05:30 WARN Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/v0.58/docs/scanner/vulnerability#severity-selection for details. ```
@@ -137,107 +144,176 @@ $ trivy image -f json -o results.json golang:1.12-alpine JSON ``` -[ - { - "Target": "php-app/composer.lock", - "Vulnerabilities": null - }, - { - "Target": "node-app/package-lock.json", - "Vulnerabilities": [ - { - "VulnerabilityID": "CVE-2018-16487", - "PkgName": "lodash", - "InstalledVersion": "4.17.4", - "FixedVersion": "\u003e=4.17.11", - "Title": "lodash: Prototype pollution in utilities function", - "Description": "A prototype pollution vulnerability was found in lodash \u003c4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", - "Severity": "HIGH", - "References": [ - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16487", - ] - } - ] - }, - { - "Target": "trivy-ci-test (alpine 3.7.1)", - "Vulnerabilities": [ - { - "VulnerabilityID": "CVE-2018-16840", - "PkgName": "curl", - "InstalledVersion": "7.61.0-r0", - "FixedVersion": "7.61.1-r1", - "Title": "curl: Use-after-free when closing \"easy\" handle in Curl_close()", - "Description": "A heap use-after-free flaw was found in curl versions from 7.59.0 through 7.61.1 in the code related to closing an easy handle. ", - "Severity": "HIGH", - "References": [ - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16840", - ] - }, - { - "VulnerabilityID": "CVE-2019-3822", - "PkgName": "curl", - "InstalledVersion": "7.61.0-r0", - "FixedVersion": "7.61.1-r2", - "Title": "curl: NTLMv2 type-3 header stack buffer overflow", - "Description": "libcurl versions from 7.36.0 to before 7.64.0 are vulnerable to a stack-based buffer overflow. ", - "Severity": "HIGH", - "References": [ - "https://curl.haxx.se/docs/CVE-2019-3822.html", - "https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E" - ] - }, - { - "VulnerabilityID": "CVE-2018-16839", - "PkgName": "curl", - "InstalledVersion": "7.61.0-r0", - "FixedVersion": "7.61.1-r1", - "Title": "curl: Integer overflow leading to heap-based buffer overflow in Curl_sasl_create_plain_message()", - "Description": "Curl versions 7.33.0 through 7.61.1 are vulnerable to a buffer overrun in the SASL authentication code that may lead to denial of service.", - "Severity": "HIGH", - "References": [ - "https://github.com/curl/curl/commit/f3a24d7916b9173c69a3e0ee790102993833d6c5", - ] - }, - { - "VulnerabilityID": "CVE-2018-19486", - "PkgName": "git", - "InstalledVersion": "2.15.2-r0", - "FixedVersion": "2.15.3-r0", - "Title": "git: Improper handling of PATH allows for commands to be executed from the current directory", - "Description": "Git before 2.19.2 on Linux and UNIX executes commands from the current working directory (as if '.' were at the end of $PATH) in certain cases involving the run_command() API and run-command.c, because there was a dangerous change from execvp to execv during 2017.", - "Severity": "HIGH", - "References": [ - "https://usn.ubuntu.com/3829-1/", +{ + "SchemaVersion": 2, + "CreatedAt": "2024-12-26T21:58:15.943876+05:30", + "ArtifactName": "alpine:latest", + "ArtifactType": "container_image", + "Metadata": { + "OS": { + "Family": "alpine", + "Name": "3.20.3" + }, + "ImageID": "sha256:511a44083d3a23416fadc62847c45d14c25cbace86e7a72b2b350436978a0450", + "DiffIDs": [ + "sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8" + ], + "RepoTags": [ + "alpine:latest" + ], + "RepoDigests": [ + "alpine@sha256:1e42bbe2508154c9126d48c2b8a75420c3544343bf86fd041fb7527e017a4b4a" + ], + "ImageConfig": { + "architecture": "arm64", + "created": "2024-09-06T12:05:36Z", + "history": [ + { + "created": "2024-09-06T12:05:36Z", + "created_by": "ADD alpine-minirootfs-3.20.3-aarch64.tar.gz / # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2024-09-06T12:05:36Z", + "created_by": "CMD [\"/bin/sh\"]", + "comment": "buildkit.dockerfile.v0", + "empty_layer": true + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8" ] }, - { - "VulnerabilityID": "CVE-2018-17456", - "PkgName": "git", - "InstalledVersion": "2.15.2-r0", - "FixedVersion": "2.15.3-r0", - "Title": "git: arbitrary code execution via .gitmodules", - "Description": "Git before 2.14.5, 2.15.x before 2.15.3, 2.16.x before 2.16.5, 2.17.x before 2.17.2, 2.18.x before 2.18.1, and 2.19.x before 2.19.1 allows remote code execution during processing of a recursive \"git clone\" of a superproject if a .gitmodules file has a URL field beginning with a '-' character.", - "Severity": "HIGH", - "References": [ - "http://www.securitytracker.com/id/1041811", - ] + "config": { + "Cmd": [ + "/bin/sh" + ], + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "WorkingDir": "/", + "ArgsEscaped": true } - ] - }, - { - "Target": "python-app/Pipfile.lock", - "Vulnerabilities": null + } }, - { - "Target": "ruby-app/Gemfile.lock", - "Vulnerabilities": null - }, - { - "Target": "rust-app/Cargo.lock", - "Vulnerabilities": null - } -] + "Results": [ + { + "Target": "alpine:latest (alpine 3.20.3)", + "Class": "os-pkgs", + "Type": "alpine", + "Vulnerabilities": [ + { + "VulnerabilityID": "CVE-2024-9143", + "PkgID": "libcrypto3@3.3.2-r0", + "PkgName": "libcrypto3", + "PkgIdentifier": { + "PURL": "pkg:apk/alpine/libcrypto3@3.3.2-r0?arch=aarch64\u0026distro=3.20.3", + "UID": "f705555b49cd2259" + }, + "InstalledVersion": "3.3.2-r0", + "FixedVersion": "3.3.2-r1", + "Status": "fixed", + "Layer": { + "DiffID": "sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8" + }, + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2024-9143", + "DataSource": { + "ID": "alpine", + "Name": "Alpine Secdb", + "URL": "https://secdb.alpinelinux.org/" + }, + "Title": "openssl: Low-level invalid GF(2^m) parameters lead to OOB memory access", + "Description": "Issue summary: Use of the low-level GF(2^m) elliptic curve APIs with untrusted\nexplicit values for the field polynomial can lead to out-of-bounds memory reads\nor writes.\n\nImpact summary: Out of bound memory writes can lead to an application crash or\neven a possibility of a remote code execution, however, in all the protocols\ninvolving Elliptic Curve Cryptography that we're aware of, either only \"named\ncurves\" are supported, or, if explicit curve parameters are supported, they\nspecify an X9.62 encoding of binary (GF(2^m)) curves that can't represent\nproblematic input values. Thus the likelihood of existence of a vulnerable\napplication is low.\n\nIn particular, the X9.62 encoding is used for ECC keys in X.509 certificates,\nso problematic inputs cannot occur in the context of processing X.509\ncertificates. Any problematic use-cases would have to be using an \"exotic\"\ncurve encoding.\n\nThe affected APIs include: EC_GROUP_new_curve_GF2m(), EC_GROUP_new_from_params(),\nand various supporting BN_GF2m_*() functions.\n\nApplications working with \"exotic\" explicit binary (GF(2^m)) curve parameters,\nthat make it possible to represent invalid field polynomials with a zero\nconstant term, via the above or similar APIs, may terminate abruptly as a\nresult of reading or writing outside of array bounds. Remote code execution\ncannot easily be ruled out.\n\nThe FIPS modules in 3.3, 3.2, 3.1 and 3.0 are not affected by this issue.", + "Severity": "LOW", + "CweIDs": [ + "CWE-787" + ], + "VendorSeverity": { + "amazon": 3, + "redhat": 1, + "ubuntu": 1 + }, + "CVSS": { + "redhat": { + "V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L", + "V3Score": 3.7 + } + }, + "References": [ + "https://access.redhat.com/security/cve/CVE-2024-9143", + "https://github.com/openssl/openssl/commit/72ae83ad214d2eef262461365a1975707f862712", + "https://github.com/openssl/openssl/commit/bc7e04d7c8d509fb78fc0e285aa948fb0da04700", + "https://github.com/openssl/openssl/commit/c0d3e4d32d2805f49bec30547f225bc4d092e1f4", + "https://github.com/openssl/openssl/commit/fdf6723362ca51bd883295efe206cb5b1cfa5154", + "https://github.openssl.org/openssl/extended-releases/commit/8efc0cbaa8ebba8e116f7b81a876a4123594d86a", + "https://github.openssl.org/openssl/extended-releases/commit/9d576994cec2b7aa37a91740ea7e680810957e41", + "https://nvd.nist.gov/vuln/detail/CVE-2024-9143", + "https://openssl-library.org/news/secadv/20241016.txt", + "https://www.cve.org/CVERecord?id=CVE-2024-9143" + ], + "PublishedDate": "2024-10-16T17:15:18.13Z", + "LastModifiedDate": "2024-11-08T16:35:21.58Z" + }, + { + "VulnerabilityID": "CVE-2024-9143", + "PkgID": "libssl3@3.3.2-r0", + "PkgName": "libssl3", + "PkgIdentifier": { + "PURL": "pkg:apk/alpine/libssl3@3.3.2-r0?arch=aarch64\u0026distro=3.20.3", + "UID": "c4a39ef718e71832" + }, + "InstalledVersion": "3.3.2-r0", + "FixedVersion": "3.3.2-r1", + "Status": "fixed", + "Layer": { + "DiffID": "sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8" + }, + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2024-9143", + "DataSource": { + "ID": "alpine", + "Name": "Alpine Secdb", + "URL": "https://secdb.alpinelinux.org/" + }, + "Title": "openssl: Low-level invalid GF(2^m) parameters lead to OOB memory access", + "Description": "Issue summary: Use of the low-level GF(2^m) elliptic curve APIs with untrusted\nexplicit values for the field polynomial can lead to out-of-bounds memory reads\nor writes.\n\nImpact summary: Out of bound memory writes can lead to an application crash or\neven a possibility of a remote code execution, however, in all the protocols\ninvolving Elliptic Curve Cryptography that we're aware of, either only \"named\ncurves\" are supported, or, if explicit curve parameters are supported, they\nspecify an X9.62 encoding of binary (GF(2^m)) curves that can't represent\nproblematic input values. Thus the likelihood of existence of a vulnerable\napplication is low.\n\nIn particular, the X9.62 encoding is used for ECC keys in X.509 certificates,\nso problematic inputs cannot occur in the context of processing X.509\ncertificates. Any problematic use-cases would have to be using an \"exotic\"\ncurve encoding.\n\nThe affected APIs include: EC_GROUP_new_curve_GF2m(), EC_GROUP_new_from_params(),\nand various supporting BN_GF2m_*() functions.\n\nApplications working with \"exotic\" explicit binary (GF(2^m)) curve parameters,\nthat make it possible to represent invalid field polynomials with a zero\nconstant term, via the above or similar APIs, may terminate abruptly as a\nresult of reading or writing outside of array bounds. Remote code execution\ncannot easily be ruled out.\n\nThe FIPS modules in 3.3, 3.2, 3.1 and 3.0 are not affected by this issue.", + "Severity": "LOW", + "CweIDs": [ + "CWE-787" + ], + "VendorSeverity": { + "amazon": 3, + "redhat": 1, + "ubuntu": 1 + }, + "CVSS": { + "redhat": { + "V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L", + "V3Score": 3.7 + } + }, + "References": [ + "https://access.redhat.com/security/cve/CVE-2024-9143", + "https://github.com/openssl/openssl/commit/72ae83ad214d2eef262461365a1975707f862712", + "https://github.com/openssl/openssl/commit/bc7e04d7c8d509fb78fc0e285aa948fb0da04700", + "https://github.com/openssl/openssl/commit/c0d3e4d32d2805f49bec30547f225bc4d092e1f4", + "https://github.com/openssl/openssl/commit/fdf6723362ca51bd883295efe206cb5b1cfa5154", + "https://github.openssl.org/openssl/extended-releases/commit/8efc0cbaa8ebba8e116f7b81a876a4123594d86a", + "https://github.openssl.org/openssl/extended-releases/commit/9d576994cec2b7aa37a91740ea7e680810957e41", + "https://nvd.nist.gov/vuln/detail/CVE-2024-9143", + "https://openssl-library.org/news/secadv/20241016.txt", + "https://www.cve.org/CVERecord?id=CVE-2024-9143" + ], + "PublishedDate": "2024-10-16T17:15:18.13Z", + "LastModifiedDate": "2024-11-08T16:35:21.58Z" + } + ] + } + ] +} + ``` @@ -339,8 +415,8 @@ If Trivy is installed using rpm then default templates can be found at `/usr/loc |:----------------:|:---------:| | Vulnerability | ✓ | | Misconfiguration | ✓ | -| Secret | | -| License | | +| Secret | ✓ | +| License | ✓ | In the following example using the template `junit.tpl` XML can be generated. ``` @@ -449,6 +525,7 @@ $ trivy convert --format table --severity CRITICAL result.json [yarn-lock]: ../coverage/language/nodejs.md#yarn [dotnet-packages-lock]: ../coverage/language/dotnet.md#packageslockjson [poetry-lock]: ../coverage/language/python.md#poetry +[uv-lock]: ../coverage/language/python.md#uv [gemfile-lock]: ../coverage/language/ruby.md#bundler [go-mod]: ../coverage/language/golang.md#go-module [composer-lock]: ../coverage/language/php.md#composerlock diff --git a/docs/docs/coverage/language/index.md b/docs/docs/coverage/language/index.md index 74d578852241..a922986400c1 100644 --- a/docs/docs/coverage/language/index.md +++ b/docs/docs/coverage/language/index.md @@ -22,6 +22,7 @@ On the other hand, when the target is a post-build artifact, like a container im | | gemspec | ✅ | ✅ | - | - | | [Python](python.md) | Pipfile.lock | - | - | ✅ | ✅ | | | poetry.lock | - | - | ✅ | ✅ | +| | uv.lock | - | - | ✅ | ✅ | | | requirements.txt | - | - | ✅ | ✅ | | | egg package[^1] | ✅ | ✅ | - | - | | | wheel package[^2] | ✅ | ✅ | - | - | diff --git a/docs/docs/coverage/language/python.md b/docs/docs/coverage/language/python.md index 6b249adfcb8b..24d920fb9271 100644 --- a/docs/docs/coverage/language/python.md +++ b/docs/docs/coverage/language/python.md @@ -8,6 +8,7 @@ The following scanners are supported for package managers. | pip | ✓ | ✓ | ✓ | | Pipenv | ✓ | ✓ | - | | Poetry | ✓ | ✓ | - | +| uv | ✓ | ✓ | - | In addition, Trivy supports three formats of Python packages: `egg`, `wheel` and `conda`. The following scanners are supported for Python packages. @@ -25,7 +26,8 @@ The following table provides an outline of the features Trivy offers. |-----------------|------------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|:----------------------------------------:| | pip | requirements.txt | - | Include | - | ✓ | ✓ | | Pipenv | Pipfile.lock | ✓ | Include | - | ✓ | Not needed | -| Poetry | poetry.lock | ✓ | Exclude | ✓ | - | Not needed | +| Poetry | poetry.lock | ✓ | [Exclude](#poetry) | ✓ | - | Not needed | +| uv | uv.lock | ✓ | [Exclude](#uv) | ✓ | - | Not needed | | | Packaging | Dependency graph | @@ -126,6 +128,16 @@ To build the correct dependency graph, `pyproject.toml` also needs to be present License detection is not supported for `Poetry`. +By default, Trivy doesn't report development dependencies. Use the `--include-dev-deps` flag to include them. + + +### uv +Trivy uses `uv.lock` to identify dependencies and find vulnerabilities. + +License detection is not supported for `uv`. + +By default, Trivy doesn't report development dependencies. Use the `--include-dev-deps` flag to include them. + ## 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/package-formats/) for the detail. diff --git a/docs/docs/coverage/os/index.md b/docs/docs/coverage/os/index.md index 8756ddc8aa95..74a40787c600 100644 --- a/docs/docs/coverage/os/index.md +++ b/docs/docs/coverage/os/index.md @@ -11,7 +11,7 @@ Trivy supports operating systems for | OS | Supported Versions | Package Managers | |---------------------------------------|-------------------------------------|------------------| -| [Alpine Linux](alpine.md) | 2.2 - 2.7, 3.0 - 3.20, edge | apk | +| [Alpine Linux](alpine.md) | 2.2 - 2.7, 3.0 - 3.21, edge | apk | | [Wolfi Linux](wolfi.md) | (n/a) | apk | | [Chainguard](chainguard.md) | (n/a) | apk | | [Red Hat Enterprise Linux](rhel.md) | 6, 7, 8 | dnf/yum/rpm | diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index 4bf6aa064999..dab87fc541fc 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -35,6 +35,7 @@ trivy filesystem [flags] PATH - "precise": Prioritizes precise by minimizing false positives. - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") + --distro string [EXPERIMENTAL] specify a distribution, / --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan --enable-modules strings [EXPERIMENTAL] module names to enable diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index 41bc6ce842bc..8727cfbd90d4 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -49,6 +49,7 @@ trivy image [flags] IMAGE_NAME - "precise": Prioritizes precise by minimizing false positives. - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") + --distro string [EXPERIMENTAL] specify a distribution, / --docker-host string unix domain socket path to use for docker scanning --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan @@ -78,6 +79,7 @@ trivy image [flags] IMAGE_NAME --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files --list-all-pkgs output all packages in the JSON report regardless of vulnerability + --max-image-size string [EXPERIMENTAL] maximum image size to process, specified in a human-readable format (e.g., '44kB', '17MB'); an error will be returned if the image exceeds this size --misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot]) --module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules") --no-progress suppress progress bar diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index 9290ec0719b8..959532e1c806 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -45,6 +45,7 @@ trivy kubernetes [flags] [CONTEXT] - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") --disable-node-collector When the flag is activated, the node-collector job will not be executed, thus skipping misconfiguration findings on the node. + --distro string [EXPERIMENTAL] specify a distribution, / --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan --exclude-kinds strings indicate the kinds exclude from scanning (example: node) diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 38ae6611b595..1b756d900348 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -19,7 +19,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) ``` --branch string pass the branch name to be scanned - --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "memory") + --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "fs") --cache-ttl duration cache TTL when using redis as cache backend --cf-params strings specify paths to override the CloudFormation parameters files --check-namespaces strings Rego namespaces diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index b84dcc5cd2c3..35cc54ff66a3 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -37,6 +37,7 @@ trivy rootfs [flags] ROOTDIR - "precise": Prioritizes precise by minimizing false positives. - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") + --distro string [EXPERIMENTAL] specify a distribution, / --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan --enable-modules strings [EXPERIMENTAL] module names to enable diff --git a/docs/docs/references/configuration/cli/trivy_sbom.md b/docs/docs/references/configuration/cli/trivy_sbom.md index 9456e8883532..63f855b13335 100644 --- a/docs/docs/references/configuration/cli/trivy_sbom.md +++ b/docs/docs/references/configuration/cli/trivy_sbom.md @@ -29,6 +29,7 @@ trivy sbom [flags] SBOM_PATH - "precise": Prioritizes precise by minimizing false positives. - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") + --distro string [EXPERIMENTAL] specify a distribution, / --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan --exit-code int specify exit code when any security issues are found diff --git a/docs/docs/references/configuration/cli/trivy_vm.md b/docs/docs/references/configuration/cli/trivy_vm.md index 1074d878d866..6fe9de30fcd8 100644 --- a/docs/docs/references/configuration/cli/trivy_vm.md +++ b/docs/docs/references/configuration/cli/trivy_vm.md @@ -33,6 +33,7 @@ trivy vm [flags] VM_IMAGE - "precise": Prioritizes precise by minimizing false positives. - "comprehensive": Aims to detect more security findings at the cost of potential false positives. (precise,comprehensive) (default "precise") + --distro string [EXPERIMENTAL] specify a distribution, / --download-db-only download/update vulnerability database but don't run a scan --download-java-db-only download/update Java index database but don't run a scan --enable-modules strings [EXPERIMENTAL] module names to enable diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index 365d2e5a57a9..d8cdefb98719 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -137,6 +137,9 @@ image: # Same as '--input' input: "" + # Same as '--max-image-size' + max-size: "" + # Same as '--platform' platform: "" @@ -461,6 +464,8 @@ pkg: ```yaml registry: + mirrors: + # Same as '--password' password: [] @@ -570,6 +575,9 @@ scan: # Same as '--detection-priority' detection-priority: "precise" + # Same as '--distro' + distro: "" + # Same as '--file-patterns' file-patterns: [] diff --git a/docs/docs/references/troubleshooting.md b/docs/docs/references/troubleshooting.md index 5d51b0532200..41bb8acb1c93 100644 --- a/docs/docs/references/troubleshooting.md +++ b/docs/docs/references/troubleshooting.md @@ -79,21 +79,25 @@ $ TRIVY_INSECURE=true trivy image [YOUR_IMAGE] ``` ### GitHub Rate limiting +Trivy uses GitHub API for [VEX repositories](../supply-chain/vex/repo.md). !!! error ``` bash - $ trivy image ... + $ trivy image --vex repo ... ... API rate limit exceeded for xxx.xxx.xxx.xxx. ``` -Specify GITHUB_TOKEN for authentication -https://developer.github.com/v3/#rate-limiting +Specify GITHUB_TOKEN for [authentication](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28) ``` -$ GITHUB_TOKEN=XXXXXXXXXX trivy alpine:3.10 +$ GITHUB_TOKEN=XXXXXXXXXX trivy image --vex repo [YOUR_IMAGE] ``` +!!! note + `GITHUB_TOKEN` doesn't help with the rate limit for the vulnerability database and other assets. + See https://github.com/aquasecurity/trivy/discussions/8009 + ### Unable to open JAR files !!! error @@ -217,6 +221,11 @@ Please remove the token and try downloading the DB again. docker logout ghcr.io ``` +or + +```shell +unset GITHUB_TOKEN +``` ## Homebrew ### Scope error diff --git a/docs/docs/scanner/misconfiguration/custom/index.md b/docs/docs/scanner/misconfiguration/custom/index.md index d45638f1533d..c0dc382dec14 100644 --- a/docs/docs/scanner/misconfiguration/custom/index.md +++ b/docs/docs/scanner/misconfiguration/custom/index.md @@ -121,17 +121,17 @@ Trivy supports extra fields in the `custom` section as described below. If you are creating checks for your Trivy misconfiguration scans, some fields are optional as referenced in the table below. The `schemas` field should be used to enable policy validation using a built-in schema. It is recommended to use this to ensure your checks are correct and do not reference incorrect properties/values. -| Field name | Allowed values | Default value | In table | In JSON | -|----------------------------|-------------------------------------------------------------------|:----------------------------:|:----------------:|:----------------:| -| title | Any characters | N/A | :material-check: | :material-check: | -| description | Any characters | | :material-close: | :material-check: | -| schemas.input | `schema["kubernetes"]`, `schema["dockerfile"]`, `schema["cloud"]` | (applied to all input types) | :material-close: | :material-close: | -| custom.id | Any characters | N/A | :material-check: | :material-check: | -| custom.severity | `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` | UNKNOWN | :material-check: | :material-check: | -| custom.recommended_actions | Any characters | | :material-close: | :material-check: | -| custom.deprecated | `true`, `false` | `false` | :material-close: | :material-check: | -| custom.input.selector.type | Any item(s) in [this list][source-types] | | :material-close: | :material-check: | -| url | Any characters | | :material-close: | :material-check: | +| Field name | Allowed values | Default value | In table | In JSON | +|----------------------------|-------------------------------------------------------------------|:----------------------------:|:--------:|:-------:| +| title | Any characters | N/A | ✅ | ✅ | +| description | Any characters | | - | ✅ | +| schemas.input | `schema["kubernetes"]`, `schema["dockerfile"]`, `schema["cloud"]` | (applied to all input types) | - | - | +| custom.id | Any characters | N/A | ✅ | ✅ | +| custom.severity | `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` | UNKNOWN | ✅ | ✅ | +| custom.recommended_actions | Any characters | | - | ✅ | +| custom.deprecated | `true`, `false` | `false` | - | ✅ | +| custom.input.selector.type | Any item(s) in [this list][source-types] | | - | ✅ | +| url | Any characters | | - | ✅ | #### custom.avd_id and custom.id diff --git a/docs/docs/scanner/misconfiguration/index.md b/docs/docs/scanner/misconfiguration/index.md index 8a2f331b6ab0..7419e7757af9 100644 --- a/docs/docs/scanner/misconfiguration/index.md +++ b/docs/docs/scanner/misconfiguration/index.md @@ -449,9 +449,9 @@ From the Terraform [docs](https://developer.hashicorp.com/terraform/cli/config/c If multiple variables evaluate to the same hostname, Trivy will choose the environment variable name where the dashes have not been encoded as double underscores. -### Skipping resources by inline comments +### Skipping detected misconfigurations by inline comments -Trivy supports ignoring misconfigured resources by inline comments for Terraform and CloudFormation configuration files only. +Trivy supports ignoring detected misconfigurations by inline comments for Terraform, CloudFormation (YAML), Helm and Dockerfile configuration files only. In cases where Trivy can detect comments of a specific format immediately adjacent to resource definitions, it is possible to ignore findings from a single source of resource definition (in contrast to `.trivyignore`, which has a directory-wide scope on all of the files scanned). The format for these comments is `trivy:ignore:` immediately following the format-specific line-comment [token](https://developer.hashicorp.com/terraform/language/syntax/configuration#comments). @@ -503,6 +503,29 @@ Resources: BucketName: test-bucket ``` +!!!note + Ignore rules for Helm files should be placed before the YAML object, since only it contains the location data needed for ignoring. + +Example for Helm: +```yaml + serviceAccountName: "testchart.serviceAccountName" + containers: + # trivy:ignore:KSV018 + - name: "testchart" + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + image: "your-repository/your-image:your-tag" + imagePullPolicy: "Always" +``` + +Example for Dockerfile: +```Dockerfile +FROM scratch +# trivy:ignore:AVD-DS-0022 +MAINTAINER moby@example.com +``` + #### Expiration Date You can specify the expiration date of the ignore rule in `yyyy-mm-dd` format. This is a useful feature when you want to make sure that an ignored issue is not forgotten and worth revisiting in the future. For example: diff --git a/docs/docs/scanner/vulnerability.md b/docs/docs/scanner/vulnerability.md index 9d4e908c667b..26aeacee58e9 100644 --- a/docs/docs/scanner/vulnerability.md +++ b/docs/docs/scanner/vulnerability.md @@ -339,6 +339,12 @@ Regardless of the chosen mode, user review of detected vulnerabilities is crucia - `precise`: Review thoroughly, considering potential missed vulnerabilities. - `comprehensive`: Carefully investigate each reported vulnerability due to increased false positive possibility. +### Overriding OS version +By default, Trivy automatically detects the OS during container image scanning and performs vulnerability detection based on that OS. +However, in some cases, you may want to scan an image with a different OS version than the one detected. +Also, you may want to specify the OS version when OS is not detected. +For these cases, Trivy supports a `--distro` flag using the `/` format (e.g. `alpine/3.20`) to set the desired OS version. + [^1]: https://github.com/GoogleContainerTools/distroless [nvd-CVE-2023-0464]: https://nvd.nist.gov/vuln/detail/CVE-2023-0464 diff --git a/docs/docs/supply-chain/vex/file.md b/docs/docs/supply-chain/vex/file.md index 242ec4c5a040..bc5e92d34643 100644 --- a/docs/docs/supply-chain/vex/file.md +++ b/docs/docs/supply-chain/vex/file.md @@ -269,13 +269,13 @@ You can see [the appendix](#applying-vex-to-dependency-trees) for more details o Provide the VEX when scanning your target. ```bash -$ trivy image debian:11 --vex debian11.openvex.json +$ trivy image debian:11.6 --vex debian11.openvex.json ... 2023-04-26T17:56:05.358+0300 INFO Filtered out the detected vulnerability {"VEX format": "OpenVEX", "vulnerability-id": "CVE-2019-8457", "status": "not_affected", "justification": "vulnerable_code_not_in_execute_path"} -debian11.spdx.json (debian 11.6) -================================ -Total: 80 (UNKNOWN: 0, LOW: 58, MEDIUM: 6, HIGH: 16, CRITICAL: 0) +debian:11.6 (debian 11.6) + +Total: 176 (UNKNOWN: 1, LOW: 82, MEDIUM: 46, HIGH: 41, CRITICAL: 5) ``` CVE-2019-8457 is no longer shown as it is filtered out according to the given OpenVEX document. @@ -420,13 +420,13 @@ You can see [the appendix](#applying-vex-to-dependency-trees) for more details o Provide the CSAF document when scanning your target. ```bash -$ trivy image debian:11 --vex debian11.vex.csaf +$ trivy image debian:11.8 --vex debian11.vex.csaf ... 2024-01-02T10:28:26.704+0100 INFO Filtered out the detected vulnerability {"VEX format": "CSAF", "vulnerability-id": "CVE-2019-8457", "status": "not_affected"} -debian11.spdx.json (debian 11.6) -================================ -Total: 80 (UNKNOWN: 0, LOW: 58, MEDIUM: 6, HIGH: 16, CRITICAL: 0) +debian:11.8 (debian 11.8) + +Total: 153 (UNKNOWN: 1, LOW: 82, MEDIUM: 33, HIGH: 32, CRITICAL: 5) ``` CVE-2019-8457 is no longer shown as it is filtered out according to the given CSAF document. diff --git a/docs/docs/target/container_image.md b/docs/docs/target/container_image.md index 8129c0c071e0..62d5e7e09984 100644 --- a/docs/docs/target/container_image.md +++ b/docs/docs/target/container_image.md @@ -463,6 +463,12 @@ trivy image --compliance docker-cis-1.6.0 [YOUR_IMAGE_NAME] ## Authentication Please reference [this page](../advanced/private-registries/index.md). +## Scan Cache +When scanning container images, it stores analysis results in the cache, using the image ID and the layer IDs as the key. +This approach enables faster scans of the same container image or different images that share layers. + +More details are available in the [cache documentation](../configuration/cache.md#scan-cache-backend). + ## Options ### Scan Image on a specific Architecture and OS By default, Trivy loads an image on a "linux/amd64" machine. @@ -518,3 +524,30 @@ You can configure Podman daemon socket with `--podman-host`. ```shell $ trivy image --podman-host /run/user/1000/podman/podman.sock YOUR_IMAGE ``` + +### Prevent scanning oversized container images +Use the `--max-image-size` flag to avoid scanning images that exceed a specified size. The size is specified in a human-readable format[^1] (e.g., `100MB`, `10GB`). + +An error is returned in the following cases: + +- if the compressed image size exceeds the limit, +- if the accumulated size of the uncompressed layers exceeds the limit during their pulling. + +The layers are pulled into a temporary folder during their pulling and are always cleaned up, even after a successful scan. + +!!! warning "EXPERIMENTAL" + This feature might change without preserving backwards compatibility. + + +Example Usage: +```bash +# Limit uncompressed image size to 10GB +$ trivy image --max-image-size=10GB myapp:latest +``` + +Error Output: +```bash +Error: uncompressed image size (15GB) exceeds maximum allowed size (10GB) +``` + +[^1]: Trivy uses decimal (SI) prefixes (based on 1000) for size. diff --git a/docs/docs/target/filesystem.md b/docs/docs/target/filesystem.md index 72e47f0e0c5e..273a51188717 100644 --- a/docs/docs/target/filesystem.md +++ b/docs/docs/target/filesystem.md @@ -91,3 +91,13 @@ $ trivy fs --scanners license /path/to/project ## SBOM generation Trivy can generate SBOM for local projects. See [here](../supply-chain/sbom.md) for the detail. + +## Scan Cache +When scanning local projects, it doesn't use the cache by default. +However, when the local project is a git repository with clean status and the cache backend other than the memory one is enabled, it stores analysis results, using the latest commit hash as the key. + +```shell +$ trivy fs --cache-backend fs /path/to/git/repo +``` + +More details are available in the [cache documentation](../configuration/cache.md#scan-cache-backend). diff --git a/docs/docs/target/kubernetes.md b/docs/docs/target/kubernetes.md index 291c9fb7728e..1d06eebd6cd2 100644 --- a/docs/docs/target/kubernetes.md +++ b/docs/docs/target/kubernetes.md @@ -38,6 +38,10 @@ for example: trivy k8s --report summary ``` +!!! note "JSON result for multi-container pods" + For multi-container pods, it may be challenging to associate results with specific images in the json summary report. Kubernetes treats a pod as a single object, so individual images within the pod aren’t distinguished. + For detailed information, please use the `--report all` option. + By default Trivy will look for a [`kubeconfig` configuration file in the default location](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/), and use the default cluster that is specified. You can also specify a `kubeconfig` using the `--kubeconfig` flag: @@ -45,10 +49,41 @@ You can also specify a `kubeconfig` using the `--kubeconfig` flag: trivy k8s --kubeconfig ~/.kube/config2 ``` -By default, all cluster resource images will be downloaded and scanned. +## Required roles +To successfully scan a Kubernetes cluster, `trivy kubernetes` subcommand must be executed under a role or a cluster role that has some specific permissions. + +The role must have `list` verb for all resources (`"*"`) inside the following API groups: core (`""`), `"apps"`, `"batch"`,`"networking.k8s.io"`, `"rbac.authorization.k8s.io"`: +```yaml +- apiGroups: [""] + resources: ["*"] + verbs: ["list"] +- apiGroups: ["apps", "batch", "networking.k8s.io", "rbac.authorization.k8s.io"] + resources: ["*"] + verbs: ["list"] +``` +If `node collector` is enabled (default: enabled), Trivy needs a cluster role with some additional permissions to run and track the jobs: +```yaml +- apiGroups: [""] + resources: ["nodes/proxy", "pods/log"] + verbs: ["get"] +- apiGroups: [""] + resources: ["events"] + verbs: ["watch"] +- apiGroups: ["batch"] + resources: ["jobs", "cronjobs"] + verbs: ["list", "get"] +- apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["create","delete", "watch"] +- apiGroups: [""] + resources: ["namespaces"] + verbs: ["create"] +``` ### Skip-images +By default, all cluster resource images will be downloaded and scanned. + You can control whether Trivy will scan and download the cluster resource images. To disable this feature, add the --skip-images flag. - `--skip-images` flag will prevent the downloading and scanning of images (including vulnerabilities and secrets) in the cluster resources. @@ -87,6 +122,9 @@ You can control which namespaces will be discovered using the `--include-namespa By default, all namespaces will be included in cluster scanning. +!!! note "using `--exclude-namespaces`" + Trivy requires a complete list of namespaces to exclude specific ones. Therefore, `--exclude-namespaces` option is only available for cluster roles now. + Example: ```sh diff --git a/docs/docs/target/repository.md b/docs/docs/target/repository.md index a4385825e33f..9a8a3165d204 100644 --- a/docs/docs/target/repository.md +++ b/docs/docs/target/repository.md @@ -109,6 +109,12 @@ $ trivy repo --scanners license (REPO_PATH | REPO_URL) Trivy can generate SBOM for code repositories. See [here](../supply-chain/sbom.md) for the detail. +## Scan Cache +When scanning git repositories, it stores analysis results in the cache, using the latest commit hash as the key. +Note that the cache is not used when the repository is dirty, otherwise Trivy will miss the files that are not committed. + +More details are available in the [cache documentation](../configuration/cache.md#scan-cache-backend). + ## References The following flags and environmental variables are available for remote git repositories. diff --git a/docs/docs/target/vm.md b/docs/docs/target/vm.md index 44ab945ce35d..4bba67626463 100644 --- a/docs/docs/target/vm.md +++ b/docs/docs/target/vm.md @@ -182,6 +182,14 @@ $ trivy vm --scanners license [YOUR_VM_IMAGE] Trivy can generate SBOM for VM images. See [here](../supply-chain/sbom.md) for the detail. +## Scan Cache +When scanning AMI or EBS snapshots, it stores analysis results in the cache, using the snapshot ID. +Scanning the same snapshot several times skips analysis if the cache is already available. + +When scanning local files, it doesn't use the cache by default. + +More details are available in the [cache documentation](../configuration/cache.md#scan-cache-backend). + ## Supported Architectures ### Virtual machine images diff --git a/docs/getting-started/faq.md b/docs/getting-started/faq.md index 3bd1e9fcb978..f31c2f89ab08 100644 --- a/docs/getting-started/faq.md +++ b/docs/getting-started/faq.md @@ -11,7 +11,7 @@ Check out the [Scanning coverage page](../docs/coverage/index.md). ### Is there a paid version of Trivy? If you liked Trivy, you will love Aqua which builds on top of Trivy to provide even more enhanced capabilities for a complete security management offering. -You can find a high level comparison table specific to Trivy users [here](https://github.com/aquasecurity/resources/blob/main/trivy-aqua.md). +You can find a high level comparison table specific to Trivy users [here](../commercial/compare.md). In addition check out the website for more information about our products and services. If you'd like to contact Aqua or request a demo, please use this form: diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 73ddddafda48..b46ce3c340ea 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -69,6 +69,6 @@ Now that you up and ready, here are some resources to help you deepen your knowl # Want more? Check out Aqua If you liked Trivy, you will love Aqua which builds on top of Trivy to provide even more enhanced capabilities for a complete security management offering. -You can find a high level comparison table specific to Trivy users [here](https://github.com/aquasecurity/resources/blob/main/trivy-aqua.md). +You can find a high level comparison table specific to Trivy users [here](../commercial/compare.md). In addition, check out the website for more information about our products and services. If you'd like to contact Aqua or request a demo, please use this form: diff --git a/examples/module/spring4shell/spring4shell.go b/examples/module/spring4shell/spring4shell.go index 6c527cc946b2..18bda7094b11 100644 --- a/examples/module/spring4shell/spring4shell.go +++ b/examples/module/spring4shell/spring4shell.go @@ -5,6 +5,7 @@ package main import ( "bufio" + "errors" "fmt" "io" "os" @@ -112,7 +113,7 @@ func (Spring4Shell) parseTomcatReleaseNotes(f *os.File, filePath string) (*seria m := tomcatVersionRegex.FindStringSubmatch(string(b)) if len(m) != 2 { - return nil, fmt.Errorf("unknown tomcat release notes format") + return nil, errors.New("unknown tomcat release notes format") } return &serialize.AnalysisResult{ diff --git a/go.mod b/go.mod index eabb8d2df514..05ce5907ad1f 100644 --- a/go.mod +++ b/go.mod @@ -1,71 +1,72 @@ module github.com/aquasecurity/trivy -go 1.22.9 +go 1.23.4 require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 github.com/BurntSushi/toml v1.4.0 - github.com/CycloneDX/cyclonedx-go v0.9.1 + github.com/CycloneDX/cyclonedx-go v0.9.2 github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible github.com/Masterminds/sprig/v3 v3.3.0 github.com/NYTimes/gziphandler v1.1.1 github.com/alecthomas/chroma v0.10.0 - github.com/alicebob/miniredis/v2 v2.33.0 - github.com/antchfx/htmlquery v1.3.3 + github.com/alicebob/miniredis/v2 v2.34.0 github.com/apparentlymart/go-cidr v1.1.0 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce - github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 - github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 - github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f + github.com/aquasecurity/go-npm-version v0.0.1 + github.com/aquasecurity/go-pep440-version v0.0.1 + github.com/aquasecurity/go-version v0.0.1 + github.com/aquasecurity/iamgo v0.0.10 + github.com/aquasecurity/jfather v0.0.8 github.com/aquasecurity/table v1.8.0 github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 github.com/aquasecurity/tml v0.6.1 - github.com/aquasecurity/trivy-checks v1.4.0 - github.com/aquasecurity/trivy-db v0.0.0-20241120092622-333d808d7e45 + github.com/aquasecurity/trivy-checks v1.6.1 + github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 - github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc - github.com/aws/aws-sdk-go-v2 v1.32.5 - github.com/aws/aws-sdk-go-v2/config v1.28.5 - github.com/aws/aws-sdk-go-v2/credentials v1.17.46 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 - github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 - github.com/aws/aws-sdk-go-v2/service/s3 v1.68.0 - github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect - github.com/aws/smithy-go v1.22.1 + github.com/aquasecurity/trivy-kubernetes v0.7.0 + github.com/aws/aws-sdk-go-v2 v1.34.0 + github.com/aws/aws-sdk-go-v2/config v1.29.2 + github.com/aws/aws-sdk-go-v2/credentials v1.17.55 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.201.1 + github.com/aws/aws-sdk-go-v2/service/ecr v1.38.7 + github.com/aws/aws-sdk-go-v2/service/s3 v1.74.1 + github.com/aws/smithy-go v1.22.2 github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c - github.com/bmatcuk/doublestar/v4 v4.7.1 + github.com/bmatcuk/doublestar/v4 v4.8.1 github.com/cenkalti/backoff/v4 v4.3.0 - github.com/cheggaaa/pb/v3 v3.1.5 - github.com/containerd/containerd/v2 v2.0.0 - github.com/containerd/platforms v1.0.0-rc.0 + github.com/cheggaaa/pb/v3 v3.1.6 + github.com/containerd/containerd/v2 v2.0.2 + github.com/containerd/platforms v1.0.0-rc.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.3.1+incompatible - github.com/docker/docker v27.3.1+incompatible + github.com/docker/cli v27.5.0+incompatible + github.com/docker/docker v27.5.0+incompatible github.com/docker/go-connections v0.5.0 + github.com/docker/go-units v0.5.0 github.com/fatih/color v1.18.0 - github.com/go-git/go-git/v5 v5.12.0 + github.com/go-git/go-git/v5 v5.13.2 github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-redis/redis/v8 v8.11.5 - github.com/gocsaf/csaf/v3 v3.1.0 + github.com/gocsaf/csaf/v3 v3.1.1 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/google/go-containerregistry v0.20.2 + github.com/google/go-containerregistry v0.20.3 github.com/google/go-github/v62 v62.0.0 github.com/google/licenseclassifier/v2 v2.0.0 github.com/google/uuid v1.6.0 github.com/google/wire v0.6.0 - github.com/hashicorp/go-getter v1.7.6 + github.com/hashicorp/go-getter v1.7.8 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.7 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.9.0 + github.com/hashicorp/hc-install v0.9.1 github.com/hashicorp/hcl/v2 v2.23.0 - github.com/hashicorp/terraform-exec v0.21.0 + github.com/hashicorp/terraform-exec v0.22.0 github.com/in-toto/in-toto-golang v0.9.0 github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f github.com/knqyf263/go-deb-version v0.0.0-20241115132648-6f4aee6ccd23 @@ -73,8 +74,6 @@ require ( github.com/knqyf263/go-rpmdb v0.1.1 github.com/knqyf263/nested v0.0.1 github.com/kylelemons/godebug v1.1.0 - github.com/liamg/iamgo v0.0.9 - github.com/liamg/jfather v0.0.7 github.com/liamg/memoryfs v1.6.0 github.com/magefile/mage v1.15.0 github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee @@ -88,60 +87,64 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/moby/buildkit v0.17.2 - github.com/open-policy-agent/opa v0.70.0 + github.com/moby/buildkit v0.18.2 + github.com/open-policy-agent/opa v1.1.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 github.com/openvex/go-vex v0.2.5 github.com/owenrumney/go-sarif/v2 v2.3.3 - github.com/owenrumney/squealer v1.2.5 + github.com/owenrumney/squealer v1.2.6 github.com/package-url/packageurl-go v0.1.3 github.com/quasilyte/go-ruleguard/dsl v0.3.22 - github.com/samber/lo v1.47.0 + github.com/samber/lo v1.49.0 github.com/sassoftware/go-rpmutils v0.4.0 - github.com/secure-systems-lab/go-securesystemslib v0.8.0 - github.com/sigstore/rekor v1.3.6 + github.com/secure-systems-lab/go-securesystemslib v0.9.0 + github.com/sigstore/rekor v1.3.8 github.com/sirupsen/logrus v1.9.3 github.com/sosedoff/gitkit v0.4.0 github.com/spdx/tools-golang v0.5.5 // v0.5.3 with necessary changes. Can be upgraded to version 0.5.4 after release. - github.com/spf13/cast v1.7.0 + github.com/spf13/cast v1.7.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 - github.com/testcontainers/testcontainers-go v0.34.0 - github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0 - github.com/tetratelabs/wazero v1.8.1 + github.com/testcontainers/testcontainers-go v0.35.0 + github.com/testcontainers/testcontainers-go/modules/localstack v0.35.0 + github.com/tetratelabs/wazero v1.8.2 github.com/twitchtv/twirp v8.1.3+incompatible github.com/xeipuuv/gojsonschema v1.2.0 github.com/xlab/treeprint v1.2.0 - github.com/zclconf/go-cty v1.15.0 + github.com/zclconf/go-cty v1.16.2 github.com/zclconf/go-cty-yaml v1.1.0 go.etcd.io/bbolt v1.3.11 - golang.org/x/crypto v0.29.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/crypto v0.32.0 + golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect golang.org/x/mod v0.22.0 - golang.org/x/net v0.31.0 - golang.org/x/sync v0.9.0 - golang.org/x/term v0.26.0 - golang.org/x/text v0.20.0 - golang.org/x/vuln v1.1.3 - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 - google.golang.org/protobuf v1.35.2 + golang.org/x/net v0.34.0 + golang.org/x/sync v0.10.0 + golang.org/x/term v0.28.0 + golang.org/x/text v0.21.0 + golang.org/x/vuln v1.1.4 + golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 + google.golang.org/protobuf v1.36.4 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm/v3 v3.16.3 - k8s.io/api v0.31.2 - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 - modernc.org/sqlite v1.34.1 + helm.sh/helm/v3 v3.17.0 + k8s.io/api v0.32.1 + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 + modernc.org/sqlite v1.34.5 sigs.k8s.io/yaml v1.4.0 ) require ( - cloud.google.com/go v0.112.1 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect - cloud.google.com/go/iam v1.1.6 // indirect - cloud.google.com/go/storage v1.39.1 // indirect + cel.dev/expr v0.19.0 // indirect + cloud.google.com/go v0.116.0 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/iam v1.2.2 // indirect + cloud.google.com/go/monitoring v1.21.2 // indirect + cloud.google.com/go/storage v1.45.0 // indirect dario.cat/mergo v1.0.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect @@ -153,8 +156,11 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect github.com/DataDog/zstd v1.5.5 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/Intevation/gval v1.3.0 // indirect github.com/Intevation/jsonpath v0.2.1 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect @@ -164,49 +170,40 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect - github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect + github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/agnivade/levenshtein v1.2.0 // indirect - github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect + github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect - github.com/antchfx/xpath v1.3.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.55.5 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/briandowns/spinner v1.23.0 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // 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.8 // indirect + github.com/cloudflare/circl v1.5.0 // indirect + github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/containerd v1.7.23 // indirect + github.com/containerd/containerd v1.7.25 // indirect github.com/containerd/containerd/api v1.8.0 // indirect - github.com/containerd/continuity v0.4.4 // indirect + github.com/containerd/continuity v0.4.5 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/plugin v1.0.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect - github.com/containerd/ttrpc v1.2.6 // indirect - github.com/containerd/typeurl/v2 v2.2.2 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect + github.com/containerd/ttrpc v1.2.7 // indirect + github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect - github.com/cyphar/filepath-securejoin v0.3.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect @@ -215,23 +212,25 @@ require ( github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.5.0 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/dsnet/compress v0.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/envoyproxy/go-control-plane v0.13.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/evanphx/json-patch v5.9.0+incompatible // indirect - github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.0 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-ini/ini v1.67.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -248,7 +247,7 @@ require ( github.com/gofrs/uuid v4.3.1+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect @@ -257,10 +256,10 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/s2a-go v0.1.7 // indirect + github.com/google/s2a-go v0.1.8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.3 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect @@ -269,14 +268,13 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect - github.com/hashicorp/hcl v1.0.1-vault-5 // indirect - github.com/hashicorp/terraform-json v0.22.1 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect + github.com/hashicorp/terraform-json v0.24.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -284,16 +282,16 @@ require ( github.com/klauspost/compress v1.17.11 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect + github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect github.com/lib/pq v1.10.9 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/magiconair/properties v1.8.9 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect @@ -301,7 +299,7 @@ require ( github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/signal v0.7.1 // indirect @@ -323,7 +321,7 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect @@ -331,14 +329,14 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.61.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/rubenv/sql-migrate v1.7.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect @@ -348,16 +346,16 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sigstore/cosign/v2 v2.2.4 // indirect - github.com/sigstore/sigstore v1.8.3 // indirect + github.com/sigstore/sigstore v1.8.12 // indirect github.com/sigstore/timestamp-authority v1.2.2 // indirect - github.com/skeema/knownhosts v1.2.2 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/tchap/go-patricia/v2 v2.3.1 // indirect + github.com/tchap/go-patricia/v2 v2.3.2 // indirect github.com/theupdateframework/go-tuf v0.7.0 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect @@ -365,7 +363,7 @@ require ( github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect github.com/ulikunitz/xz v0.5.12 // indirect - github.com/vbatts/tar-split v0.11.5 // indirect + github.com/vbatts/tar-split v0.11.6 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -378,53 +376,64 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.32.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect - go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect - golang.org/x/sys v0.27.0 // indirect + golang.org/x/oauth2 v0.25.0 // indirect + golang.org/x/sys v0.29.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect - golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.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-20241007155032-5fefd90f89a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.67.1 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.29.0 // indirect + google.golang.org/api v0.216.0 // indirect + google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/grpc v1.70.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.31.1 // indirect - k8s.io/apimachinery v0.31.2 // indirect - k8s.io/apiserver v0.31.2 // indirect - k8s.io/cli-runtime v0.31.2 // indirect - k8s.io/client-go v0.31.2 // indirect - k8s.io/component-base v0.31.2 // indirect + k8s.io/apiextensions-apiserver v0.32.0 // indirect + k8s.io/apimachinery v0.32.1 // indirect + k8s.io/apiserver v0.32.0 // indirect + k8s.io/cli-runtime v0.32.1 // indirect + k8s.io/client-go v0.32.1 // indirect + k8s.io/component-base v0.32.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/kubectl v0.31.2 // indirect - modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/kubectl v0.32.1 // indirect modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect - modernc.org/strutil v1.2.0 // indirect - modernc.org/token v1.1.0 // indirect mvdan.cc/sh/v3 v3.10.0 // indirect oras.land/oras-go v1.2.5 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.17.2 // indirect - sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/kustomize/api v0.18.0 // indirect + sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) + +require ( + github.com/aws/aws-sdk-go v1.55.6 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.29 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.29 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.10 // indirect +) diff --git a/go.sum b/go.sum index 3ea207f45652..16f8b8f0af20 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,11 @@ +cel.dev/expr v0.19.0 h1:lXuo+nDhpyJSpWxpPVi5cPUwzKb+dsdOiw6IreM5yt0= +cel.dev/expr v0.19.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -15,6 +18,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -26,28 +30,96 @@ cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+Y cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -55,12 +127,44 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -68,122 +172,450 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= -cloud.google.com/go/kms v1.15.8 h1:szIeDCowID8th2i8XE4uRev5PMxQFqW+JjwYxL9h6xs= -cloud.google.com/go/kms v1.15.8/go.mod h1:WoUHcDjD9pluCg7pNds131awnH429QGvRM3N/4MyoVs= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/kms v1.20.4 h1:CJ0hMpOg1ANN9tx/a/GPJ+Uxudy8k6f3fvGFuTHiE5A= +cloud.google.com/go/kms v1.20.4/go.mod h1:gPLsp1r4FblUgBYPOcvI/bUPpdMg2Jm1ZVKU4tQUfcc= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.39.1 h1:MvraqHKhogCOTXTlct/9C3K3+Uy2jBmFYb3/Sp6dVtY= -cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= +cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= +cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e h1:GwCVItFUPxwdsEYnlUcJ6PJxOjTeFFCKOh6QWg4oAzQ= cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHceQLLwcOkCEXM1+DyCXTHEJhNGDpJ2kmV6axsx24= cuelang.org/go v0.8.1 h1:VFYsxIFSPY5KgSaH1jQ2GxHOrbu6Ga3kEI70yCZwnOg= @@ -193,6 +625,8 @@ dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= @@ -203,18 +637,18 @@ github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0/go.mod h1:GgeIE+1be8Ivm7Sh4RgwI42aTtC9qrcj+Y9Y6CjJhJs= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0 h1:7rKG7UmnrxX4N53TFhkYqjc+kVUZuw0fL8I3Fh+Ld9E= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0/go.mod h1:Wjo+24QJVhhl/L7jy6w9yzFF2yDOf3cKECAa8ecf9vE= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 h1:eXnN9kaS8TiDwXjoie3hMRLuwdUBUMW9KRgOqB3mCaw= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0/go.mod h1:XIpam8wumeZ5rVMuhdDQLMfIPDf1WO3IzrCRO3e3e3o= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -239,24 +673,33 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKkqS2qzQM= -github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= +github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo= +github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= github.com/Intevation/gval v1.3.0 h1:+Ze5sft5MmGbZrHj06NVUbcxCb67l9RaPTLMNr37mjw= github.com/Intevation/gval v1.3.0/go.mod h1:xmGyGpP5be12EL0P12h+dqiYG8qn2j3PJxIgkoOHO5o= github.com/Intevation/jsonpath v0.2.1 h1:rINNQJ0Pts5XTFEG+zamtdL7l9uuE1z0FBA+r55Sw+A= github.com/Intevation/jsonpath v0.2.1/go.mod h1:WnZ8weMmwAx/fAO3SutjYFU+v7DFreNYnibV7CiaYIw= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -277,8 +720,8 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= +github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= @@ -289,6 +732,10 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -315,21 +762,21 @@ github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOq github.com/alibabacloud-go/tea-utils v1.4.5/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw= github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= -github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= -github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= -github.com/alicebob/miniredis/v2 v2.33.0 h1:uvTF0EDeu9RLnUEG27Db5I68ESoIxTiXbNUiji6lZrA= -github.com/alicebob/miniredis/v2 v2.33.0/go.mod h1:MhP4a3EU7aENRi9aO+tHfTBZicLqQevyi/DJpoj6mi0= +github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= +github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0= +github.com/alicebob/miniredis/v2 v2.34.0/go.mod h1:kWShP4b58T1CW0Y5dViCd5ztzrDqRWqM3nksiyXk5s8= github.com/aliyun/credentials-go v1.3.1 h1:uq/0v7kWrxmoLGpqjx7vtQ/s03f0zR//0br/xWDTE28= github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE= -github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU= -github.com/antchfx/xpath v1.3.2 h1:LNjzlsSjinu3bQpw9hWMY9ocB80oLOWuQqFvO6xt51U= -github.com/antchfx/xpath v1.3.2/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= @@ -339,28 +786,31 @@ github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s= -github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 h1:eveqE9ivrt30CJ7dOajOfBavhZ4zPqHcZe/4tKp0alc= -github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798/go.mod h1:hxbJZtKlO4P8sZ9nztizR6XLoE33O+BkPmuYQ4ACyz0= -github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 h1:vmXNl+HDfqqXgr0uY1UgK1GAhps8nbAAtqHNBcgyf+4= -github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46/go.mod h1:olhPNdiiAAMiSujemd1O/sc6GcyePr23f/6uGKtthNg= +github.com/aquasecurity/go-npm-version v0.0.1 h1:2i/MM+A4KI8AJrqJa/Cwsa4qyljA8S/qngPyQiIVHcA= +github.com/aquasecurity/go-npm-version v0.0.1/go.mod h1:hxbJZtKlO4P8sZ9nztizR6XLoE33O+BkPmuYQ4ACyz0= +github.com/aquasecurity/go-pep440-version v0.0.1 h1:8VKKQtH2aV61+0hovZS3T//rUF+6GDn18paFTVS0h0M= +github.com/aquasecurity/go-pep440-version v0.0.1/go.mod h1:3naPe+Bp6wi3n4l5iBFCZgS0JG8vY6FT0H4NGhFJ+i4= github.com/aquasecurity/go-version v0.0.0-20201107203531-5e48ac5d022a/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= -github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= -github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f h1:6mwfszC0VohA3NF75EX8pPStmmL0spZnTlkLp83M69c= -github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f/go.mod h1:1cPOp4BaQZ1G2F5fnw4dFz6pkOyXJI9KTuak8ghIl3U= +github.com/aquasecurity/go-version v0.0.1 h1:4cNl516agK0TCn5F7mmYN+xVs1E3S45LkgZk3cbaW2E= +github.com/aquasecurity/go-version v0.0.1/go.mod h1:s1UU6/v2hctXcOa3OLwfj5d9yoXHa3ahf+ipSwEvGT0= +github.com/aquasecurity/iamgo v0.0.10 h1:t/HG/MI1eSephztDc+Rzh/YfgEa+NqgYRSfr6pHdSCQ= +github.com/aquasecurity/iamgo v0.0.10/go.mod h1:GI9IQJL2a+C+V2+i3vcwnNKuIJXZ+HAfqxZytwy+cPk= +github.com/aquasecurity/jfather v0.0.8 h1:tUjPoLGdlkJU0qE7dSzd1MHk2nQFNPR0ZfF+6shaExE= +github.com/aquasecurity/jfather v0.0.8/go.mod h1:Ag+L/KuR/f8vn8okUi8Wc1d7u8yOpi2QTaGX10h71oY= github.com/aquasecurity/table v1.8.0 h1:9ntpSwrUfjrM6/YviArlx/ZBGd6ix8W+MtojQcM7tv0= github.com/aquasecurity/table v1.8.0/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw= github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 h1:b43UVqYjz7qDqK+cVOtF2Lk6CxjytYItP6Pgf3wGsNE= github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8/go.mod h1:wXA9k3uuaxY3yu7gxrxZDPo/04FEMJtwyecdAlYrEIo= github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo= github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY= -github.com/aquasecurity/trivy-checks v1.4.0 h1:XFGPuA8C4f31GO9g7xOkubHq4W87y9iXrWnulsIoZFs= -github.com/aquasecurity/trivy-checks v1.4.0/go.mod h1:TSUbI3wBy9jgQl5lRUCR+B5pNiOxp6M26Jep8VCL/eM= -github.com/aquasecurity/trivy-db v0.0.0-20241120092622-333d808d7e45 h1:ljinbg7JTQvdnzuRsPYS6btA51SyGYWKCQInxSIwbRw= -github.com/aquasecurity/trivy-db v0.0.0-20241120092622-333d808d7e45/go.mod h1:Lg2avQhFy5qeGA0eMysI/61REVvWpEltverCarGc3l0= +github.com/aquasecurity/trivy-checks v1.6.1 h1:ANxKl+c9/k3Uk0YNQwpFBx++CG9Goi5T0YeN7Qimmf4= +github.com/aquasecurity/trivy-checks v1.6.1/go.mod h1:xjHg4ivIIIFD7FFNpGrqxi1pRgAW1EXeG4VlkGiymjI= +github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e h1:O5j5SeCNBrXApgBTOobO06q4LMxJxIhcSGE7H6Y154E= +github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e/go.mod h1:gS8VhlNxhraiq60BBnJw9kGtjeMspQ9E8pX24jCL4jg= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc h1:/mFBYIK9RY+L8s1CIbQbJ5B3v0YmoDSu5eAzavvMa+Y= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc/go.mod h1:ctlibFXOQyjWybeVVQI6NLG6GJoPWZJ4cIirQ/wPCQs= +github.com/aquasecurity/trivy-kubernetes v0.7.0 h1:0pRJFSslUYd9xzQIEw1c0mS7k1Vv489nH/LsxeU6yME= +github.com/aquasecurity/trivy-kubernetes v0.7.0/go.mod h1:O6JZMicTmZrsjEpGzsnBMhPTHAfpnTMqXTAMidG6M+M= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -368,46 +818,46 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= -github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= -github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= -github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= +github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.34.0 h1:9iyL+cjifckRGEVpRKZP3eIxVlL06Qk1Tk13vreaVQU= +github.com/aws/aws-sdk-go-v2 v1.34.0/go.mod h1:JgstGg0JjWU1KpVJjD5H0y0yyAIpSdKEq556EI6yOOM= +github.com/aws/aws-sdk-go-v2/config v1.29.2 h1:JuIxOEPcSKpMB0J+khMjznG9LIhIBdmqNiEcPclnwqc= +github.com/aws/aws-sdk-go-v2/config v1.29.2/go.mod h1:HktTHregOZwNSM/e7WTfVSu9RCX+3eOv+6ij27PtaYs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.55 h1:CDhKnDEaGkLA5ZszV/qw5uwN5M8rbv9Cl0JRN+PRsaM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.55/go.mod h1:kPD/vj+RB5MREDUky376+zdnjZpR+WgdBBvwrmnlmKE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.25 h1:kU7tmXNaJ07LsyN3BUgGqAmVmQtq0w6duVIHAKfp0/w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.25/go.mod h1:OiC8+OiqrURb1wrwmr/UbOVLFSWEGxjinj5C299VQdo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.29 h1:Ej0Rf3GMv50Qh4G4852j2djtoDb7AzQ7MuQeFHa3D70= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.29/go.mod h1:oeNTC7PwJNoM5AznVr23wxhLnuJv0ZDe5v7w0wqIs9M= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.29 h1:6e8a71X+9GfghragVevC5bZqvATtc3mAMgxpSNbgzF0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.29/go.mod h1:c4jkZiQ+BWpNqq7VtrxjwISrLrt/VvPq3XiopkUIolI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 h1:SeDJWG4pmye+/aO6k+zt9clPTUy1MXqUmkW8rbAddQg= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1/go.mod h1:wRzaW0v9GGQS0h//wpsVDw3Hah5gs5UP+NxoyGeZIGM= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 h1:RhSoBFT5/8tTmIseJUXM6INTXTQDF8+0oyxWBnozIms= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0/go.mod h1:mzj8EEjIHSN2oZRXiw1Dd+uB4HZTl7hC8nBzX9IZMWw= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 h1:zg+3FGHA0PBs0KM25qE/rOf2o5zsjNa1g/Qq83+SDI0= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6/go.mod h1:ZSq54Z9SIsOTf1Efwgw1msilSs4XVEfVQiP9nYVnKpM= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.201.1 h1:HJUHMHbBg3stGO7ZZfpwbeK9xVhGS7GK8NScady6Moc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.201.1/go.mod h1:cRD0Fhzj0YD+uAh16NChQAv9/BB0S9x3YK9hLx1jb/k= +github.com/aws/aws-sdk-go-v2/service/ecr v1.38.7 h1:3fxpNAXVQV7J3dymLoQjoI5AxbrI4/FDYlfk+wPoB3s= +github.com/aws/aws-sdk-go-v2/service/ecr v1.38.7/go.mod h1:vj6+DOvmrbZgqmZvyrbMienKS3PQTHJpqa+BRBKR6Xc= 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.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= -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.68.0 h1:bFpcqdwtAEsgpZXvkTxIThFQx/EM0oV6kXmfFIGjxME= -github.com/aws/aws-sdk-go-v2/service/s3 v1.68.0/go.mod h1:ralv4XawHjEMaHOWnTFushl0WRqim/gQWesAMF6hTow= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= -github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= -github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.10 h1:hN4yJBGswmFTOVYqmbz1GBs9ZMtQe8SrYxPwrkrlRv8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.10/go.mod h1:TsxON4fEZXyrKY+D+3d2gSTyJkGORexIYab9PTf56DA= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.8 h1:KbLZjYqhQ9hyB4HwXiheiflTlYQa0+Fz0Ms/rh5f3mk= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.8/go.mod h1:ANs9kBhK4Ghj9z1W+bsr3WsNaPF71qkgd6eE6Ekol/Y= +github.com/aws/aws-sdk-go-v2/service/s3 v1.74.1 h1:9LawY3cDJ3HE+v2GMd5SOkNLDwgN4K7TsCjyVBYu/L4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.74.1/go.mod h1:hHnELVnIHltd8EOF3YzahVX6F6y2C6dNqpRj1IMkS5I= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.12 h1:kznaW4f81mNMlREkU9w3jUuJvU5g/KsqDV43ab7Rp6s= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.12/go.mod h1:bZy9r8e0/s0P7BSDHgMLXK2KvdyRRBIQ2blKlvLt0IU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.11 h1:mUwIpAvILeKFnRx4h1dEgGEFGuV8KJ3pEScZWVFYuZA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.11/go.mod h1:JDJtD+b8HNVv71axz8+S5492KM8wTzHRFpMKQbPlYxw= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.10 h1:g9d+TOsu3ac7SgmY2dUf1qMgu/uJVTlQ4VCbH6hRxSw= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.10/go.mod h1:WZfNmntu92HO44MVZAubQaz3qCuIdeOdog2sADfU6hU= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 h1:SoFYaT9UyGkR0+nogNyD/Lj+bsixB+SNuAS4ABlEs6M= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8/go.mod h1:2JF49jcDOrLStIXN/j/K1EKRq8a8R2qRnlZA6/o/c7c= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -422,8 +872,10 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= -github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= +github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= @@ -444,21 +896,22 @@ github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251 h1:k6UDF1uPY github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251/go.mod h1:gbPR1gPu9dB96mucYIR7T3B7p/78hRVSOuzIWLHK2Y4= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= -github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= -github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= 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/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= -github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk= -github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI= +github.com/cheggaaa/pb/v3 v3.1.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk= +github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -467,17 +920,23 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= -github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= +github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= @@ -486,14 +945,14 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= -github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/containerd v1.7.25 h1:khEQOAXOEJalRO228yzVsuASLH42vT7DIo9Ss+9SMFQ= +github.com/containerd/containerd v1.7.25/go.mod h1:tWfHzVI0azhw4CT2vaIjsb2CoV4LJ9PrMPaULAr21Ok= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= -github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= -github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= -github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/containerd/v2 v2.0.2 h1:GmH/tRBlTvrXOLwSpWE2vNAm8+MqI6nmxKpKBNKY8Wc= +github.com/containerd/containerd/v2 v2.0.2/go.mod h1:wIqEvQ/6cyPFUGJ5yMFanspPabMLor+bF865OHvNTTI= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -502,41 +961,42 @@ github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= -github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= -github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= -github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= -github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= -github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= -github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= +github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= +github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= +github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= +github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= +github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= -github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= -github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= +github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= +github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 h1:2Dx4IHfC1yHWI12AxQDJM1QbRCDfk6M+blLzlZCXdrc= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= -github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= -github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= @@ -554,12 +1014,12 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= -github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= +github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= -github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= +github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -572,13 +1032,15 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM= +github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/proto v1.12.1 h1:6n/Z2pZAnBwuhU66Gs8160B8rrrYKo7h2F2sCOnNceE= @@ -594,11 +1056,20 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= +github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= @@ -606,6 +1077,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= @@ -615,8 +1088,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= @@ -624,20 +1097,25 @@ github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcP github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= -github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= -github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= -github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= -github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= +github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -650,6 +1128,8 @@ github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQr github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -680,6 +1160,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-piv/piv-go v1.11.0 h1:5vAaCdRTFSIW4PeqMbnsDlUZ7odMYWnHBDGdmtU/Zhg= github.com/go-piv/piv-go v1.11.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM6fJZZM= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -703,15 +1185,16 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= github.com/goccy/go-yaml v1.9.5 h1:Eh/+3uk9kLxG4koCX6lRMAPS1OaMSAi+FJcya0INdB0= github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= -github.com/gocsaf/csaf/v3 v3.1.0 h1:XXmpMdR6OOGR2R7Av4LQpGNYQ/4IbquaYWfxsCs0Hro= -github.com/gocsaf/csaf/v3 v3.1.0/go.mod h1:3nGOg1D8A/Z7PQ69Or7J6flfT+ILsvPlMXSBKR7BZsY= +github.com/gocsaf/csaf/v3 v3.1.1 h1:g8kmqIwf8zqcMdQgaQT5UcPcyzvXxJyleT/T8Rt2OmQ= +github.com/gocsaf/csaf/v3 v3.1.1/go.mod h1:EpUCrQg69i+Y66MphmQvVbcj333GFLjXOYHg1zoXVso= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -726,14 +1209,16 @@ github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQg github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= 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/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= 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= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -761,6 +1246,7 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -774,8 +1260,9 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to= github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8= -github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -795,8 +1282,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= -github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= +github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= +github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/go-github/v55 v55.0.0 h1:4pp/1tNMB9X/LuAhs5i0KQAE40NmiR/y6prLNb9x9cg= github.com/google/go-github/v55 v55.0.0/go.mod h1:JLahOTA1DnXzhxEymmFF5PP2tSS9JVNj68mSZNDwskA= github.com/google/go-github/v62 v62.0.0 h1:/6mGCaRywZz9MuHyw9gD1CwsbmBX8GWsbFkwMmHdhl4= @@ -813,8 +1300,9 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -824,24 +1312,25 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= -github.com/google/trillian v1.6.0 h1:jMBeDBIkINFvS2n6oV5maDqfRlxREAc6CW9QYWQ0qT4= -github.com/google/trillian v1.6.0/go.mod h1:Yu3nIMITzNhhMJEHjAtp6xKiu+H/iHu2Oq5FjV2mCWI= +github.com/google/trillian v1.7.1 h1:+zX8jLM3524bAMPS+VxaDIDgsMv3/ty6DuLWerHXcek= +github.com/google/trillian v1.7.1/go.mod h1:E1UMAHqpZCA8AQdrKdWmHmtUfSeiD0sDWD1cv00Xa+c= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -851,8 +1340,10 @@ github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -862,9 +1353,12 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= -github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -877,15 +1371,17 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJr 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.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.6 h1:5jHuM+aH373XNtXl9TNTUH5Qd69Trve11tHIrB+6yj4= -github.com/hashicorp/go-getter v1.7.6/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.8 h1:mshVHx1Fto0/MydBekWan5zUipGq7jO0novchgMmSiY= +github.com/hashicorp/go-getter v1.7.8/go.mod h1:2c6CboOEb9jG6YvmC9xdD+tyAFsrUaJPedwXDGr0TM4= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -913,27 +1409,26 @@ 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.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= -github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= -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/hc-install v0.9.1 h1:gkqTfE3vVbafGQo6VZXcy2v5yoz2bE0+nhZXruCuODQ= +github.com/hashicorp/hc-install v0.9.1/go.mod h1:pWWvN/IrfeBK4XPeXXYkL6EjMufHkCK5DvwxeLKuBf0= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= -github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= -github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= -github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= -github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= -github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE= -github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE= +github.com/hashicorp/terraform-exec v0.22.0 h1:G5+4Sz6jYZfRYUCg6eQgDsqTzkNXV+fP8l+uRmZHj64= +github.com/hashicorp/terraform-exec v0.22.0/go.mod h1:bjVbsncaeh8jVdhttWYZuBGj21FcYw6Ia/XfHcNO7lQ= +github.com/hashicorp/terraform-json v0.24.0 h1:rUiyF+x1kYawXeRth6fKFm/MdfBS6+lW4NbeATsYz8Q= +github.com/hashicorp/terraform-json v0.24.0/go.mod h1:Nfj5ubo9xbu9uiAoZVBsNOjvNKB66Oyrvtit74kC7ow= +github.com/hashicorp/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= +github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU= github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -942,10 +1437,11 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= -github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE= -github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc= +github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs= @@ -961,17 +1457,23 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8= github.com/knqyf263/go-deb-version v0.0.0-20241115132648-6f4aee6ccd23 h1:dWzdsqjh1p2gNtRKqNwuBvKqMNwnLOPLzVZT1n6DK7s= @@ -983,8 +1485,11 @@ github.com/knqyf263/go-rpmdb v0.1.1/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+Y github.com/knqyf263/nested v0.0.1 h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc= github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1000,12 +1505,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6Fm github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 h1:WGrKdjHtWC67RX96eTkYD2f53NDHhrq/7robWTAfk4s= -github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491/go.mod h1:o158RFmdEbYyIZmXAbrvmJWesbyxlLKee6X64VPVuOc= -github.com/liamg/iamgo v0.0.9 h1:tADGm3xVotyRJmuKKaH4+zsBn7LOcvgdpuF3WsSKW3c= -github.com/liamg/iamgo v0.0.9/go.mod h1:Kk6ZxBF/GQqG9nnaUjIi6jf+WXNpeOTyhwc6gnguaZQ= -github.com/liamg/jfather v0.0.7 h1:Xf78zS263yfT+xr2VSo6+kyAy4ROlCacRqJG7s5jt4k= -github.com/liamg/jfather v0.0.7/go.mod h1:xXBGiBoiZ6tmHhfy5Jzw8sugzajwYdi6VosIpB3/cPM= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/liamg/memoryfs v1.6.0 h1:jAFec2HI1PgMTem5gR7UT8zi9u4BfG5jorCRlLH06W8= github.com/liamg/memoryfs v1.6.0/go.mod h1:z7mfqXFQS8eSeBBsFjYLlxYRMRyiPktytvYCYTb3BSk= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -1017,10 +1518,13 @@ github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNe github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee h1:cgm8mE25x5XXX2oyvJDlyJ72K+rDu/4ZCYce2worNb8= @@ -1039,9 +1543,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= @@ -1050,19 +1553,23 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032 h1:TLygBUBxikNJJfLwgm+Qwdgq1FtfV8Uh7bcxRyTzK8s= github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032/go.mod h1:vYT9HE7WCvL64iVeZylKmCsWKfE+JZ8105iuh2Trk8g= -github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= -github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= +github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -1078,16 +1585,16 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= -github.com/moby/buildkit v0.17.2 h1:/jgk/MuXbA7jeXMkknOpHYB+Ct4aNvQHkBB7SxD3D4U= -github.com/moby/buildkit v0.17.2/go.mod h1:vr5vltV8wt4F2jThbNOChfbAklJ0DOW11w36v210hOg= +github.com/moby/buildkit v0.18.2 h1:l86uBvxh4ntNoUUg3Y0eGTbKg1PbUh6tawJ4Xt75SpQ= +github.com/moby/buildkit v0.18.2/go.mod h1:vCR5CX8NGsPTthTg681+9kdmfvkvqJBXEv71GZe5msU= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -1124,8 +1631,9 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE= github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481/go.mod h1:yKZQO8QE2bHlgozqWDiRVqTFlLQSj30K/6SAK8EeYFw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oleiade/reflections v1.0.1 h1:D1XO3LVEYroYskEsoSiGItp9RUxG6jWnCVvrqH0HHQM= @@ -1136,16 +1644,16 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/open-policy-agent/opa v0.70.0 h1:B3cqCN2iQAyKxK6+GI+N40uqkin+wzIrM7YA60t9x1U= -github.com/open-policy-agent/opa v0.70.0/go.mod h1:Y/nm5NY0BX0BqjBriKUiV81sCl8XOjjvqQG7dXrggtI= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-policy-agent/opa v1.1.0 h1:HMz2evdEMTyNqtdLjmu3Vyx06BmhNYAx67Yz3Ll9q2s= +github.com/open-policy-agent/opa v1.1.0/go.mod h1:T1pASQ1/vwfTa+e2fYcfpLCvWgYtqtiUv+IuA/dLPQs= 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= @@ -1167,8 +1675,8 @@ github.com/openvex/go-vex v0.2.5/go.mod h1:j+oadBxSUELkrKh4NfNb+BPo77U3q7gdKME88 github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= github.com/owenrumney/go-sarif/v2 v2.3.3 h1:ubWDJcF5i3L/EIOER+ZyQ03IfplbSU1BLOE26uKQIIU= github.com/owenrumney/go-sarif/v2 v2.3.3/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w= -github.com/owenrumney/squealer v1.2.5 h1:zxaDuYTTwqyOlh6koqE57SZ1TdKX06Khu3HSofFMi7M= -github.com/owenrumney/squealer v1.2.5/go.mod h1:lTHxnEfjl8y3QIQpoawfl/Bpe9A7SYKptgKSNtzkHOw= +github.com/owenrumney/squealer v1.2.6 h1:oxqhVqB99kZXAHLpKbpIMevxLgF1/Ihx3DTbO+9312w= +github.com/owenrumney/squealer v1.2.6/go.mod h1:k57s5gAGAWLhDmHLUDfycLx50cuviLC0CxBYxVep4yA= github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs= github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= @@ -1179,13 +1687,21 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1204,12 +1720,14 @@ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/j github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= +github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1221,30 +1739,35 @@ github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= -github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= +github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4= +github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= +github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= -github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= +github.com/samber/lo v1.49.0 h1:AGnTnQrg1jpFuwECPUSoxZCfVH5W22b605kWSry3YxM= +github.com/samber/lo v1.49.0/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= @@ -1253,8 +1776,8 @@ github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGq github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= -github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= -github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= +github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc= +github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -1276,18 +1799,18 @@ github.com/sigstore/cosign/v2 v2.2.4 h1:iY4vtEacmu2hkNj1Fh+8EBqBwKs2DHM27/lbNWDF github.com/sigstore/cosign/v2 v2.2.4/go.mod h1:JZlRD2uaEjVAvZ1XJ3QkkZJhTqSDVtLaet+C/TMR81Y= github.com/sigstore/fulcio v1.4.5 h1:WWNnrOknD0DbruuZWCbN+86WRROpEl3Xts+WT2Ek1yc= github.com/sigstore/fulcio v1.4.5/go.mod h1:oz3Qwlma8dWcSS/IENR/6SjbW4ipN0cxpRVfgdsjMU8= -github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8= -github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc= -github.com/sigstore/sigstore v1.8.3 h1:G7LVXqL+ekgYtYdksBks9B38dPoIsbscjQJX/MGWkA4= -github.com/sigstore/sigstore v1.8.3/go.mod h1:mqbTEariiGA94cn6G3xnDiV6BD8eSLdL/eA7bvJ0fVs= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3 h1:LTfPadUAo+PDRUbbdqbeSl2OuoFQwUFTnJ4stu+nwWw= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3/go.mod h1:QV/Lxlxm0POyhfyBtIbTWxNeF18clMlkkyL9mu45y18= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3 h1:xgbPRCr2npmmsuVVteJqi/ERw9+I13Wou7kq0Yk4D8g= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3/go.mod h1:G4+I83FILPX6MtnoaUdmv/bRGEVtR3JdLeJa/kXdk/0= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3 h1:vDl2fqPT0h3D/k6NZPlqnKFd1tz3335wm39qjvpZNJc= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3/go.mod h1:9uOJXbXEXj+M6QjMKH5PaL5WDMu43rHfbIMgXzA8eKI= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3 h1:h9G8j+Ds21zqqulDbA/R/ft64oQQIyp8S7wJYABYSlg= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3/go.mod h1:zgCeHOuqF6k7A7TTEvftcA9V3FRzB7mrPtHOhXAQBnc= +github.com/sigstore/rekor v1.3.8 h1:B8kJI8mpSIXova4Jxa6vXdJyysRxFGsEsLKBDl0rRjA= +github.com/sigstore/rekor v1.3.8/go.mod h1:/dHFYKSuxEygfDRnEwyJ+ZD6qoVYNXQdi1mJrKvKWsI= +github.com/sigstore/sigstore v1.8.12 h1:S8xMVZbE2z9ZBuQUEG737pxdLjnbOIcFi5v9UFfkJFc= +github.com/sigstore/sigstore v1.8.12/go.mod h1:+PYQAa8rfw0QdPpBcT+Gl3egKD9c+TUgAlF12H3Nmjo= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.12 h1:EC3UmIaa7nV9sCgSpVevmvgvTYTkMqyrRbj5ojPp7tE= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.12/go.mod h1:aw60vs3crnQdM/DYH+yF2P0MVKtItwAX34nuaMrY7Lk= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.12 h1:FPpliDTywSy0woLHMAdmTSZ5IS/lVBZ0dY0I+2HmnSY= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.12/go.mod h1:NkPiz4XA0JcBSXzJUrjMj7Xi7oSTew1Ip3Zmt56mHlw= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.12 h1:kweBChR6M9FEvmxN3BMEcl7SNnwxTwKF7THYFKLOE5U= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.12/go.mod h1:6+d+A6oYt1W5OgtzgEVb21V7tAZ/C2Ihtzc5MNJbayY= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.12 h1:jvY1B9bjP+tKzdKDyuq5K7O19CG2IKzGJNTy5tuL2Gs= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.12/go.mod h1:2uEeOb8xE2RC6OvzxKux1wkS39Zv8gA27z92m49xUTc= github.com/sigstore/timestamp-authority v1.2.2 h1:X4qyutnCQqJ0apMewFyx+3t7Tws00JQ/JonBiu3QvLE= github.com/sigstore/timestamp-authority v1.2.2/go.mod h1:nEah4Eq4wpliDjlY342rXclGSO7Kb9hoRrl9tqLW13A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1295,8 +1818,8 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= -github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/sosedoff/gitkit v0.4.0 h1:opyQJ/h9xMRLsz2ca/2CRXtstePcpldiZN8DpLLF8Os= @@ -1307,10 +1830,13 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk= github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= -github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -1336,6 +1862,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -1346,16 +1873,16 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtse github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= -github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= -github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= -github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= -github.com/testcontainers/testcontainers-go v0.34.0/go.mod h1:6P/kMkQe8yqPHfPWNulFGdFHTD8HB2vLq/231xY2iPQ= -github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0 h1:WkjVmea0XQyGTY10Er8fOsVjHQ77iJCmTExnx6fC3Tw= -github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0/go.mod h1:rTo76O/BBeAtfazMQqLvfwBrntBBwDP7/+Z60dm3e9U= -github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= -github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= +github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM= +github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= +github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo= +github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= +github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo= +github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4= +github.com/testcontainers/testcontainers-go/modules/localstack v0.35.0 h1:0EbOXcy8XQkyDUs1Y9YPUHOUByNnlGsLi5B3ln8F/RU= +github.com/testcontainers/testcontainers-go/modules/localstack v0.35.0/go.mod h1:MlHuaWQimz+15dmQ6R2S1vpYxhGFEpmRZQsL2NVWNng= +github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4= +github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= @@ -1382,8 +1909,8 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= +github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= +github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= @@ -1414,6 +1941,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= @@ -1428,14 +1956,16 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= -github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70= +github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= @@ -1450,31 +1980,37 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/detectors/gcp v1.32.0 h1:P78qWqkLSShicHmAzfECaTgvslqHxblNE9j62Ws1NK8= +go.opentelemetry.io/contrib/detectors/gcp v1.32.0/go.mod h1:TVqo0Sda4Cv8gCIixd7LuLwW4EylumVWfhjZJjDD4DU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -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= -go.step.sm/crypto v0.44.2/go.mod h1:x1439EnFhadzhkuaGX7sz03LEMQ+jV4gRamf5LCZJQQ= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.step.sm/crypto v0.56.0 h1:KcFfV76cI9Xaw8bdSc9x55skyuSdcHcTdL37vvVZnvY= +go.step.sm/crypto v0.56.0/go.mod h1:snWNloxY9s1W+HsFqcviq55nvzbqqX6LxVt0Vktv5mw= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -1485,31 +2021,52 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1533,10 +2090,16 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.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.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1573,12 +2136,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1590,15 +2156,22 @@ golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1622,10 +2195,14 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1639,12 +2216,14 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.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= @@ -1695,11 +2274,14 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1707,8 +2289,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1727,28 +2312,40 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 h1:FemxDzfMUcK2f3YY4H+05K9CDzbSVr2+q/JKN45pey0= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1758,20 +2355,30 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1784,6 +2391,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1813,25 +2421,31 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= -golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= -golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= +golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1840,8 +2454,16 @@ golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1889,9 +2511,18 @@ google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaE google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= -google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.216.0 h1:xnEHy+xWFrtYInWPy8OdGFsyIfWJjtVnO39g7pz2BFY= +google.golang.org/api v0.216.0/go.mod h1:K9wzQMvWi47Z9IU7OgdOofvZuw75Ge3PPITImZR/UyI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1934,7 +2565,9 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1967,6 +2600,7 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= @@ -1999,13 +2633,41 @@ google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53B google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -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-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= 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= @@ -2032,6 +2694,7 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= @@ -2041,8 +2704,13 @@ 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.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= 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= @@ -2059,8 +2727,11 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2074,8 +2745,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -2099,8 +2768,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.16.3 h1:kb8bSxMeRJ+knsK/ovvlaVPfdis0X3/ZhYCSFRP+YmY= -helm.sh/helm/v3 v3.16.3/go.mod h1:zeVWGDR4JJgiRbT3AnNsjYaX8OTJlIE9zC+Q7F7iUSU= +helm.sh/helm/v3 v3.17.0 h1:DUD4AGdNVn7PSTYfxe1gmQG7s18QeWv/4jI9TubnhT0= +helm.sh/helm/v3 v3.17.0/go.mod h1:Mo7eGyKPPHlS0Ml67W8z/lbkox/gD9Xt1XpD6bxvZZA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2108,71 +2777,104 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= -k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= -k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= -k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= -k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/apiserver v0.31.2 h1:VUzOEUGRCDi6kX1OyQ801m4A7AUPglpsmGvdsekmcI4= -k8s.io/apiserver v0.31.2/go.mod h1:o3nKZR7lPlJqkU5I3Ove+Zx3JuoFjQobGX1Gctw6XuE= -k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ= -k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= -k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA= -k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= +k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= +k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= +k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= +k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= +k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs= +k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag= +k8s.io/cli-runtime v0.32.1 h1:19nwZPlYGJPUDbhAxDIS2/oydCikvKMHsxroKNGA2mM= +k8s.io/cli-runtime v0.32.1/go.mod h1:NJPbeadVFnV2E7B7vF+FvU09mpwYlZCu8PqjzfuOnkY= +k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= +k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= +k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk= +k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M= -k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kubectl v0.32.1 h1:/btLtXLQUU1rWx8AEvX9jrb9LaI6yeezt3sFALhB8M8= +k8s.io/kubectl v0.32.1/go.mod h1:sezNuyWi1STk4ZNPVRIFfgjqMI6XMf+oCVLjZen/pFQ= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk= -modernc.org/sqlite v1.34.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g= +modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= -sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= -sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= -sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= -sigs.k8s.io/release-utils v0.7.7 h1:JKDOvhCk6zW8ipEOkpTGDH/mW3TI+XqtPp16aaQ79FU= -sigs.k8s.io/release-utils v0.7.7/go.mod h1:iU7DGVNi3umZJ8q6aHyUFzsDUIaYwNnNKGHo3YE5E3s= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= +sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= +sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= +sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= +sigs.k8s.io/release-utils v0.8.4 h1:4QVr3UgbyY/d9p74LBhg0njSVQofUsAZqYOzVZBhdBw= +sigs.k8s.io/release-utils v0.8.4/go.mod h1:m1bHfscTemQp+z+pLCZnkXih9n0+WukIUU70n6nFnU0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= diff --git a/goreleaser-canary.yml b/goreleaser-canary.yml index b49abde49d34..ed360afbdd8d 100644 --- a/goreleaser-canary.yml +++ b/goreleaser-canary.yml @@ -3,7 +3,7 @@ version: 2 project_name: trivy_canary_build builds: - - main: cmd/trivy/main.go + main: ./cmd/trivy/ binary: trivy ldflags: - -s -w diff --git a/helm/trivy/Chart.yaml b/helm/trivy/Chart.yaml index 70da66749c7d..e2cf46ff51d0 100644 --- a/helm/trivy/Chart.yaml +++ b/helm/trivy/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: trivy -version: 0.9.0 -appVersion: 0.57.1 +version: 0.10.1 +appVersion: 0.58.1 description: Trivy helm chart keywords: - scanner diff --git a/integration/client_server_test.go b/integration/client_server_test.go index 0df09c6ae051..6a9dda6a59f3 100644 --- a/integration/client_server_test.go +++ b/integration/client_server_test.go @@ -36,6 +36,7 @@ type csArgs struct { ListAllPackages bool Target string secretConfig string + Distro string } func TestClientServer(t *testing.T) { @@ -52,6 +53,18 @@ func TestClientServer(t *testing.T) { }, golden: "testdata/alpine-39.json.golden", }, + { + name: "alpine 3.9 as alpine 3.10", + args: csArgs{ + Input: "testdata/fixtures/images/alpine-39.tar.gz", + Distro: "alpine/3.10", + }, + override: func(t *testing.T, want, got *types.Report) { + want.Metadata.OS.Name = "3.10" + want.Results[0].Target = "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.10)" + }, + golden: "testdata/alpine-39.json.golden", + }, { name: "alpine 3.9 with high and critical severity", args: csArgs{ @@ -684,6 +697,10 @@ func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string osArgs = append(osArgs, c.Target) } + if c.Distro != "" { + osArgs = append(osArgs, "--distro", c.Distro) + } + return osArgs } diff --git a/integration/docker_engine_test.go b/integration/docker_engine_test.go index a543d22e466f..cd9b3fee6b75 100644 --- a/integration/docker_engine_test.go +++ b/integration/docker_engine_test.go @@ -25,6 +25,7 @@ func TestDockerEngine(t *testing.T) { ignoreStatus []string severity []string ignoreIDs []string + maxImageSize string input string golden string wantErr string @@ -34,6 +35,12 @@ func TestDockerEngine(t *testing.T) { input: "testdata/fixtures/images/alpine-39.tar.gz", golden: "testdata/alpine-39.json.golden", }, + { + name: "alpine:3.9, with max image size", + maxImageSize: "100mb", + input: "testdata/fixtures/images/alpine-39.tar.gz", + golden: "testdata/alpine-39.json.golden", + }, { name: "alpine:3.9, with high and critical severity", severity: []string{ @@ -195,6 +202,12 @@ func TestDockerEngine(t *testing.T) { input: "badimage:latest", wantErr: "unable to inspect the image (badimage:latest)", }, + { + name: "sad path, image size is larger than the maximum", + input: "testdata/fixtures/images/alpine-39.tar.gz", + maxImageSize: "3mb", + wantErr: "uncompressed layers size 5.8MB exceeds maximum allowed size 3MB", + }, } // Set up testing DB @@ -263,6 +276,11 @@ func TestDockerEngine(t *testing.T) { require.NoError(t, err, "failed to write .trivyignore") defer os.Remove(trivyIgnore) } + + if tt.maxImageSize != "" { + osArgs = append(osArgs, []string{"--max-image-size", tt.maxImageSize}...) + } + osArgs = append(osArgs, tt.input) // Run Trivy diff --git a/integration/k8s_test.go b/integration/k8s_test.go index 498f667932c4..109c4b7b2a82 100644 --- a/integration/k8s_test.go +++ b/integration/k8s_test.go @@ -106,4 +106,55 @@ func TestK8s(t *testing.T) { return len(*r.Dependencies) > 0 })) }) + + t.Run("limited user test", func(t *testing.T) { + // Set up the output file + outputFile := filepath.Join(t.TempDir(), "output.json") + + osArgs := []string{ + "--cache-dir", + cacheDir, + "k8s", + "limitedcontext", + "--kubeconfig", "limitedconfig", + "--report", + "summary", + "-q", + "--timeout", + "5m0s", + "--include-namespaces", "limitedns", + "--format", + "json", + "--output", + outputFile, + } + + // Run Trivy + err := execute(osArgs) + require.NoError(t, err) + + var got report.ConsolidatedReport + f, err := os.Open(outputFile) + require.NoError(t, err) + defer f.Close() + + err = json.NewDecoder(f).Decode(&got) + require.NoError(t, err) + + // Flatten findings + results := lo.FlatMap(got.Findings, func(resource report.Resource, _ int) []types.Result { + return resource.Results + }) + + // Has vulnerabilities + assert.True(t, lo.SomeBy(results, func(r types.Result) bool { + return len(r.Vulnerabilities) > 0 + })) + + // Has misconfigurations + assert.True(t, lo.SomeBy(results, func(r types.Result) bool { + return len(r.Misconfigurations) > 0 + })) + + }) } diff --git a/integration/repo_test.go b/integration/repo_test.go index 87c27684d3ab..365056a83fb0 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -16,6 +16,7 @@ import ( // TestRepository tests `trivy repo` with the local code repositories func TestRepository(t *testing.T) { + t.Setenv("NUGET_PACKAGES", t.TempDir()) type args struct { scanner types.Scanner ignoreIDs []string @@ -158,6 +159,15 @@ func TestRepository(t *testing.T) { }, golden: "testdata/poetry.json.golden", }, + { + name: "uv", + args: args{ + scanner: types.VulnerabilityScanner, + listAllPkgs: true, + input: "testdata/fixtures/repo/uv", + }, + golden: "testdata/uv.json.golden", + }, { name: "pom", args: args{ diff --git a/integration/sbom_test.go b/integration/sbom_test.go index e887f1520e68..1bc41f58639b 100644 --- a/integration/sbom_test.go +++ b/integration/sbom_test.go @@ -186,11 +186,6 @@ func overrideSBOMReport(t *testing.T, want, got *types.Report) { want.Metadata.ImageID = "" want.Metadata.ImageConfig = v1.ConfigFile{} want.Metadata.DiffIDs = nil - for i, result := range want.Results { - for j := range result.Vulnerabilities { - want.Results[i].Vulnerabilities[j].Layer.DiffID = "" - } - } // when running on Windows FS got.ArtifactName = filepath.ToSlash(filepath.Clean(got.ArtifactName)) diff --git a/integration/standalone_tar_test.go b/integration/standalone_tar_test.go index 039293cbfd56..4a0027e7743a 100644 --- a/integration/standalone_tar_test.go +++ b/integration/standalone_tar_test.go @@ -24,11 +24,13 @@ func TestTar(t *testing.T) { SkipDirs []string SkipFiles []string DetectionPriority ftypes.DetectionPriority + Distro string } tests := []struct { - name string - args args - golden string + name string + args args + golden string + override func(t *testing.T, want, got *types.Report) }{ { name: "alpine 3.9", @@ -159,6 +161,19 @@ func TestTar(t *testing.T) { }, golden: "testdata/alpine-39-ignore-cveids.json.golden", }, + { + name: "alpine 3.9 as alpine 3.10", + args: args{ + Format: types.FormatJSON, + Input: "testdata/fixtures/images/alpine-39.tar.gz", + Distro: "alpine/3.10", + }, + override: func(t *testing.T, want, got *types.Report) { + want.Metadata.OS.Name = "3.10" + want.Results[0].Target = "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.10)" + }, + golden: "testdata/alpine-39.json.golden", + }, { name: "alpine 3.10", args: args{ @@ -345,7 +360,7 @@ func TestTar(t *testing.T) { name: "sle micro rancher 5.4", args: args{ Format: types.FormatJSON, - Input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + Input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", }, golden: "testdata/sl-micro-rancher5.4.json.golden", }, @@ -434,8 +449,14 @@ func TestTar(t *testing.T) { osArgs = append(osArgs, "--detection-priority", string(tt.args.DetectionPriority)) } + if tt.args.Distro != "" { + osArgs = append(osArgs, "--distro", tt.args.Distro) + } + // Run Trivy - runTest(t, osArgs, tt.golden, "", tt.args.Format, runOptions{}) + runTest(t, osArgs, tt.golden, "", tt.args.Format, runOptions{ + override: overrideFuncs(overrideUID, tt.override), + }) }) } } diff --git a/integration/testdata/conda-cyclonedx.json.golden b/integration/testdata/conda-cyclonedx.json.golden index df8f575e9053..90499f2a1fd0 100644 --- a/integration/testdata/conda-cyclonedx.json.golden +++ b/integration/testdata/conda-cyclonedx.json.golden @@ -2,7 +2,7 @@ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000004", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000005", "version": 1, "metadata": { "timestamp": "2021-08-25T12:20:30+00:00", @@ -17,7 +17,7 @@ ] }, "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", "type": "application", "name": "testdata/fixtures/repo/conda", "properties": [ @@ -92,7 +92,7 @@ ], "dependencies": [ { - "ref": "3ff14136-e09f-4df9-80ea-000000000001", + "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ "pkg:conda/openssl@1.1.1q", "pkg:conda/pip@22.2.2" diff --git a/integration/testdata/conda-environment-cyclonedx.json.golden b/integration/testdata/conda-environment-cyclonedx.json.golden index 7062e1e1a356..4989a923bf72 100644 --- a/integration/testdata/conda-environment-cyclonedx.json.golden +++ b/integration/testdata/conda-environment-cyclonedx.json.golden @@ -2,7 +2,7 @@ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000004", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000005", "version": 1, "metadata": { "timestamp": "2021-08-25T12:20:30+00:00", @@ -17,7 +17,7 @@ ] }, "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", "type": "application", "name": "testdata/fixtures/repo/conda-environment", "properties": [ @@ -30,7 +30,7 @@ }, "components": [ { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000003", "type": "application", "name": "environment.yaml", "properties": [ @@ -60,13 +60,13 @@ ], "dependencies": [ { - "ref": "3ff14136-e09f-4df9-80ea-000000000001", + "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ - "3ff14136-e09f-4df9-80ea-000000000002" + "3ff14136-e09f-4df9-80ea-000000000003" ] }, { - "ref": "3ff14136-e09f-4df9-80ea-000000000002", + "ref": "3ff14136-e09f-4df9-80ea-000000000003", "dependsOn": [ "pkg:conda/bzip2@1.0.8" ] diff --git a/integration/testdata/fixtures/db/oracle.yaml b/integration/testdata/fixtures/db/oracle.yaml index 8418edcfd6cb..88745d05b23d 100644 --- a/integration/testdata/fixtures/db/oracle.yaml +++ b/integration/testdata/fixtures/db/oracle.yaml @@ -7,8 +7,14 @@ FixedVersion: "7.61.1-11.el8" Entries: - FixedVersion: "7.61.1-11.el8" + Arches: + - x86_64 + - aarch64 - key: CVE-2019-5436 value: FixedVersion: "7.61.1-12.el8" Entries: - FixedVersion: "7.61.1-12.el8" + Arches: + - x86_64 + - aarch64 diff --git a/integration/testdata/fixtures/k8s/kube-config-template b/integration/testdata/fixtures/k8s/kube-config-template new file mode 100644 index 000000000000..90b8b082e579 --- /dev/null +++ b/integration/testdata/fixtures/k8s/kube-config-template @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: {{CA}} + server: {{URL}} + name: kind-kind-test +contexts: +- context: + cluster: kind-kind-test + namespace: limitedns + user: limiteduser + name: limitedcontext +kind: Config +preferences: {} +users: +- name: limiteduser + user: + token: {{TOKEN}} \ No newline at end of file diff --git a/integration/testdata/fixtures/k8s/limited-binding.yaml b/integration/testdata/fixtures/k8s/limited-binding.yaml new file mode 100644 index 000000000000..6844922417be --- /dev/null +++ b/integration/testdata/fixtures/k8s/limited-binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: limited-binding + namespace: limitedns + +subjects: +- kind: ServiceAccount + name: limiteduser + namespace: default + +roleRef: + kind: Role + name: limited-role + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/integration/testdata/fixtures/k8s/limited-pod.yaml b/integration/testdata/fixtures/k8s/limited-pod.yaml new file mode 100644 index 000000000000..a4968e7fae84 --- /dev/null +++ b/integration/testdata/fixtures/k8s/limited-pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: limited-pod + namespace: limitedns +spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/integration/testdata/fixtures/k8s/limited-role.yaml b/integration/testdata/fixtures/k8s/limited-role.yaml new file mode 100644 index 000000000000..31dff1fb1f26 --- /dev/null +++ b/integration/testdata/fixtures/k8s/limited-role.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: limited-role + namespace: limitedns +rules: +- apiGroups: [""] + resources: ["*"] + verbs: ["list"] +- apiGroups: ["apps", "batch", "networking.k8s.io","rbac.authorization.k8s.io"] + resources: ["*"] + verbs: ["list"] diff --git a/integration/testdata/fixtures/repo/uv/uv.lock b/integration/testdata/fixtures/repo/uv/uv.lock new file mode 100644 index 000000000000..e16e05558ffb --- /dev/null +++ b/integration/testdata/fixtures/repo/uv/uv.lock @@ -0,0 +1,51 @@ +version = 1 +requires-python = ">=3.11" +resolution-markers = [ + "python_full_version < '3.12'", + "python_full_version >= '3.12'", +] + +[[package]] +name = "click" +version = "8.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", size = 331147 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48", size = 96588 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "uv-test" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "click" }, + { name = "werkzeug" }, +] + +[package.metadata] +requires-dist = [ + { name = "click", specifier = "==8.1.3" }, + { name = "werkzeug", specifier = "==0.11.1" }, +] + +[[package]] +name = "werkzeug" +version = "0.11.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/b4/824c916f1451164bd871ad062defa2f48a34e2e952b12c0422f3ecf3a531/Werkzeug-0.11.1.tar.gz", hash = "sha256:280b37866a1fa8604549cbc278f06d310143e20f1a6520ae5cf66e0df615e0a7", size = 1151713 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/37/398042f9b852c57f7e9b4e1173dcd40e7b9980d9c76a700647c458f582b1/Werkzeug-0.11.1-py2.py3-none-any.whl", hash = "sha256:bca5d6a06e4603abd0d2c10bb5ce523039bf16a0a7b8320bd74f6458d20d4c3b", size = 304783 }, +] diff --git a/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden b/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden index 496ca8ae3110..259715928e0f 100644 --- a/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden +++ b/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden @@ -80,6 +80,14 @@ "version": "5.0-4", "purl": "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:831c5620387fb9efec59fc82a42b948546c6be601e3ab34a87108ecf852aa15f" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:000eee12ec04cc914bf96e8f5dee7767510c2aca3816af6078bd9fbe3150920c" + }, { "name": "aquasecurity:trivy:PkgID", "value": "bash@5.0-4" @@ -105,6 +113,14 @@ "version": "2.0.5-1", "purl": "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2", "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:831c5620387fb9efec59fc82a42b948546c6be601e3ab34a87108ecf852aa15f" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:000eee12ec04cc914bf96e8f5dee7767510c2aca3816af6078bd9fbe3150920c" + }, { "name": "aquasecurity:trivy:PkgID", "value": "libidn2-0@2.0.5-1" @@ -141,6 +157,14 @@ "name": "aquasecurity:trivy:FilePath", "value": "var/lib/gems/2.5.0/specifications/activesupport-6.0.2.1.gemspec" }, + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:75e43d55939745950bc3f8fad56c5834617c4339f0f54755e69a0dd5372624e9" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:a8877cad19f14a7044524a145ce33170085441a7922458017db1631dcd5f7602" + }, { "name": "aquasecurity:trivy:PkgID", "value": "activesupport@6.0.2.1" diff --git a/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden b/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden index 3afc57682556..1da5298a7398 100644 --- a/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden +++ b/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden @@ -76,6 +76,9 @@ { "bom-ref": "pkg:deb/debian/adduser@3.118?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Adduser Developers " + }, "name": "adduser", "version": "3.118", "licenses": [ @@ -111,14 +114,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.118" } - ], - "supplier": { - "name": "Debian Adduser Developers " - } + ] }, { "bom-ref": "pkg:deb/debian/apt@1.8.2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "APT Development Team " + }, "name": "apt", "version": "1.8.2", "licenses": [ @@ -159,14 +162,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.8.2" } - ], - "supplier": { - "name": "APT Development Team " - } + ] }, { "bom-ref": "pkg:deb/debian/base-files@10.3%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Santiago Vila " + }, "name": "base-files", "version": "10.3+deb10u2", "licenses": [ @@ -202,14 +205,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "10.3+deb10u2" } - ], - "supplier": { - "name": "Santiago Vila " - } + ] }, { "bom-ref": "pkg:deb/debian/base-passwd@3.5.46?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Colin Watson " + }, "name": "base-passwd", "version": "3.5.46", "licenses": [ @@ -250,14 +253,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.5.46" } - ], - "supplier": { - "name": "Colin Watson " - } + ] }, { "bom-ref": "pkg:deb/debian/bash@5.0-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Matthias Klose " + }, "name": "bash", "version": "5.0-4", "licenses": [ @@ -297,14 +300,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.0" } - ], - "supplier": { - "name": "Matthias Klose " - } + ] }, { "bom-ref": "pkg:deb/debian/bsdutils@2.33.1-0.1?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "bsdutils", "version": "1:2.33.1-0.1", "licenses": [ @@ -414,14 +417,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/ca-certificates@20190110?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Michael Shuler " + }, "name": "ca-certificates", "version": "20190110", "licenses": [ @@ -467,14 +470,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "20190110" } - ], - "supplier": { - "name": "Michael Shuler " - } + ] }, { "bom-ref": "pkg:deb/debian/coreutils@8.30-3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Michael Stone " + }, "name": "coreutils", "version": "8.30-3", "licenses": [ @@ -514,14 +517,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "8.30" } - ], - "supplier": { - "name": "Michael Stone " - } + ] }, { "bom-ref": "pkg:deb/debian/dash@0.5.10.2-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Andrej Shadura " + }, "name": "dash", "version": "0.5.10.2-5", "licenses": [ @@ -561,14 +564,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.5.10.2" } - ], - "supplier": { - "name": "Andrej Shadura " - } + ] }, { "bom-ref": "pkg:deb/debian/debconf@1.5.71?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debconf Developers " + }, "name": "debconf", "version": "1.5.71", "licenses": [ @@ -604,14 +607,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.5.71" } - ], - "supplier": { - "name": "Debconf Developers " - } + ] }, { "bom-ref": "pkg:deb/debian/debian-archive-keyring@2019.1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Release Team " + }, "name": "debian-archive-keyring", "version": "2019.1", "licenses": [ @@ -647,14 +650,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2019.1" } - ], - "supplier": { - "name": "Debian Release Team " - } + ] }, { "bom-ref": "pkg:deb/debian/debianutils@4.8.6.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Clint Adams " + }, "name": "debianutils", "version": "4.8.6.1", "licenses": [ @@ -690,14 +693,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.8.6.1" } - ], - "supplier": { - "name": "Clint Adams " - } + ] }, { "bom-ref": "pkg:deb/debian/diffutils@3.7-3?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Santiago Vila " + }, "name": "diffutils", "version": "1:3.7-3", "licenses": [ @@ -746,14 +749,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.7" } - ], - "supplier": { - "name": "Santiago Vila " - } + ] }, { "bom-ref": "pkg:deb/debian/dpkg@1.19.7?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Dpkg Developers " + }, "name": "dpkg", "version": "1.19.7", "licenses": [ @@ -809,14 +812,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.19.7" } - ], - "supplier": { - "name": "Dpkg Developers " - } + ] }, { "bom-ref": "pkg:deb/debian/e2fsprogs@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Theodore Y. Ts'o " + }, "name": "e2fsprogs", "version": "1.44.5-1+deb10u2", "licenses": [ @@ -861,14 +864,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.44.5" } - ], - "supplier": { - "name": "Theodore Y. Ts'o " - } + ] }, { "bom-ref": "pkg:deb/debian/fdisk@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "fdisk", "version": "2.33.1-0.1", "licenses": [ @@ -978,14 +981,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/findutils@4.6.0%2Bgit%2B20190209-2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Andreas Metzler " + }, "name": "findutils", "version": "4.6.0+git+20190209-2", "licenses": [ @@ -1030,14 +1033,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.6.0+git+20190209" } - ], - "supplier": { - "name": "Andreas Metzler " - } + ] }, { "bom-ref": "pkg:deb/debian/gcc-8-base@8.3.0-6?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GCC Maintainers " + }, "name": "gcc-8-base", "version": "8.3.0-6", "licenses": [ @@ -1102,14 +1105,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "8.3.0" } - ], - "supplier": { - "name": "Debian GCC Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/gpgv@2.2.12-1%2Bdeb10u1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuPG Maintainers " + }, "name": "gpgv", "version": "2.2.12-1+deb10u1", "licenses": [ @@ -1204,14 +1207,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.2.12" } - ], - "supplier": { - "name": "Debian GnuPG Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/grep@3.3-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Anibal Monsalve Salazar " + }, "name": "grep", "version": "3.3-1", "licenses": [ @@ -1256,14 +1259,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.3" } - ], - "supplier": { - "name": "Anibal Monsalve Salazar " - } + ] }, { "bom-ref": "pkg:deb/debian/gzip@1.9-3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Bdale Garbee " + }, "name": "gzip", "version": "1.9-3", "licenses": [ @@ -1303,14 +1306,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.9" } - ], - "supplier": { - "name": "Bdale Garbee " - } + ] }, { "bom-ref": "pkg:deb/debian/hostname@3.21?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Michael Meskes " + }, "name": "hostname", "version": "3.21", "licenses": [ @@ -1346,14 +1349,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.21" } - ], - "supplier": { - "name": "Michael Meskes " - } + ] }, { "bom-ref": "pkg:deb/debian/init-system-helpers@1.56%2Bnmu1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian systemd Maintainers " + }, "name": "init-system-helpers", "version": "1.56+nmu1", "licenses": [ @@ -1399,14 +1402,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.56+nmu1" } - ], - "supplier": { - "name": "Debian systemd Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libacl1@2.2.53-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Guillem Jover " + }, "name": "libacl1", "version": "2.2.53-4", "licenses": [ @@ -1461,14 +1464,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.2.53" } - ], - "supplier": { - "name": "Guillem Jover " - } + ] }, { "bom-ref": "pkg:deb/debian/libapt-pkg5.0@1.8.2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "APT Development Team " + }, "name": "libapt-pkg5.0", "version": "1.8.2", "licenses": [ @@ -1509,14 +1512,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.8.2" } - ], - "supplier": { - "name": "APT Development Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libattr1@2.4.48-4?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Guillem Jover " + }, "name": "libattr1", "version": "1:2.4.48-4", "licenses": [ @@ -1575,14 +1578,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.4.48" } - ], - "supplier": { - "name": "Guillem Jover " - } + ] }, { "bom-ref": "pkg:deb/debian/libaudit-common@2.8.4-3?arch=all&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Laurent Bigonville " + }, "name": "libaudit-common", "version": "1:2.8.4-3", "licenses": [ @@ -1636,14 +1639,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8.4" } - ], - "supplier": { - "name": "Laurent Bigonville " - } + ] }, { "bom-ref": "pkg:deb/debian/libaudit1@2.8.4-3?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Laurent Bigonville " + }, "name": "libaudit1", "version": "1:2.8.4-3", "licenses": [ @@ -1697,14 +1700,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8.4" } - ], - "supplier": { - "name": "Laurent Bigonville " - } + ] }, { "bom-ref": "pkg:deb/debian/libblkid1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "libblkid1", "version": "2.33.1-0.1", "licenses": [ @@ -1814,14 +1817,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/libbz2-1.0@1.0.6-9.2~deb10u1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Anibal Monsalve Salazar " + }, "name": "libbz2-1.0", "version": "1.0.6-9.2~deb10u1", "licenses": [ @@ -1866,14 +1869,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.0.6" } - ], - "supplier": { - "name": "Anibal Monsalve Salazar " - } + ] }, { "bom-ref": "pkg:deb/debian/libc-bin@2.28-10?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "GNU Libc Maintainers " + }, "name": "libc-bin", "version": "2.28-10", "licenses": [ @@ -1918,14 +1921,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.28" } - ], - "supplier": { - "name": "GNU Libc Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libc6@2.28-10?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "GNU Libc Maintainers " + }, "name": "libc6", "version": "2.28-10", "licenses": [ @@ -1970,14 +1973,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.28" } - ], - "supplier": { - "name": "GNU Libc Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libcap-ng0@0.7.9-2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Pierre Chifflier " + }, "name": "libcap-ng0", "version": "0.7.9-2", "licenses": [ @@ -2027,14 +2030,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.7.9" } - ], - "supplier": { - "name": "Pierre Chifflier " - } + ] }, { "bom-ref": "pkg:deb/debian/libcom-err2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Theodore Y. Ts'o " + }, "name": "libcom-err2", "version": "1.44.5-1+deb10u2", "purl": "pkg:deb/debian/libcom-err2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -2067,14 +2070,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.44.5" } - ], - "supplier": { - "name": "Theodore Y. Ts'o " - } + ] }, { "bom-ref": "pkg:deb/debian/libdb5.3@5.3.28%2Bdfsg1-0.5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Berkeley DB Team " + }, "name": "libdb5.3", "version": "5.3.28+dfsg1-0.5", "purl": "pkg:deb/debian/libdb5.3@5.3.28%2Bdfsg1-0.5?arch=amd64&distro=debian-10.2", @@ -2107,14 +2110,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.3.28+dfsg1" } - ], - "supplier": { - "name": "Debian Berkeley DB Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libdebconfclient0@0.249?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Install System Team " + }, "name": "libdebconfclient0", "version": "0.249", "purl": "pkg:deb/debian/libdebconfclient0@0.249?arch=amd64&distro=debian-10.2", @@ -2143,14 +2146,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.249" } - ], - "supplier": { - "name": "Debian Install System Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libext2fs2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Theodore Y. Ts'o " + }, "name": "libext2fs2", "version": "1.44.5-1+deb10u2", "licenses": [ @@ -2195,14 +2198,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.44.5" } - ], - "supplier": { - "name": "Theodore Y. Ts'o " - } + ] }, { "bom-ref": "pkg:deb/debian/libfdisk1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "libfdisk1", "version": "2.33.1-0.1", "licenses": [ @@ -2312,14 +2315,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/libffi6@3.2.1-9?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GCC Maintainers " + }, "name": "libffi6", "version": "3.2.1-9", "licenses": [ @@ -2359,14 +2362,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.2.1" } - ], - "supplier": { - "name": "Debian GCC Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libgcc1@8.3.0-6?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Debian GCC Maintainers " + }, "name": "libgcc1", "version": "1:8.3.0-6", "purl": "pkg:deb/debian/libgcc1@8.3.0-6?arch=amd64&distro=debian-10.2&epoch=1", @@ -2399,14 +2402,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "8.3.0" } - ], - "supplier": { - "name": "Debian GCC Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libgcrypt20@1.8.4-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuTLS Maintainers " + }, "name": "libgcrypt20", "version": "1.8.4-5", "licenses": [ @@ -2451,14 +2454,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.8.4" } - ], - "supplier": { - "name": "Debian GnuTLS Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libgdbm-compat4@1.18.1-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Dmitry Bogatov " + }, "name": "libgdbm-compat4", "version": "1.18.1-4", "licenses": [ @@ -2518,14 +2521,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.18.1" } - ], - "supplier": { - "name": "Dmitry Bogatov " - } + ] }, { "bom-ref": "pkg:deb/debian/libgdbm6@1.18.1-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Dmitry Bogatov " + }, "name": "libgdbm6", "version": "1.18.1-4", "licenses": [ @@ -2585,14 +2588,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.18.1" } - ], - "supplier": { - "name": "Dmitry Bogatov " - } + ] }, { "bom-ref": "pkg:deb/debian/libgmp10@6.1.2%2Bdfsg-4?arch=amd64&distro=debian-10.2&epoch=2", "type": "library", + "supplier": { + "name": "Debian Science Team " + }, "name": "libgmp10", "version": "2:6.1.2+dfsg-4", "licenses": [ @@ -2651,14 +2654,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1.2+dfsg" } - ], - "supplier": { - "name": "Debian Science Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libgnutls30@3.6.7-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuTLS Maintainers " + }, "name": "libgnutls30", "version": "3.6.7-4", "licenses": [ @@ -2748,14 +2751,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.6.7" } - ], - "supplier": { - "name": "Debian GnuTLS Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libgpg-error0@1.35-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuPG Maintainers " + }, "name": "libgpg-error0", "version": "1.35-1", "licenses": [ @@ -2820,14 +2823,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.35" } - ], - "supplier": { - "name": "Debian GnuPG Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libhogweed4@3.4.1-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Magnus Holmgren " + }, "name": "libhogweed4", "version": "3.4.1-1", "purl": "pkg:deb/debian/libhogweed4@3.4.1-1?arch=amd64&distro=debian-10.2", @@ -2860,14 +2863,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.4.1" } - ], - "supplier": { - "name": "Magnus Holmgren " - } + ] }, { "bom-ref": "pkg:deb/debian/libidn2-0@2.0.5-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Libidn team " + }, "name": "libidn2-0", "version": "2.0.5-1", "licenses": [ @@ -2937,14 +2940,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.0.5" } - ], - "supplier": { - "name": "Debian Libidn team " - } + ] }, { "bom-ref": "pkg:deb/debian/libjemalloc2@5.1.0-3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Faidon Liambotis " + }, "name": "libjemalloc2", "version": "5.1.0-3", "licenses": [ @@ -3009,14 +3012,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.1.0" } - ], - "supplier": { - "name": "Faidon Liambotis " - } + ] }, { "bom-ref": "pkg:deb/debian/liblz4-1@1.8.3-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Nobuhiro Iwamatsu " + }, "name": "liblz4-1", "version": "1.8.3-1", "licenses": [ @@ -3066,14 +3069,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.8.3" } - ], - "supplier": { - "name": "Nobuhiro Iwamatsu " - } + ] }, { "bom-ref": "pkg:deb/debian/liblzma5@5.2.4-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Jonathan Nieder " + }, "name": "liblzma5", "version": "5.2.4-1", "licenses": [ @@ -3183,14 +3186,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.2.4" } - ], - "supplier": { - "name": "Jonathan Nieder " - } + ] }, { "bom-ref": "pkg:deb/debian/libmount1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "libmount1", "version": "2.33.1-0.1", "licenses": [ @@ -3300,14 +3303,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/libncurses6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Craig Small " + }, "name": "libncurses6", "version": "6.1+20181013-2+deb10u2", "purl": "pkg:deb/debian/libncurses6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -3340,14 +3343,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1+20181013" } - ], - "supplier": { - "name": "Craig Small " - } + ] }, { "bom-ref": "pkg:deb/debian/libncursesw6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Craig Small " + }, "name": "libncursesw6", "version": "6.1+20181013-2+deb10u2", "purl": "pkg:deb/debian/libncursesw6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -3380,14 +3383,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1+20181013" } - ], - "supplier": { - "name": "Craig Small " - } + ] }, { "bom-ref": "pkg:deb/debian/libnettle6@3.4.1-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Magnus Holmgren " + }, "name": "libnettle6", "version": "3.4.1-1", "licenses": [ @@ -3467,14 +3470,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.4.1" } - ], - "supplier": { - "name": "Magnus Holmgren " - } + ] }, { "bom-ref": "pkg:deb/debian/libp11-kit0@0.23.15-2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuTLS Maintainers " + }, "name": "libp11-kit0", "version": "0.23.15-2", "licenses": [ @@ -3534,14 +3537,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.23.15" } - ], - "supplier": { - "name": "Debian GnuTLS Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libpam-modules-bin@1.3.1-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Steve Langasek " + }, "name": "libpam-modules-bin", "version": "1.3.1-5", "licenses": [ @@ -3581,14 +3584,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.1" } - ], - "supplier": { - "name": "Steve Langasek " - } + ] }, { "bom-ref": "pkg:deb/debian/libpam-modules@1.3.1-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Steve Langasek " + }, "name": "libpam-modules", "version": "1.3.1-5", "licenses": [ @@ -3628,14 +3631,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.1" } - ], - "supplier": { - "name": "Steve Langasek " - } + ] }, { "bom-ref": "pkg:deb/debian/libpam-runtime@1.3.1-5?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Steve Langasek " + }, "name": "libpam-runtime", "version": "1.3.1-5", "licenses": [ @@ -3675,14 +3678,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.1" } - ], - "supplier": { - "name": "Steve Langasek " - } + ] }, { "bom-ref": "pkg:deb/debian/libpam0g@1.3.1-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Steve Langasek " + }, "name": "libpam0g", "version": "1.3.1-5", "licenses": [ @@ -3722,14 +3725,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.1" } - ], - "supplier": { - "name": "Steve Langasek " - } + ] }, { "bom-ref": "pkg:deb/debian/libpcre3@8.39-12?arch=amd64&distro=debian-10.2&epoch=2", "type": "library", + "supplier": { + "name": "Matthew Vernon " + }, "name": "libpcre3", "version": "2:8.39-12", "purl": "pkg:deb/debian/libpcre3@8.39-12?arch=amd64&distro=debian-10.2&epoch=2", @@ -3766,14 +3769,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "8.39" } - ], - "supplier": { - "name": "Matthew Vernon " - } + ] }, { "bom-ref": "pkg:deb/debian/libreadline7@7.0-5?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Matthias Klose " + }, "name": "libreadline7", "version": "7.0-5", "licenses": [ @@ -3818,14 +3821,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "7.0" } - ], - "supplier": { - "name": "Matthias Klose " - } + ] }, { "bom-ref": "pkg:deb/debian/libruby2.5@2.5.5-3%2Bdeb10u1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Team " + }, "name": "libruby2.5", "version": "2.5.5-3+deb10u1", "licenses": [ @@ -3965,14 +3968,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.5.5" } - ], - "supplier": { - "name": "Debian Ruby Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libseccomp2@2.3.3-4?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Kees Cook " + }, "name": "libseccomp2", "version": "2.3.3-4", "licenses": [ @@ -4012,14 +4015,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.3.3" } - ], - "supplier": { - "name": "Kees Cook " - } + ] }, { "bom-ref": "pkg:deb/debian/libselinux1@2.8-1%2Bb1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian SELinux maintainers " + }, "name": "libselinux1", "version": "2.8-1+b1", "licenses": [ @@ -4064,14 +4067,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8" } - ], - "supplier": { - "name": "Debian SELinux maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libsemanage-common@2.8-2?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian SELinux maintainers " + }, "name": "libsemanage-common", "version": "2.8-2", "licenses": [ @@ -4116,14 +4119,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8" } - ], - "supplier": { - "name": "Debian SELinux maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libsemanage1@2.8-2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian SELinux maintainers " + }, "name": "libsemanage1", "version": "2.8-2", "licenses": [ @@ -4168,14 +4171,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8" } - ], - "supplier": { - "name": "Debian SELinux maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libsepol1@2.8-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian SELinux maintainers " + }, "name": "libsepol1", "version": "2.8-1", "licenses": [ @@ -4220,14 +4223,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.8" } - ], - "supplier": { - "name": "Debian SELinux maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libsmartcols1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "libsmartcols1", "version": "2.33.1-0.1", "licenses": [ @@ -4337,14 +4340,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/libss2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Theodore Y. Ts'o " + }, "name": "libss2", "version": "1.44.5-1+deb10u2", "purl": "pkg:deb/debian/libss2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -4377,14 +4380,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.44.5" } - ], - "supplier": { - "name": "Theodore Y. Ts'o " - } + ] }, { "bom-ref": "pkg:deb/debian/libssl1.1@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian OpenSSL Team " + }, "name": "libssl1.1", "version": "1.1.1d-0+deb10u2", "purl": "pkg:deb/debian/libssl1.1@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -4417,14 +4420,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.1.1d" } - ], - "supplier": { - "name": "Debian OpenSSL Team " - } + ] }, { "bom-ref": "pkg:deb/debian/libstdc%2B%2B6@8.3.0-6?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GCC Maintainers " + }, "name": "libstdc++6", "version": "8.3.0-6", "purl": "pkg:deb/debian/libstdc%2B%2B6@8.3.0-6?arch=amd64&distro=debian-10.2", @@ -4455,16 +4458,16 @@ }, { "name": "aquasecurity:trivy:SrcVersion", - "value": "8.3.0" - } - ], - "supplier": { - "name": "Debian GCC Maintainers " - } + "value": "8.3.0" + } + ] }, { "bom-ref": "pkg:deb/debian/libsystemd0@241-7~deb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian systemd Maintainers " + }, "name": "libsystemd0", "version": "241-7~deb10u2", "licenses": [ @@ -4534,14 +4537,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "241" } - ], - "supplier": { - "name": "Debian systemd Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libtasn1-6@4.13-3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian GnuTLS Maintainers " + }, "name": "libtasn1-6", "version": "4.13-3", "licenses": [ @@ -4596,14 +4599,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.13" } - ], - "supplier": { - "name": "Debian GnuTLS Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libtinfo6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Craig Small " + }, "name": "libtinfo6", "version": "6.1+20181013-2+deb10u2", "purl": "pkg:deb/debian/libtinfo6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -4636,14 +4639,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1+20181013" } - ], - "supplier": { - "name": "Craig Small " - } + ] }, { "bom-ref": "pkg:deb/debian/libudev1@241-7~deb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian systemd Maintainers " + }, "name": "libudev1", "version": "241-7~deb10u2", "licenses": [ @@ -4713,14 +4716,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "241" } - ], - "supplier": { - "name": "Debian systemd Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/libunistring2@0.9.10-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Jörg Frings-Fürst " + }, "name": "libunistring2", "version": "0.9.10-1", "licenses": [ @@ -4810,14 +4813,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.9.10" } - ], - "supplier": { - "name": "J\u00f6rg Frings-F\u00fcrst " - } + ] }, { "bom-ref": "pkg:deb/debian/libuuid1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "libuuid1", "version": "2.33.1-0.1", "licenses": [ @@ -4927,14 +4930,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/libyaml-0-2@0.2.1-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Anders Kaseorg " + }, "name": "libyaml-0-2", "version": "0.2.1-1", "licenses": [ @@ -4979,14 +4982,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.2.1" } - ], - "supplier": { - "name": "Anders Kaseorg " - } + ] }, { "bom-ref": "pkg:deb/debian/libzstd1@1.3.8%2Bdfsg-3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Med Packaging Team " + }, "name": "libzstd1", "version": "1.3.8+dfsg-3", "licenses": [ @@ -5046,14 +5049,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.8+dfsg" } - ], - "supplier": { - "name": "Debian Med Packaging Team " - } + ] }, { "bom-ref": "pkg:deb/debian/login@4.5-1.1?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Shadow package maintainers " + }, "name": "login", "version": "1:4.5-1.1", "licenses": [ @@ -5097,14 +5100,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.5" } - ], - "supplier": { - "name": "Shadow package maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/mawk@1.3.3-17%2Bb3?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Steve Langasek " + }, "name": "mawk", "version": "1.3.3-17+b3", "licenses": [ @@ -5144,14 +5147,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.3.3" } - ], - "supplier": { - "name": "Steve Langasek " - } + ] }, { "bom-ref": "pkg:deb/debian/mount@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "mount", "version": "2.33.1-0.1", "licenses": [ @@ -5261,14 +5264,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/ncurses-base@6.1%2B20181013-2%2Bdeb10u2?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Craig Small " + }, "name": "ncurses-base", "version": "6.1+20181013-2+deb10u2", "purl": "pkg:deb/debian/ncurses-base@6.1%2B20181013-2%2Bdeb10u2?arch=all&distro=debian-10.2", @@ -5301,14 +5304,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1+20181013" } - ], - "supplier": { - "name": "Craig Small " - } + ] }, { "bom-ref": "pkg:deb/debian/ncurses-bin@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Craig Small " + }, "name": "ncurses-bin", "version": "6.1+20181013-2+deb10u2", "purl": "pkg:deb/debian/ncurses-bin@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -5341,14 +5344,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "6.1+20181013" } - ], - "supplier": { - "name": "Craig Small " - } + ] }, { "bom-ref": "pkg:deb/debian/openssl@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian OpenSSL Team " + }, "name": "openssl", "version": "1.1.1d-0+deb10u2", "purl": "pkg:deb/debian/openssl@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", @@ -5381,14 +5384,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.1.1d" } - ], - "supplier": { - "name": "Debian OpenSSL Team " - } + ] }, { "bom-ref": "pkg:deb/debian/passwd@4.5-1.1?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Shadow package maintainers " + }, "name": "passwd", "version": "1:4.5-1.1", "licenses": [ @@ -5432,14 +5435,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.5" } - ], - "supplier": { - "name": "Shadow package maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/perl-base@5.28.1-6?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Niko Tyni " + }, "name": "perl-base", "version": "5.28.1-6", "purl": "pkg:deb/debian/perl-base@5.28.1-6?arch=amd64&distro=debian-10.2", @@ -5472,14 +5475,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.28.1" } - ], - "supplier": { - "name": "Niko Tyni " - } + ] }, { "bom-ref": "pkg:deb/debian/rake@12.3.1-3?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "rake", "version": "12.3.1-3", "licenses": [ @@ -5519,14 +5522,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "12.3.1" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/readline-common@7.0-5?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Matthias Klose " + }, "name": "readline-common", "version": "7.0-5", "licenses": [ @@ -5571,14 +5574,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "7.0" } - ], - "supplier": { - "name": "Matthias Klose " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-did-you-mean@1.2.1-1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-did-you-mean", "version": "1.2.1-1", "licenses": [ @@ -5618,14 +5621,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.2.1" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-minitest@5.11.3-1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-minitest", "version": "5.11.3-1", "licenses": [ @@ -5665,14 +5668,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "5.11.3" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-net-telnet@0.1.1-2?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-net-telnet", "version": "0.1.1-2", "licenses": [ @@ -5712,14 +5715,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.1.1" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-power-assert@1.1.1-1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-power-assert", "version": "1.1.1-1", "licenses": [ @@ -5764,14 +5767,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.1.1" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-test-unit@3.2.8-1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-test-unit", "version": "3.2.8-1", "licenses": [ @@ -5826,14 +5829,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "3.2.8" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby-xmlrpc@0.3.0-2?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "ruby-xmlrpc", "version": "0.3.0-2", "licenses": [ @@ -5873,14 +5876,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "0.3.0" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby2.5@2.5.5-3%2Bdeb10u1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Team " + }, "name": "ruby2.5", "version": "2.5.5-3+deb10u1", "licenses": [ @@ -6020,14 +6023,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.5.5" } - ], - "supplier": { - "name": "Debian Ruby Team " - } + ] }, { "bom-ref": "pkg:deb/debian/ruby@2.5.1?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Antonio Terceiro " + }, "name": "ruby", "version": "1:2.5.1", "licenses": [ @@ -6072,14 +6075,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.5.1" } - ], - "supplier": { - "name": "Antonio Terceiro " - } + ] }, { "bom-ref": "pkg:deb/debian/rubygems-integration@1.11?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian Ruby Extras Maintainers " + }, "name": "rubygems-integration", "version": "1.11", "licenses": [ @@ -6115,14 +6118,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.11" } - ], - "supplier": { - "name": "Debian Ruby Extras Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/sed@4.7-1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Clint Adams " + }, "name": "sed", "version": "4.7-1", "licenses": [ @@ -6162,14 +6165,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "4.7" } - ], - "supplier": { - "name": "Clint Adams " - } + ] }, { "bom-ref": "pkg:deb/debian/sysvinit-utils@2.93-8?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Debian sysvinit maintainers " + }, "name": "sysvinit-utils", "version": "2.93-8", "licenses": [ @@ -6214,14 +6217,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.93" } - ], - "supplier": { - "name": "Debian sysvinit maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/tar@1.30%2Bdfsg-6?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "Bdale Garbee " + }, "name": "tar", "version": "1.30+dfsg-6", "licenses": [ @@ -6266,14 +6269,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.30+dfsg" } - ], - "supplier": { - "name": "Bdale Garbee " - } + ] }, { "bom-ref": "pkg:deb/debian/tzdata@2019c-0%2Bdeb10u1?arch=all&distro=debian-10.2", "type": "library", + "supplier": { + "name": "GNU Libc Maintainers " + }, "name": "tzdata", "version": "2019c-0+deb10u1", "purl": "pkg:deb/debian/tzdata@2019c-0%2Bdeb10u1?arch=all&distro=debian-10.2", @@ -6306,14 +6309,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2019c" } - ], - "supplier": { - "name": "GNU Libc Maintainers " - } + ] }, { "bom-ref": "pkg:deb/debian/util-linux@2.33.1-0.1?arch=amd64&distro=debian-10.2", "type": "library", + "supplier": { + "name": "LaMont Jones " + }, "name": "util-linux", "version": "2.33.1-0.1", "licenses": [ @@ -6423,14 +6426,14 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "2.33.1" } - ], - "supplier": { - "name": "LaMont Jones " - } + ] }, { "bom-ref": "pkg:deb/debian/zlib1g@1.2.11.dfsg-1?arch=amd64&distro=debian-10.2&epoch=1", "type": "library", + "supplier": { + "name": "Mark Brown " + }, "name": "zlib1g", "version": "1:1.2.11.dfsg-1", "licenses": [ @@ -6474,10 +6477,7 @@ "name": "aquasecurity:trivy:SrcVersion", "value": "1.2.11.dfsg" } - ], - "supplier": { - "name": "Mark Brown " - } + ] }, { "bom-ref": "pkg:gem/activesupport@6.0.2.1", @@ -8631,111 +8631,33 @@ { "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ - "pkg:deb/debian/adduser@3.118?arch=all&distro=debian-10.2", "pkg:deb/debian/apt@1.8.2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/base-files@10.3%2Bdeb10u2?arch=amd64&distro=debian-10.2", "pkg:deb/debian/base-passwd@3.5.46?arch=amd64&distro=debian-10.2", "pkg:deb/debian/bash@5.0-4?arch=amd64&distro=debian-10.2", "pkg:deb/debian/bsdutils@2.33.1-0.1?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/ca-certificates@20190110?arch=all&distro=debian-10.2", "pkg:deb/debian/coreutils@8.30-3?arch=amd64&distro=debian-10.2", "pkg:deb/debian/dash@0.5.10.2-5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/debconf@1.5.71?arch=all&distro=debian-10.2", - "pkg:deb/debian/debian-archive-keyring@2019.1?arch=all&distro=debian-10.2", - "pkg:deb/debian/debianutils@4.8.6.1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/diffutils@3.7-3?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/dpkg@1.19.7?arch=amd64&distro=debian-10.2", "pkg:deb/debian/e2fsprogs@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/fdisk@2.33.1-0.1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/findutils@4.6.0%2Bgit%2B20190209-2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/gcc-8-base@8.3.0-6?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/gpgv@2.2.12-1%2Bdeb10u1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/grep@3.3-1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/gzip@1.9-3?arch=amd64&distro=debian-10.2", "pkg:deb/debian/hostname@3.21?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/init-system-helpers@1.56%2Bnmu1?arch=all&distro=debian-10.2", "pkg:deb/debian/libacl1@2.2.53-4?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libapt-pkg5.0@1.8.2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libattr1@2.4.48-4?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/libaudit-common@2.8.4-3?arch=all&distro=debian-10.2&epoch=1", - "pkg:deb/debian/libaudit1@2.8.4-3?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/libblkid1@2.33.1-0.1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libbz2-1.0@1.0.6-9.2~deb10u1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libc-bin@2.28-10?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libc6@2.28-10?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libcap-ng0@0.7.9-2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libcom-err2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libdb5.3@5.3.28%2Bdfsg1-0.5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libdebconfclient0@0.249?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libext2fs2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libfdisk1@2.33.1-0.1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libffi6@3.2.1-9?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libgcc1@8.3.0-6?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/libgcrypt20@1.8.4-5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libgdbm-compat4@1.18.1-4?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libgdbm6@1.18.1-4?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libgmp10@6.1.2%2Bdfsg-4?arch=amd64&distro=debian-10.2&epoch=2", - "pkg:deb/debian/libgnutls30@3.6.7-4?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libgpg-error0@1.35-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libhogweed4@3.4.1-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libidn2-0@2.0.5-1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libjemalloc2@5.1.0-3?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/liblz4-1@1.8.3-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/liblzma5@5.2.4-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libmount1@2.33.1-0.1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libncurses6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libncursesw6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libnettle6@3.4.1-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libp11-kit0@0.23.15-2?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libpam-modules-bin@1.3.1-5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libpam-modules@1.3.1-5?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libpam-runtime@1.3.1-5?arch=all&distro=debian-10.2", - "pkg:deb/debian/libpam0g@1.3.1-5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libpcre3@8.39-12?arch=amd64&distro=debian-10.2&epoch=2", - "pkg:deb/debian/libreadline7@7.0-5?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libruby2.5@2.5.5-3%2Bdeb10u1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libseccomp2@2.3.3-4?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libselinux1@2.8-1%2Bb1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libsemanage-common@2.8-2?arch=all&distro=debian-10.2", - "pkg:deb/debian/libsemanage1@2.8-2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libsepol1@2.8-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libsmartcols1@2.33.1-0.1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/libss2@1.44.5-1%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libssl1.1@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libstdc%2B%2B6@8.3.0-6?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libsystemd0@241-7~deb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libtasn1-6@4.13-3?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libtinfo6@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libudev1@241-7~deb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libunistring2@0.9.10-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libuuid1@2.33.1-0.1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libyaml-0-2@0.2.1-1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/libzstd1@1.3.8%2Bdfsg-3?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/login@4.5-1.1?arch=amd64&distro=debian-10.2&epoch=1", "pkg:deb/debian/mawk@1.3.3-17%2Bb3?arch=amd64&distro=debian-10.2", "pkg:deb/debian/mount@2.33.1-0.1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/ncurses-base@6.1%2B20181013-2%2Bdeb10u2?arch=all&distro=debian-10.2", "pkg:deb/debian/ncurses-bin@6.1%2B20181013-2%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/openssl@1.1.1d-0%2Bdeb10u2?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/passwd@4.5-1.1?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/perl-base@5.28.1-6?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/rake@12.3.1-3?arch=all&distro=debian-10.2", - "pkg:deb/debian/readline-common@7.0-5?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-did-you-mean@1.2.1-1?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-minitest@5.11.3-1?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-net-telnet@0.1.1-2?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-power-assert@1.1.1-1?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-test-unit@3.2.8-1?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby-xmlrpc@0.3.0-2?arch=all&distro=debian-10.2", - "pkg:deb/debian/ruby2.5@2.5.5-3%2Bdeb10u1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/ruby@2.5.1?arch=amd64&distro=debian-10.2&epoch=1", - "pkg:deb/debian/rubygems-integration@1.11?arch=all&distro=debian-10.2", "pkg:deb/debian/sed@4.7-1?arch=amd64&distro=debian-10.2", "pkg:deb/debian/sysvinit-utils@2.93-8?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/tar@1.30%2Bdfsg-6?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/tzdata@2019c-0%2Bdeb10u1?arch=all&distro=debian-10.2", - "pkg:deb/debian/util-linux@2.33.1-0.1?arch=amd64&distro=debian-10.2", - "pkg:deb/debian/zlib1g@1.2.11.dfsg-1?arch=amd64&distro=debian-10.2&epoch=1" + "pkg:deb/debian/tzdata@2019c-0%2Bdeb10u1?arch=all&distro=debian-10.2" ] }, { @@ -9640,4 +9562,4 @@ } ], "vulnerabilities": [] -} \ No newline at end of file +} diff --git a/integration/testdata/fluentd-multiple-lockfiles.json.golden b/integration/testdata/fluentd-multiple-lockfiles.json.golden index fec0e1a39a0d..106bb020e84c 100644 --- a/integration/testdata/fluentd-multiple-lockfiles.json.golden +++ b/integration/testdata/fluentd-multiple-lockfiles.json.golden @@ -36,7 +36,10 @@ }, "InstalledVersion": "5.0-4", "Status": "affected", - "Layer": {}, + "Layer": { + "Digest": "sha256:000eee12ec04cc914bf96e8f5dee7767510c2aca3816af6078bd9fbe3150920c", + "DiffID": "sha256:831c5620387fb9efec59fc82a42b948546c6be601e3ab34a87108ecf852aa15f" + }, "SeveritySource": "debian", "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-18276", "DataSource": { @@ -102,7 +105,10 @@ "InstalledVersion": "2.0.5-1", "FixedVersion": "2.0.5-1+deb10u1", "Status": "fixed", - "Layer": {}, + "Layer": { + "Digest": "sha256:000eee12ec04cc914bf96e8f5dee7767510c2aca3816af6078bd9fbe3150920c", + "DiffID": "sha256:831c5620387fb9efec59fc82a42b948546c6be601e3ab34a87108ecf852aa15f" + }, "SeveritySource": "nvd", "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-18224", "DataSource": { @@ -173,7 +179,10 @@ "InstalledVersion": "6.0.2.1", "FixedVersion": "6.0.3.1, 5.2.4.3", "Status": "fixed", - "Layer": {}, + "Layer": { + "Digest": "sha256:a8877cad19f14a7044524a145ce33170085441a7922458017db1631dcd5f7602", + "DiffID": "sha256:75e43d55939745950bc3f8fad56c5834617c4339f0f54755e69a0dd5372624e9" + }, "SeveritySource": "ghsa", "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-8165", "DataSource": { diff --git a/integration/testdata/helm.json.golden b/integration/testdata/helm.json.golden index 36ac8cf19935..5654b1a07f94 100644 --- a/integration/testdata/helm.json.golden +++ b/integration/testdata/helm.json.golden @@ -22,7 +22,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 79, - "Failures": 14 + "Failures": 15 }, "Misconfigurations": [ { @@ -805,8 +805,51 @@ "CauseMetadata": { "Provider": "Kubernetes", "Service": "general", + "StartLine": 19, + "EndLine": 22, "Code": { - "Lines": null + "Lines": [ + { + "Number": 19, + "Content": " - name: nginx", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - \u001b[38;5;33mname\u001b[0m: nginx", + "FirstCause": true, + "LastCause": false + }, + { + "Number": 20, + "Content": " image: nginx:1.14.2", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mimage\u001b[0m: nginx:1.14.2", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 21, + "Content": " ports:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mports\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 22, + "Content": " - containerPort: 80", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - \u001b[38;5;33mcontainerPort\u001b[0m: \u001b[38;5;37m80\u001b[0m", + "FirstCause": false, + "LastCause": true + } + ] } } }, @@ -905,6 +948,32 @@ "Lines": null } } + }, + { + "Type": "Helm Security Check", + "ID": "KSV118", + "AVDID": "AVD-KSV-0118", + "Title": "Default security context configured", + "Description": "Security context controls the allocation of security parameters for the pod/container/volume, ensuring the appropriate level of protection. Relying on default security context may expose vulnerabilities to potential attacks that rely on privileged access.", + "Message": "container nginx-deployment in default namespace is using the default security context", + "Namespace": "builtin.kubernetes.KSV118", + "Query": "data.builtin.kubernetes.KSV118.deny", + "Resolution": "To enhance security, it is strongly recommended not to rely on the default security context. Instead, it is advisable to explicitly define the required security parameters (such as runAsNonRoot, capabilities, readOnlyRootFilesystem, etc.) within the security context.", + "Severity": "HIGH", + "PrimaryURL": "https://avd.aquasec.com/misconfig/ksv118", + "References": [ + "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", + "https://avd.aquasec.com/misconfig/ksv118" + ], + "Status": "FAIL", + "Layer": {}, + "CauseMetadata": { + "Provider": "Kubernetes", + "Service": "general", + "Code": { + "Lines": null + } + } } ] } diff --git a/integration/testdata/helm_testchart.json.golden b/integration/testdata/helm_testchart.json.golden index 478bcea3b672..c760d570cd82 100644 --- a/integration/testdata/helm_testchart.json.golden +++ b/integration/testdata/helm_testchart.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 89, + "Successes": 90, "Failures": 4 }, "Misconfigurations": [ @@ -302,8 +302,110 @@ "CauseMetadata": { "Provider": "Kubernetes", "Service": "general", + "StartLine": 28, + "EndLine": 57, "Code": { - "Lines": null + "Lines": [ + { + "Number": 28, + "Content": " - name: testchart", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - \u001b[38;5;33mname\u001b[0m: testchart", + "FirstCause": true, + "LastCause": false + }, + { + "Number": 29, + "Content": " securityContext:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33msecurityContext\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 30, + "Content": " capabilities:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mcapabilities\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 31, + "Content": " drop:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mdrop\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 32, + "Content": " - ALL", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - ALL", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 33, + "Content": " readOnlyRootFilesystem: true", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mreadOnlyRootFilesystem\u001b[0m: \u001b[38;5;166mtrue", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 34, + "Content": " runAsGroup: 10001", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsGroup\u001b[0m: \u001b[38;5;37m10001", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 35, + "Content": " runAsNonRoot: true", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsNonRoot\u001b[0m: \u001b[38;5;166mtrue", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 36, + "Content": " runAsUser: 10001", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsUser\u001b[0m: \u001b[38;5;37m10001", + "FirstCause": false, + "LastCause": true + }, + { + "Number": 37, + "Content": "", + "IsCause": false, + "Annotation": "", + "Truncated": true, + "FirstCause": false, + "LastCause": false + } + ] } } }, @@ -341,7 +443,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 60, + "Successes": 61, "Failures": 0 } }, @@ -350,7 +452,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 59, + "Successes": 60, "Failures": 0 } } diff --git a/integration/testdata/helm_testchart.overridden.json.golden b/integration/testdata/helm_testchart.overridden.json.golden index 36710b35734e..a813a887a89e 100644 --- a/integration/testdata/helm_testchart.overridden.json.golden +++ b/integration/testdata/helm_testchart.overridden.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 87, + "Successes": 88, "Failures": 6 }, "Misconfigurations": [ @@ -430,8 +430,110 @@ "CauseMetadata": { "Provider": "Kubernetes", "Service": "general", + "StartLine": 28, + "EndLine": 57, "Code": { - "Lines": null + "Lines": [ + { + "Number": 28, + "Content": " - name: testchart", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - \u001b[38;5;33mname\u001b[0m: testchart", + "FirstCause": true, + "LastCause": false + }, + { + "Number": 29, + "Content": " securityContext:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33msecurityContext\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 30, + "Content": " capabilities:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mcapabilities\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 31, + "Content": " drop:", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mdrop\u001b[0m:", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 32, + "Content": " - ALL", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " - ALL", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 33, + "Content": " readOnlyRootFilesystem: true", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": " \u001b[38;5;33mreadOnlyRootFilesystem\u001b[0m: \u001b[38;5;166mtrue", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 34, + "Content": " runAsGroup: 10001", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsGroup\u001b[0m: \u001b[38;5;37m10001", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 35, + "Content": " runAsNonRoot: true", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsNonRoot\u001b[0m: \u001b[38;5;166mtrue", + "FirstCause": false, + "LastCause": false + }, + { + "Number": 36, + "Content": " runAsUser: 0", + "IsCause": true, + "Annotation": "", + "Truncated": false, + "Highlighted": "\u001b[0m \u001b[38;5;33mrunAsUser\u001b[0m: \u001b[38;5;37m0", + "FirstCause": false, + "LastCause": true + }, + { + "Number": 37, + "Content": "", + "IsCause": false, + "Annotation": "", + "Truncated": true, + "FirstCause": false, + "LastCause": false + } + ] } } }, @@ -568,7 +670,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 60, + "Successes": 61, "Failures": 0 } }, @@ -577,7 +679,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 59, + "Successes": 60, "Failures": 0 } } diff --git a/integration/testdata/julia-spdx.json.golden b/integration/testdata/julia-spdx.json.golden index a770765dd849..039d19ecdadf 100644 --- a/integration/testdata/julia-spdx.json.golden +++ b/integration/testdata/julia-spdx.json.golden @@ -154,11 +154,6 @@ "relatedSpdxElement": "SPDXRef-Package-7784b00da0cb0cb0", "relationshipType": "CONTAINS" }, - { - "spdxElementId": "SPDXRef-Application-18fc3597717a3e56", - "relatedSpdxElement": "SPDXRef-Package-960543ac5c5f7e10", - "relationshipType": "CONTAINS" - }, { "spdxElementId": "SPDXRef-Application-18fc3597717a3e56", "relatedSpdxElement": "SPDXRef-Package-a4705eb108e4f15c", diff --git a/integration/testdata/npm-cyclonedx.json.golden b/integration/testdata/npm-cyclonedx.json.golden index d7bcc56af462..9f47c487996e 100644 --- a/integration/testdata/npm-cyclonedx.json.golden +++ b/integration/testdata/npm-cyclonedx.json.golden @@ -294,18 +294,10 @@ { "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ - "pkg:npm/asap@2.0.6", "pkg:npm/jquery@3.3.9", - "pkg:npm/js-tokens@4.0.0", - "pkg:npm/loose-envify@1.4.0", - "pkg:npm/object-assign@4.1.1", "pkg:npm/promise@8.0.3", - "pkg:npm/prop-types@15.7.2", - "pkg:npm/react-is@16.8.6", "pkg:npm/react@16.8.6", - "pkg:npm/redux@4.0.1", - "pkg:npm/scheduler@0.13.6", - "pkg:npm/symbol-observable@1.2.0" + "pkg:npm/redux@4.0.1" ] }, { diff --git a/integration/testdata/pom-cyclonedx.json.golden b/integration/testdata/pom-cyclonedx.json.golden index 42650c62b54e..1202c466d2e4 100644 --- a/integration/testdata/pom-cyclonedx.json.golden +++ b/integration/testdata/pom-cyclonedx.json.golden @@ -2,7 +2,7 @@ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000005", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000006", "version": 1, "metadata": { "timestamp": "2021-08-25T12:20:30+00:00", @@ -17,7 +17,7 @@ ] }, "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", "type": "application", "name": "testdata/fixtures/repo/pom", "properties": [ @@ -30,7 +30,7 @@ }, "components": [ { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000003", "type": "application", "name": "pom.xml", "properties": [ @@ -83,13 +83,13 @@ ], "dependencies": [ { - "ref": "3ff14136-e09f-4df9-80ea-000000000001", + "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ - "3ff14136-e09f-4df9-80ea-000000000002" + "3ff14136-e09f-4df9-80ea-000000000003" ] }, { - "ref": "3ff14136-e09f-4df9-80ea-000000000002", + "ref": "3ff14136-e09f-4df9-80ea-000000000003", "dependsOn": [ "pkg:maven/com.example/log4shell@1.0-SNAPSHOT" ] diff --git a/integration/testdata/uv.json.golden b/integration/testdata/uv.json.golden new file mode 100644 index 000000000000..1a65b79b9224 --- /dev/null +++ b/integration/testdata/uv.json.golden @@ -0,0 +1,195 @@ +{ + "SchemaVersion": 2, + "CreatedAt": "2021-08-25T12:20:30.000000005Z", + "ArtifactName": "testdata/fixtures/repo/uv", + "ArtifactType": "repository", + "Metadata": { + "ImageConfig": { + "architecture": "", + "created": "0001-01-01T00:00:00Z", + "os": "", + "rootfs": { + "type": "", + "diff_ids": null + }, + "config": {} + } + }, + "Results": [ + { + "Target": "uv.lock", + "Class": "lang-pkgs", + "Type": "uv", + "Packages": [ + { + "ID": "uv-test@0.1.0", + "Name": "uv-test", + "Identifier": { + "PURL": "pkg:pypi/uv-test@0.1.0", + "UID": "d8b4e0c0129124ef" + }, + "Version": "0.1.0", + "Relationship": "root", + "DependsOn": [ + "click@8.1.3", + "werkzeug@0.11.1" + ], + "Layer": {} + }, + { + "ID": "click@8.1.3", + "Name": "click", + "Identifier": { + "PURL": "pkg:pypi/click@8.1.3", + "UID": "76baa5f52f0c32da" + }, + "Version": "8.1.3", + "Relationship": "direct", + "DependsOn": [ + "colorama@0.4.6" + ], + "Layer": {} + }, + { + "ID": "werkzeug@0.11.1", + "Name": "werkzeug", + "Identifier": { + "PURL": "pkg:pypi/werkzeug@0.11.1", + "UID": "de1411a7bb678535" + }, + "Version": "0.11.1", + "Relationship": "direct", + "Layer": {} + }, + { + "ID": "colorama@0.4.6", + "Name": "colorama", + "Identifier": { + "PURL": "pkg:pypi/colorama@0.4.6", + "UID": "49acc401742db23d" + }, + "Version": "0.4.6", + "Indirect": true, + "Relationship": "indirect", + "Layer": {} + } + ], + "Vulnerabilities": [ + { + "VulnerabilityID": "CVE-2019-14806", + "PkgID": "werkzeug@0.11.1", + "PkgName": "werkzeug", + "PkgIdentifier": { + "PURL": "pkg:pypi/werkzeug@0.11.1", + "UID": "de1411a7bb678535" + }, + "InstalledVersion": "0.11.1", + "FixedVersion": "0.15.3", + "Status": "fixed", + "Layer": {}, + "SeveritySource": "ghsa", + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-14806", + "DataSource": { + "ID": "ghsa", + "Name": "GitHub Security Advisory Pip", + "URL": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Apip" + }, + "Title": "python-werkzeug: insufficient debugger PIN randomness vulnerability", + "Description": "Pallets Werkzeug before 0.15.3, when used with Docker, has insufficient debugger PIN randomness because Docker containers share the same machine id.", + "Severity": "HIGH", + "CweIDs": [ + "CWE-331" + ], + "VendorSeverity": { + "ghsa": 3, + "nvd": 3, + "redhat": 2, + "ubuntu": 1 + }, + "CVSS": { + "nvd": { + "V2Vector": "AV:N/AC:L/Au:N/C:P/I:N/A:N", + "V3Vector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "V2Score": 5, + "V3Score": 7.5 + }, + "redhat": { + "V3Vector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "V3Score": 7.5 + } + }, + "References": [ + "http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00034.html", + "http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00047.html", + "https://access.redhat.com/security/cve/CVE-2019-14806", + "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14806", + "https://github.com/advisories/GHSA-gq9m-qvpx-68hc", + "https://github.com/pallets/werkzeug/blob/7fef41b120327d3912fbe12fb64f1951496fcf3e/src/werkzeug/debug/__init__.py#L168", + "https://github.com/pallets/werkzeug/commit/00bc43b1672e662e5e3b8cecd79e67fc968fa246", + "https://nvd.nist.gov/vuln/detail/CVE-2019-14806", + "https://palletsprojects.com/blog/werkzeug-0-15-3-released/", + "https://ubuntu.com/security/notices/USN-4655-1" + ], + "PublishedDate": "2019-08-09T15:15:00Z", + "LastModifiedDate": "2019-09-11T00:15:00Z" + }, + { + "VulnerabilityID": "CVE-2020-28724", + "PkgID": "werkzeug@0.11.1", + "PkgName": "werkzeug", + "PkgIdentifier": { + "PURL": "pkg:pypi/werkzeug@0.11.1", + "UID": "de1411a7bb678535" + }, + "InstalledVersion": "0.11.1", + "FixedVersion": "0.11.6", + "Status": "fixed", + "Layer": {}, + "SeveritySource": "ghsa", + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-28724", + "DataSource": { + "ID": "ghsa", + "Name": "GitHub Security Advisory Pip", + "URL": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Apip" + }, + "Title": "python-werkzeug: open redirect via double slash in the URL", + "Description": "Open redirect vulnerability in werkzeug before 0.11.6 via a double slash in the URL.", + "Severity": "MEDIUM", + "CweIDs": [ + "CWE-601" + ], + "VendorSeverity": { + "ghsa": 2, + "nvd": 2, + "redhat": 2, + "ubuntu": 2 + }, + "CVSS": { + "nvd": { + "V2Vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N", + "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", + "V2Score": 5.8, + "V3Score": 6.1 + }, + "redhat": { + "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N", + "V3Score": 5.4 + } + }, + "References": [ + "https://access.redhat.com/security/cve/CVE-2020-28724", + "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28724", + "https://github.com/advisories/GHSA-3p3h-qghp-hvh2", + "https://github.com/pallets/flask/issues/1639", + "https://github.com/pallets/werkzeug/issues/822", + "https://github.com/pallets/werkzeug/pull/890/files", + "https://nvd.nist.gov/vuln/detail/CVE-2020-28724", + "https://ubuntu.com/security/notices/USN-4655-1" + ], + "PublishedDate": "2020-11-18T15:15:00Z", + "LastModifiedDate": "2020-12-01T16:05:00Z" + } + ] + } + ] +} diff --git a/internal/gittest/server.go b/internal/gittest/server.go index 277d645de241..0a0012b29755 100644 --- a/internal/gittest/server.go +++ b/internal/gittest/server.go @@ -5,7 +5,9 @@ package gittest import ( "errors" "net/http/httptest" + "os" "path/filepath" + "runtime" "testing" "time" @@ -59,6 +61,51 @@ func NewServer(t *testing.T, repo, dir string) *httptest.Server { return httptest.NewServer(service) } +// NewServerWithRepository creates a git server with an existing repository +func NewServerWithRepository(t *testing.T, repo, dir string) *httptest.Server { + // Create a bare repository + bareDir := t.TempDir() + gitDir := filepath.Join(bareDir, repo+".git") + + // Clone the existing repository as a bare repository + r, err := git.PlainClone(gitDir, true, &git.CloneOptions{ + URL: dir, + Tags: git.AllTags, + }) + require.NoError(t, err) + + // Fetch all remote branches and create local branches + err = r.Fetch(&git.FetchOptions{ + RefSpecs: []config.RefSpec{ + "+refs/remotes/origin/*:refs/heads/*", + }, + Tags: git.AllTags, + }) + if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) { + require.NoError(t, err) + } + + // Set up a git server + service := gitkit.New(gitkit.Config{Dir: bareDir}) + err = service.Setup() + require.NoError(t, err) + + return httptest.NewServer(service) +} + +// NewTestServer creates a git server with the local copy of "github.com/aquasecurity/trivy-test-repo". +// If the test repository doesn't exist, it suggests running 'mage test:unit'. +func NewTestServer(t *testing.T) *httptest.Server { + _, filePath, _, _ := runtime.Caller(0) + dir := filepath.Join(filepath.Dir(filePath), "testdata", "test-repo") + + if _, err := os.Stat(dir); os.IsNotExist(err) { + require.Fail(t, "test-repo not found. Please run 'mage test:unit' to set up the test fixtures") + } + + return NewServerWithRepository(t, "test-repo", dir) +} + func Clone(t *testing.T, ts *httptest.Server, repo, worktree string) *git.Repository { cloneOptions := git.CloneOptions{ URL: ts.URL + "/" + repo + ".git", diff --git a/internal/gittest/testdata/fixture.go b/internal/gittest/testdata/fixture.go new file mode 100644 index 000000000000..75b0d75b6280 --- /dev/null +++ b/internal/gittest/testdata/fixture.go @@ -0,0 +1,43 @@ +package gittest + +import ( + "log/slog" + "path/filepath" + "runtime" + + "github.com/go-git/go-git/v5" + "github.com/magefile/mage/target" + "golang.org/x/xerrors" +) + +const ( + repoURL = "https://github.com/aquasecurity/trivy-test-repo/" + repoDir = "test-repo" // subdirectory for the cloned repository +) + +// Fixtures clones a Git repository for unit tests +func Fixtures() error { + _, filePath, _, _ := runtime.Caller(0) + dir := filepath.Dir(filePath) + cloneDir := filepath.Join(dir, repoDir) + + // Check if the directory already exists and is up to date + if updated, err := target.Path(cloneDir, filePath); err != nil { + return err + } else if !updated { + return nil + } + + slog.Info("Cloning...", slog.String("url", repoURL)) + + // Clone the repository with all branches and tags + _, err := git.PlainClone(cloneDir, false, &git.CloneOptions{ + URL: repoURL, + Tags: git.AllTags, + }) + if err != nil { + return xerrors.Errorf("error cloning repository: %w", err) + } + + return nil +} diff --git a/magefiles/cloud_actions.go b/magefiles/cloud_actions.go deleted file mode 100644 index 195bdde349e8..000000000000 --- a/magefiles/cloud_actions.go +++ /dev/null @@ -1,271 +0,0 @@ -//go:build mage_cloudactions - -package main - -import ( - "bufio" - "context" - "errors" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - "sync" - "time" - - "github.com/antchfx/htmlquery" - "github.com/aquasecurity/trivy/pkg/log" - "golang.org/x/net/html" - "golang.org/x/sync/errgroup" -) - -const ( - serviceAuthURL = "https://docs.aws.amazon.com/service-authorization/latest/reference/" - serviceActionReferencesURL = "https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html" - targetFile = "pkg/iac/providers/aws/iam/actions.go" - defaultParallel = 10 -) - -func parseServiceURLs(doc *html.Node) ([]string, error) { - nodes, err := htmlquery.QueryAll(doc, `//div[@class="highlights"]/ul/li/a/@href`) - if err != nil { - return nil, fmt.Errorf("failed to search nodes: %w\n", err) - } - - res := make([]string, 0, len(nodes)) - - for _, node := range nodes { - // AWS Account Management - if node.FirstChild != nil { - res = append(res, serviceAuthURL+node.FirstChild.Data[2:]) - } - } - - return res, nil -} - -func parseActions(url string) ([]string, error) { - - doc, err := htmlquery.LoadURL(url) - if err != nil { - return nil, err - } - - servicePrefix, err := parseServicePrefix(doc) - if err != nil { - return nil, err - } - - actions, err := parseServiceActions(doc) - if err != nil { - return nil, err - } - - res := make([]string, 0, len(actions)) - - for _, act := range actions { - res = append(res, servicePrefix+":"+act) - } - - fmt.Printf("Parsing of %q actions is completed\n", servicePrefix) - - return res, nil -} - -func parseServiceActions(doc *html.Node) ([]string, error) { - table, err := htmlquery.Query(doc, `//div[@class="table-container"]/div/table/tbody`) - if table == nil { - return nil, errors.New("actions table not found") - } - if err != nil { - return nil, fmt.Errorf("failed to query tables: %w\n", err) - } - - var actions []string - - var f func(*html.Node) - f = func(n *html.Node) { - for _, tr := range findSubtags(n, "tr") { - var action string - for k, td := range findSubtags(tr, "td") { - // first column - action - if k == 0 { - if a := findSubtag(td, "a"); a != nil && a.FirstChild != nil { - action = a.FirstChild.Data - } - - // fourth column - resource type - // If the column is empty, then the action does not support resource-level permissions - // and you must specify all resources ("*") in your policy - } else if action != "" && k == 3 && td.FirstChild == nil { - actions = append(actions, action) - } - } - } - for c := n.FirstChild; c != nil; c = c.NextSibling { - f(c) - } - } - f(table) - - return actions, err -} - -func findSubtag(n *html.Node, tagName string) *html.Node { - for c := n.FirstChild; c != nil; c = c.NextSibling { - if c.Type == html.ElementNode && c.Data == tagName { - return c - } - } - - return nil -} - -func findSubtags(n *html.Node, tagName string) []*html.Node { - var result []*html.Node - for c := n.FirstChild; c != nil; c = c.NextSibling { - if c.Type == html.ElementNode && c.Data == tagName { - result = append(result, c) - } - } - return result -} - -func parseServicePrefix(doc *html.Node) (string, error) { - nodes, err := htmlquery.QueryAll(doc, `//div[@id="main-col-body"]/p/descendant-or-self::*/text()`) - if err != nil { - return "", fmt.Errorf("failed to query paragraph: %w\n", err) - } - - var sb strings.Builder - for _, node := range nodes { - sb.WriteString(node.Data) - } - - p := sb.String() - sb.Reset() - - idx := strings.Index(p, "service prefix: ") - if idx == -1 { - return "", fmt.Errorf("failed extract service prefix from text: %s\n", p) - } - idx += len("service prefix: ") - - if len(p)-1 <= idx { - return "", fmt.Errorf("failed to parse service prefix from text: %s\n", p) - } - - var parsed bool - for _, r := range p[idx:] { - if r == ')' { - parsed = true - break - } - sb.WriteRune(r) - } - - if !parsed { - return "", fmt.Errorf("failed to parse service prefix from text: %s\n", p) - } - - return sb.String(), nil -} - -func generateFile(path string, actions []string) error { - - f, err := os.Create(path) - if err != nil { - return fmt.Errorf("failed to create file: %w\n", err) - } - defer f.Close() - - w := bufio.NewWriter(f) - _, _ = w.WriteString( - `// Code generated by mage genallowedactions DO NOT EDIT. - -package iam - -var allowedActionsForResourceWildcardsMap = map[string]struct{}{ -`, - ) - - for _, action := range actions { - _, _ = w.WriteString("\t\"" + action + "\": {},\n") - } - _, _ = w.WriteString("}") - - return w.Flush() -} - -func main() { - if err := GenAllowedActions(); err != nil { - log.Fatal(err) - } -} - -// GenAllowedActions generates the list of valid actions for wildcard support -func GenAllowedActions() error { - log.Info("Start parsing actions") - startTime := time.Now() - defer func() { - log.Info("Parsing is completed", log.Duration(time.Since(startTime).Seconds())) - }() - - doc, err := htmlquery.LoadURL(serviceActionReferencesURL) - if err != nil { - return fmt.Errorf("failed to retrieve action references: %w\n", err) - } - urls, err := parseServiceURLs(doc) - if err != nil { - return err - } - - g, ctx := errgroup.WithContext(context.TODO()) - g.SetLimit(defaultParallel) - - // actions may be the same for services of different versions, - // e.g. Elastic Load Balancing and Elastic Load Balancing V2 - actionsSet := make(map[string]struct{}) - - var mu sync.Mutex - - for _, url := range urls { - url := url - if ctx.Err() != nil { - break - } - g.Go(func() error { - serviceActions, err := parseActions(url) - if err != nil { - return fmt.Errorf("failed to parse actions from %q: %w\n", url, err) - } - - mu.Lock() - for _, act := range serviceActions { - actionsSet[act] = struct{}{} - } - mu.Unlock() - - return nil - }) - } - - if err := g.Wait(); err != nil { - return err - } - - actions := make([]string, 0, len(actionsSet)) - - for act := range actionsSet { - actions = append(actions, act) - } - - sort.Strings(actions) - - path := filepath.FromSlash(targetFile) - if err := generateFile(path, actions); err != nil { - return fmt.Errorf("failed to generate file: %w\n", err) - } - return nil -} diff --git a/magefiles/cloud_actions_test.go b/magefiles/cloud_actions_test.go deleted file mode 100644 index 8b558062f96f..000000000000 --- a/magefiles/cloud_actions_test.go +++ /dev/null @@ -1,100 +0,0 @@ -//go:build mage_cloudactions - -package main - -import ( - "os" - "path/filepath" - "testing" - - "github.com/antchfx/htmlquery" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestParseActionTableURLs(t *testing.T) { - - doc, err := htmlquery.LoadDoc(filepath.Join("testdata", "reference_policies_actions-resources-contextkeys.html")) - require.NoError(t, err) - - urls, err := parseServiceURLs(doc) - require.NoError(t, err) - - expected := []string{ - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsaccountmanagement.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsactivate.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_alexaforbusiness.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonmediaimport.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsamplify.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsamplifyadmin.html", - "https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsamplifyuibuilder.html", - } - assert.Equal(t, expected, urls) -} - -func TestParseServicePrefix(t *testing.T) { - - doc, err := htmlquery.LoadDoc(filepath.Join("testdata", "list_amazoncloudwatch.html")) - require.NoError(t, err) - - servicePrefix, err := parseServicePrefix(doc) - require.NoError(t, err) - - assert.Equal(t, "cloudwatch", servicePrefix) -} - -func TestParseActionsFromTable(t *testing.T) { - - doc, err := htmlquery.LoadDoc(filepath.Join("testdata", "list_amazoncloudwatch.html")) - require.NoError(t, err) - - actions, err := parseServiceActions(doc) - require.NoError(t, err) - - expected := []string{ - "DeleteAnomalyDetector", - "DescribeAlarmsForMetric", - "DescribeAnomalyDetectors", - "DescribeInsightRules", - "GetMetricData", - "GetMetricStatistics", - "GetMetricWidgetImage", - "Link", - "ListDashboards", - "ListManagedInsightRules", - "ListMetricStreams", - "ListMetrics", - "PutAnomalyDetector", - "PutManagedInsightRules", - "PutMetricData", - } - - assert.Equal(t, expected, actions) -} - -func TestGenerateFile(t *testing.T) { - tmpDir := t.TempDir() - - actions := []string{ - "account:DisableRegion", - "account:EnableRegion", - "account:ListRegions", - } - path := filepath.Join(tmpDir, "test.go") - require.NoError(t, generateFile(path, actions)) - - expected := `// Code generated by mage genallowedactions DO NOT EDIT. - -package iam - -var allowedActionsForResourceWildcardsMap = map[string]struct{}{ - "account:DisableRegion": {}, - "account:EnableRegion": {}, - "account:ListRegions": {}, -}` - - b, err := os.ReadFile(path) - require.NoError(t, err) - - assert.Equal(t, expected, string(b)) -} diff --git a/magefiles/docs.go b/magefiles/docs.go index bfdd7480d2a9..f37e0d5d04ea 100644 --- a/magefiles/docs.go +++ b/magefiles/docs.go @@ -147,6 +147,14 @@ func writeFlagValue(val any, ind string, w *os.File) { } else { w.WriteString(" []\n") } + case map[string][]string: + w.WriteString("\n") + for k, vv := range v { + fmt.Fprintf(w, "%s %s:\n", ind, k) + for _, vvv := range vv { + fmt.Fprintf(w, " %s - %s\n", ind, vvv) + } + } case string: fmt.Fprintf(w, " %q\n", v) default: diff --git a/magefiles/fixture.go b/magefiles/fixture.go index e7a2c395157e..39e5bd0ddae2 100644 --- a/magefiles/fixture.go +++ b/magefiles/fixture.go @@ -7,6 +7,8 @@ import ( "path/filepath" "strings" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/authn/github" "github.com/google/go-containerregistry/pkg/crane" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/magefile/mage/sh" @@ -16,13 +18,15 @@ import ( const dir = "integration/testdata/fixtures/images/" +var auth = crane.WithAuthFromKeychain(authn.NewMultiKeychain(authn.DefaultKeychain, github.Keychain)) + func fixtureContainerImages() error { var testImages = testutil.ImageName("", "", "") if err := os.MkdirAll(dir, 0750); err != nil { return err } - tags, err := crane.ListTags(testImages) + tags, err := crane.ListTags(testImages, auth) if err != nil { return err } @@ -53,7 +57,7 @@ func saveImage(subpath, tag string) error { } fmt.Printf("Downloading %s...\n", imgName) - img, err := crane.Pull(imgName) + img, err := crane.Pull(imgName, auth) if err != nil { return err } @@ -64,7 +68,6 @@ func saveImage(subpath, tag string) error { if err = sh.Run("gzip", tarPath); err != nil { return err } - return nil } @@ -77,12 +80,12 @@ func fixtureVMImages() error { if err := os.MkdirAll(dir, 0750); err != nil { return err } - tags, err := crane.ListTags(testVMImages) + tags, err := crane.ListTags(testVMImages, auth) if err != nil { return err } for _, tag := range tags { - img, err := crane.Pull(fmt.Sprintf("%s:%s", testVMImages, tag)) + img, err := crane.Pull(fmt.Sprintf("%s:%s", testVMImages, tag), auth) if err != nil { return err } diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 6adff2d92864..de3e36df08ea 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -16,10 +16,12 @@ import ( "github.com/magefile/mage/sh" "github.com/magefile/mage/target" - //mage:import rpm - rpm "github.com/aquasecurity/trivy/pkg/fanal/analyzer/pkg/rpm/testdata" // Trivy packages should not be imported in Mage (see https://github.com/aquasecurity/trivy/pull/4242), // but this package doesn't have so many dependencies, and Mage is still fast. + //mage:import gittest + gittest "github.com/aquasecurity/trivy/internal/gittest/testdata" + //mage:import rpm + rpm "github.com/aquasecurity/trivy/pkg/fanal/analyzer/pkg/rpm/testdata" "github.com/aquasecurity/trivy/pkg/log" ) @@ -286,7 +288,7 @@ func compileWasmModules(pattern string) error { // Unit runs unit tests func (t Test) Unit() error { - mg.Deps(t.GenerateModules, rpm.Fixtures) + mg.Deps(t.GenerateModules, rpm.Fixtures, gittest.Fixtures) return sh.RunWithV(ENV, "go", "test", "-v", "-short", "-coverprofile=coverage.txt", "-covermode=atomic", "./...") } @@ -307,13 +309,74 @@ func (t Test) K8s() error { defer func() { _ = sh.RunWithV(ENV, "kind", "delete", "cluster", "--name", "kind-test") }() + // wait for the kind cluster is running correctly + err = sh.RunWithV(ENV, "kubectl", "wait", "--for=condition=Ready", "nodes", "--all", "--timeout=300s") + if err != nil { + return fmt.Errorf("can't wait for the kind cluster: %w", err) + } + err = sh.RunWithV(ENV, "kubectl", "apply", "-f", "./integration/testdata/fixtures/k8s/test_nginx.yaml") + if err != nil { + return fmt.Errorf("can't create a test deployment: %w", err) + } + + // create an environment for limited user test + err = initk8sLimitedUserEnv() + if err != nil { + return fmt.Errorf("can't create environment for limited user: %w", err) + } + + // print all resources for info + err = sh.RunWithV(ENV, "kubectl", "get", "all", "-A") if err != nil { return err } + return sh.RunWithV(ENV, "go", "test", "-v", "-tags=k8s_integration", "./integration/...") } +func initk8sLimitedUserEnv() error { + commands := [][]string{ + {"kubectl", "create", "namespace", "limitedns"}, + {"kubectl", "create", "-f", "./integration/testdata/fixtures/k8s/limited-pod.yaml"}, + {"kubectl", "create", "serviceaccount", "limiteduser"}, + {"kubectl", "create", "-f", "./integration/testdata/fixtures/k8s/limited-role.yaml"}, + {"kubectl", "create", "-f", "./integration/testdata/fixtures/k8s/limited-binding.yaml"}, + {"cp", "./integration/testdata/fixtures/k8s/kube-config-template", "./integration/limitedconfig"}, + } + + for _, cmd := range commands { + if err := sh.RunV(cmd[0], cmd[1:]...); err != nil { + return err + } + } + envs := make(map[string]string) + var err error + envs["CA"], err = sh.Output("kubectl", "config", "view", "-o", "jsonpath=\"{.clusters[?(@.name == 'kind-kind-test')].cluster.certificate-authority-data}\"", "--flatten") + if err != nil { + return err + } + envs["URL"], err = sh.Output("kubectl", "config", "view", "-o", "jsonpath=\"{.clusters[?(@.name == 'kind-kind-test')].cluster.server}\"") + if err != nil { + return err + } + envs["TOKEN"], err = sh.Output("kubectl", "create", "token", "limiteduser", "--duration=8760h") + if err != nil { + return err + } + commandsWith := [][]string{ + {"sed", "-i", "-e", "s|{{CA}}|$CA|g", "./integration/limitedconfig"}, + {"sed", "-i", "-e", "s|{{URL}}|$URL|g", "./integration/limitedconfig"}, + {"sed", "-i", "-e", "s|{{TOKEN}}|$TOKEN|g", "./integration/limitedconfig"}, + } + for _, cmd := range commandsWith { + if err := sh.RunWithV(envs, cmd[0], cmd[1:]...); err != nil { + return err + } + } + return nil +} + // Module runs Wasm integration tests func (t Test) Module() error { mg.Deps(t.FixtureContainerImages, t.GenerateExampleModules) @@ -522,13 +585,6 @@ func (Schema) Verify() error { return sh.RunWith(ENV, "go", "run", "-tags=mage_schema", "./magefiles", "--", "verify") } -type CloudActions mg.Namespace - -// Generate generates the list of possible cloud actions with AWS -func (CloudActions) Generate() error { - return sh.RunWith(ENV, "go", "run", "-tags=mage_cloudactions", "./magefiles") -} - // VEX generates a VEX document for Trivy func VEX(_ context.Context, dir string) error { return sh.RunWith(ENV, "go", "run", "-tags=mage_vex", "./magefiles/vex.go", "--dir", dir) @@ -540,3 +596,10 @@ type Helm mg.Namespace func (Helm) UpdateVersion() error { return sh.RunWith(ENV, "go", "run", "-tags=mage_helm", "./magefiles") } + +type SPDX mg.Namespace + +// UpdateLicenseExceptions updates 'exception.json' with SPDX license exceptions +func (SPDX) UpdateLicenseExceptions() error { + return sh.RunWith(ENV, "go", "run", "-tags=mage_spdx", "./magefiles/spdx.go") +} diff --git a/magefiles/schema.go b/magefiles/schema.go index 77d98d75d535..6cbf8b950ad0 100644 --- a/magefiles/schema.go +++ b/magefiles/schema.go @@ -5,7 +5,7 @@ package main import ( "bytes" "encoding/json" - "fmt" + "errors" "log" "os" @@ -66,7 +66,7 @@ func VerifySchema() error { return err } if !bytes.Equal(data, existing) { - return fmt.Errorf("schema is out of date:\n\nplease run 'mage schema:generate' and commit the changes\n") + return errors.New("schema is out of date:\n\nplease run 'mage schema:generate' and commit the changes\n") } return nil } diff --git a/magefiles/spdx.go b/magefiles/spdx.go new file mode 100644 index 000000000000..258afcd0b1cd --- /dev/null +++ b/magefiles/spdx.go @@ -0,0 +1,78 @@ +//go:build mage_spdx + +package main + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "sort" + + "github.com/samber/lo" + "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/downloader" + "github.com/aquasecurity/trivy/pkg/log" +) + +const ( + exceptionFileName = "exceptions.json" + exceptionDir = "./pkg/licensing/expression" + exceptionURL = "https://spdx.org/licenses/exceptions.json" +) + +type Exceptions struct { + Exceptions []Exception `json:"exceptions"` +} + +type Exception struct { + ID string `json:"licenseExceptionId"` +} + +func main() { + if err := run(); err != nil { + log.Fatal("Fatal error", log.Err(err)) + } + +} + +// run downloads exceptions.json file, takes only IDs and saves into `expression` package. +func run() error { + tmpDir, err := downloader.DownloadToTempDir(context.Background(), exceptionURL, downloader.Options{}) + if err != nil { + return xerrors.Errorf("unable to download exceptions.json file: %w", err) + } + tmpFile, err := os.ReadFile(filepath.Join(tmpDir, exceptionFileName)) + if err != nil { + return xerrors.Errorf("unable to read exceptions.json file: %w", err) + } + + exceptions := Exceptions{} + if err = json.Unmarshal(tmpFile, &exceptions); err != nil { + return xerrors.Errorf("unable to unmarshal exceptions.json file: %w", err) + } + + exs := lo.Map(exceptions.Exceptions, func(ex Exception, _ int) string { + return ex.ID + }) + sort.Strings(exs) + + exceptionFile := filepath.Join(exceptionDir, exceptionFileName) + f, err := os.Create(exceptionFile) + if err != nil { + return xerrors.Errorf("unable to create file %s: %w", exceptionFile, err) + } + defer f.Close() + + e, err := json.Marshal(exs) + if err != nil { + return xerrors.Errorf("unable to marshal exceptions list: %w", err) + } + + if _, err = f.Write(e); err != nil { + return xerrors.Errorf("unable to write exceptions list: %w", err) + } + + return nil +} diff --git a/magefiles/testdata/list_amazoncloudwatch.html b/magefiles/testdata/list_amazoncloudwatch.html deleted file mode 100644 index 10c20f2f8159..000000000000 --- a/magefiles/testdata/list_amazoncloudwatch.html +++ /dev/null @@ -1,958 +0,0 @@ - - Actions, resources, and condition keys for Amazon CloudWatch - Service Authorization Reference
Actions, resources, and condition keys for Amazon CloudWatch - Service Authorization Reference

Actions, resources, and condition keys for Amazon CloudWatch

Amazon CloudWatch (service prefix: cloudwatch) provides the following service-specific resources, actions, and condition context keys for use in IAM permission policies.

References:

- - - -
-

Actions defined by Amazon CloudWatch

-

You can specify the following actions in the Action element of an IAM policy statement. Use policies to grant permissions to perform an operation in AWS. When you use an action in a policy, you usually allow or deny access to the API operation or CLI command with the same name. However, in some cases, a single action controls access to more than one operation. Alternatively, some operations require several different actions.

-

The Resource types column of the Actions table indicates whether each action supports resource-level permissions. If there is no value for this column, you must specify all resources ("*") to which the policy applies in the Resource element of your policy statement. If the column includes a resource type, then you can specify an ARN of that type in a statement with that action. If the action has one or more required resources, the caller must have permission to use the action with those resources. Required resources are indicated in the table with an asterisk (*). If you limit resource access with the Resource element in an IAM policy, you must include an ARN or pattern for each required resource type. Some actions support multiple resource types. If the resource type is optional (not indicated as required), then you can choose to use one of the optional resource types.

-

The Condition keys column of the Actions table includes keys that you can specify in a policy statement's Condition element. For more information on the condition keys that are associated with resources for the service, see the Condition keys column of the Resource types table.

-
Note

Resource condition keys are listed in the Resource types table. You can find a link to the resource type that applies to an action in the Resource types (*required) column of the Actions table. The resource type in the Resource types table includes the Condition keys column, which are the resource condition keys that apply to an action in the Actions table.

- -

For details about the columns in the following table, see Actions table.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ActionsDescriptionAccess levelResource types (*required)Condition keysDependent actions
- - DeleteAlarms - Grants permission to delete a collection of alarmsWrite -

- alarm* -

-
- - DeleteAnomalyDetector - Grants permission to delete the specified anomaly detection model from your accountWrite
- - DeleteDashboards - Grants permission to delete all CloudWatch dashboards that you specifyWrite -

- dashboard* -

-
- - DeleteInsightRules - Grants permission to delete a collection of insight rulesWrite -

- insight-rule* -

-
- - DeleteMetricStream - Grants permission to delete the CloudWatch metric stream that you specifyWrite -

- metric-stream* -

-
- - DescribeAlarmHistory - Grants permission to retrieve the history for the specified alarmRead -

- alarm* -

-
- - DescribeAlarms - Grants permission to describe all alarms, currently owned by the user's accountRead -

- alarm* -

-
- - DescribeAlarmsForMetric - Grants permission to describe all alarms configured on the specified metric, currently owned by the user's accountRead
- - DescribeAnomalyDetectors - Grants permission to list the anomaly detection models that you have created in your accountRead
- - DescribeInsightRules - Grants permission to describe all insight rules, currently owned by the user's accountRead
- - DisableAlarmActions - Grants permission to disable actions for a collection of alarmsWrite -

- alarm* -

-
- - DisableInsightRules - Grants permission to disable a collection of insight rulesWrite -

- insight-rule* -

-
- - EnableAlarmActions - Grants permission to enable actions for a collection of alarmsWrite -

- alarm* -

-
- - EnableInsightRules - Grants permission to enable a collection of insight rulesWrite -

- insight-rule* -

-
- - GetDashboard - Grants permission to display the details of the CloudWatch dashboard you specifyRead -

- dashboard* -

-
- - GetInsightRuleReport - Grants permission to return the top-N report of unique contributors over a time range for a given insight ruleRead -

- insight-rule* -

-
- - GetMetricData - Grants permission to retrieve batch amounts of CloudWatch metric data and perform metric math on retrieved dataRead
- - GetMetricStatistics - Grants permission to retrieve statistics for the specified metricRead
- - GetMetricStream - Grants permission to return the details of a CloudWatch metric streamRead -

- metric-stream* -

-
- - GetMetricWidgetImage - Grants permission to retrieve snapshots of metric widgetsRead
Grants permission to share CloudWatch resources with a monitoring accountWrite
- - ListDashboards - Grants permission to return a list of all CloudWatch dashboards in your accountList
- - ListManagedInsightRules - Grants permission to list available managed Insight Rules for a given Resource ARNRead -

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-

- cloudwatch:requestManagedResourceARNs -

-
- - ListMetricStreams - Grants permission to return a list of all CloudWatch metric streams in your accountList
- - ListMetrics - Grants permission to retrieve a list of valid metrics stored for the AWS account ownerList
- - ListTagsForResource - Grants permission to list tags for an Amazon CloudWatch resourceList -

- alarm -

-
-

- insight-rule -

-
-

- SCENARIO: - CloudWatch-Alarm -

-
-

- alarm* -

-
-

- SCENARIO: - CloudWatch-InsightRule -

-
-

- insight-rule* -

-
- - PutAnomalyDetector - Grants permission to create or update an anomaly detection model for a CloudWatch metricWrite
- - PutCompositeAlarm - Grants permission to create or update a composite alarmWrite -

- alarm* -

-
-

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-

- cloudwatch:AlarmActions -

-
- - PutDashboard - Grants permission to create a CloudWatch dashboard, or update an existing dashboard if it already existsWrite -

- dashboard* -

-
- - PutInsightRule - Grants permission to create a new insight rule or replace an existing insight ruleWrite -

- insight-rule* -

-
-

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-

- cloudwatch:requestInsightRuleLogGroups -

-
- - PutManagedInsightRules - Grants permission to create managed Insight RulesWrite -

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-

- cloudwatch:requestManagedResourceARNs -

-
- - PutMetricAlarm - Grants permission to create or update an alarm and associates it with the specified Amazon CloudWatch metricWrite -

- alarm* -

-
-

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-

- cloudwatch:AlarmActions -

-
- - PutMetricData - Grants permission to publish metric data points to Amazon CloudWatchWrite -

- cloudwatch:namespace -

-
- - PutMetricStream - Grants permission to create a CloudWatch metric stream, or update an existing metric stream if it already existsWrite -

- metric-stream* -

-
-

- aws:RequestTag/${TagKey} -

-

- aws:TagKeys -

-
- - SetAlarmState - Grants permission to temporarily set the state of an alarm for testing purposesWrite -

- alarm* -

-
- - StartMetricStreams - Grants permission to start all CloudWatch metric streams that you specifyWrite -

- metric-stream* -

-
- - StopMetricStreams - Grants permission to stop all CloudWatch metric streams that you specifyWrite -

- metric-stream* -

-
- - TagResource - Grants permission to add tags to an Amazon CloudWatch resourceTagging -

- alarm -

-
-

- insight-rule -

-
-

- aws:TagKeys -

-

- aws:RequestTag/${TagKey} -

-
-

- SCENARIO: - CloudWatch-Alarm -

-
-

- alarm* -

-
-

- SCENARIO: - CloudWatch-InsightRule -

-
-

- insight-rule* -

-
- - UntagResource - Grants permission to remove a tag from an Amazon CloudWatch resourceTagging -

- alarm -

-
-

- insight-rule -

-
-

- aws:TagKeys -

-
-

- SCENARIO: - CloudWatch-Alarm -

-
-

- alarm* -

-
-

- SCENARIO: - CloudWatch-InsightRule -

-
-

- insight-rule* -

-
- -

Resource types defined by Amazon CloudWatch

- -

The following resource types are defined by this service and can be used in the Resource element of IAM permission policy statements. Each action in the Actions table identifies the resource types that can be specified with that action. A resource type can also define which condition keys you can include in a policy. These keys are displayed in the last column of the Resource types table. For details about the columns in the following table, see Resource types table.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Resource typesARNCondition keys
- - alarm - - arn:${Partition}:cloudwatch:${Region}:${Account}:alarm:${AlarmName} - -

- aws:ResourceTag/${TagKey} -

-
- - dashboard - - arn:${Partition}:cloudwatch::${Account}:dashboard/${DashboardName} -
- - insight-rule - - arn:${Partition}:cloudwatch:${Region}:${Account}:insight-rule/${InsightRuleName} - -

- aws:ResourceTag/${TagKey} -

-
- - metric-stream - - arn:${Partition}:cloudwatch:${Region}:${Account}:metric-stream/${MetricStreamName} - -

- aws:ResourceTag/${TagKey} -

-
- -

Condition keys for Amazon CloudWatch

- -

Amazon CloudWatch defines the following condition keys that can be used in the Condition element of an IAM policy. You can use these keys to further refine the conditions under which the policy statement applies. For details about the columns in the following table, see Condition keys table.

- -

To view the global condition keys that are available to all services, see Available global condition keys.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Condition keysDescriptionType
- - aws:RequestTag/${TagKey} - Filters actions based on the allowed set of values for each of the tagsString
- - aws:ResourceTag/${TagKey} - Filters actions based on tag-value associated with the resourceString
- - aws:TagKeys - Filters actions based on the presence of mandatory tags in the requestArrayOfString
- - cloudwatch:AlarmActions - Filters actions based on defined alarm actionsArrayOfString
- - cloudwatch:namespace - Filters actions based on the presence of optional namespace valuesString
- - cloudwatch:requestInsightRuleLogGroups - Filters actions based on the Log Groups specified in an Insight RuleArrayOfString
- - cloudwatch:requestManagedResourceARNs - Filters access by the Resource ARNs specified in a managed Insight RuleArrayOfARN
-
\ No newline at end of file diff --git a/magefiles/testdata/reference_policies_actions-resources-contextkeys.html b/magefiles/testdata/reference_policies_actions-resources-contextkeys.html deleted file mode 100644 index 053322c7f6bc..000000000000 --- a/magefiles/testdata/reference_policies_actions-resources-contextkeys.html +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/misc/lint/rules.go b/misc/lint/rules.go index 4f1b098535ec..591b31d1ef82 100644 --- a/misc/lint/rules.go +++ b/misc/lint/rules.go @@ -30,3 +30,8 @@ func errorsJoin(m dsl.Matcher) { m.Match(`errors.Join($*args)`). Report("use github.com/hashicorp/go-multierror.Append instead of errors.Join.") } + +func mapSet(m dsl.Matcher) { + m.Match(`map[$x]struct{}`). + Report("use github.com/aquasecurity/trivy/pkg/set.Set instead of map.") +} diff --git a/mkdocs.yml b/mkdocs.yml index 4b20bb8d6dac..00735e3c9680 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -221,7 +221,9 @@ nav: - Backporting: community/maintainer/backporting.md - Help Wanted: community/maintainer/help-wanted.md - Triage: community/maintainer/triage.md - + - Enterprise: + - Comparison: commercial/compare.md + - Contact Us: commercial/contact.md theme: name: material custom_dir: docs/overrides @@ -266,12 +268,15 @@ extra: provider: mike default: latest social: - - icon: fontawesome/brands/twitter + - icon: fontawesome/brands/x-twitter link: https://twitter.com/AquaTrivy - icon: fontawesome/brands/github link: https://github.com/aquasecurity/trivy - icon: fontawesome/brands/slack link: https://github.com/aquasecurity/trivy + analytics: + provider: google + property: G-V9LJGFH7GX plugins: - search diff --git a/pkg/cache/fs_test.go b/pkg/cache/fs_test.go index 9323391a3af4..819df36ee22f 100644 --- a/pkg/cache/fs_test.go +++ b/pkg/cache/fs_test.go @@ -286,8 +286,7 @@ func TestFSCache_PutBlob(t *testing.T) { err = fs.PutBlob(tt.args.diffID, tt.args.layerInfo) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -366,8 +365,7 @@ func TestFSCache_PutArtifact(t *testing.T) { err = fs.PutArtifact(tt.args.imageID, tt.args.imageConfig) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) diff --git a/pkg/cache/memory_test.go b/pkg/cache/memory_test.go index 3d88b565c7f9..ed0494a2ad02 100644 --- a/pkg/cache/memory_test.go +++ b/pkg/cache/memory_test.go @@ -314,8 +314,7 @@ func TestMemoryCache_DeleteBlobs(t *testing.T) { // Check that the blobs are no longer in the cache for _, blobID := range tt.blobIDs { _, err := c.GetBlob(blobID) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found in memory cache") + require.ErrorContains(t, err, "not found in memory cache") } }) } @@ -348,12 +347,10 @@ func TestMemoryCache_Clear(t *testing.T) { require.NoError(t, err) _, err = c.GetArtifact(tt.artifactID) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found in memory cache") + require.ErrorContains(t, err, "not found in memory cache") _, err = c.GetBlob(tt.blobID) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found in memory cache") + require.ErrorContains(t, err, "not found in memory cache") }) } } @@ -385,12 +382,10 @@ func TestMemoryCache_Close(t *testing.T) { require.NoError(t, err) _, err = c.GetArtifact(tt.artifactID) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found in memory cache") + require.ErrorContains(t, err, "not found in memory cache") _, err = c.GetBlob(tt.blobID) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found in memory cache") + require.ErrorContains(t, err, "not found in memory cache") }) } } diff --git a/pkg/cache/redis_test.go b/pkg/cache/redis_test.go index 3cc8bbd702ad..f08d855abd10 100644 --- a/pkg/cache/redis_test.go +++ b/pkg/cache/redis_test.go @@ -537,8 +537,7 @@ func TestRedisCache_DeleteBlobs(t *testing.T) { err = c.DeleteBlobs(tt.args.blobIDs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/cache/remote_test.go b/pkg/cache/remote_test.go index 3e1363d5dd4d..867878b99857 100644 --- a/pkg/cache/remote_test.go +++ b/pkg/cache/remote_test.go @@ -152,8 +152,7 @@ func TestRemoteCache_PutArtifact(t *testing.T) { }) err := c.PutArtifact(tt.args.imageID, tt.args.imageInfo) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -217,8 +216,7 @@ func TestRemoteCache_PutBlob(t *testing.T) { }) err := c.PutBlob(tt.args.diffID, tt.args.layerInfo) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -299,8 +297,7 @@ func TestRemoteCache_MissingBlobs(t *testing.T) { }) gotMissingImage, gotMissingLayerIDs, err := c.MissingBlobs(tt.args.imageID, tt.args.layerIDs) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -353,8 +350,7 @@ func TestRemoteCache_PutArtifactInsecure(t *testing.T) { }) err := c.PutArtifact(tt.args.imageID, tt.args.imageInfo) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err, tt.name) diff --git a/pkg/commands/app.go b/pkg/commands/app.go index dbe3d54ba373..7bedce99ff65 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -476,7 +476,7 @@ func NewRepositoryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { repoFlags.ReportFlagGroup.Compliance = nil // disable '--compliance' repoFlags.ReportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol' - repoFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default + repoFlags.ScanFlagGroup.DistroFlag = nil // `repo` subcommand doesn't support scanning OS packages, so we can disable `--distro` cmd := &cobra.Command{ Use: "repository [flags] (REPO_PATH | REPO_URL)", diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 5018434d10c2..80d2f77710ee 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -356,7 +356,22 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err if opts.GenerateDefaultConfig { log.Info("Writing the default config to trivy-default.yaml...") - return viper.SafeWriteConfigAs("trivy-default.yaml") + + hiddenFlags := flag.HiddenFlags() + // Viper does not have the ability to remove flags. + // So we only save the necessary flags and set these flags after viper.Reset + v := viper.New() + for _, k := range viper.AllKeys() { + // Skip the `GenerateDefaultConfigFlag` flags to avoid errors with default config file. + // Users often use "normal" formats instead of compliance. So we'll skip ComplianceFlag + // Also don't keep removed or deprecated flags to avoid confusing users. + if k == flag.GenerateDefaultConfigFlag.ConfigName || k == flag.ComplianceFlag.ConfigName || slices.Contains(hiddenFlags, k) { + continue + } + v.Set(k, viper.Get(k)) + } + + return v.SafeWriteConfigAs("trivy-default.yaml") } r, err := NewRunner(ctx, opts) @@ -483,16 +498,7 @@ func (r *runner) initScannerConfig(ctx context.Context, opts flag.Options) (Scan target = opts.Input } - scanOptions := types.ScanOptions{ - PkgTypes: opts.PkgTypes, - PkgRelationships: opts.PkgRelationships, - Scanners: opts.Scanners, - ImageConfigScanners: opts.ImageConfigScanners, // this is valid only for 'image' subcommand - ScanRemovedPackages: opts.ScanRemovedPkgs, // this is valid only for 'image' subcommand - LicenseCategories: opts.LicenseCategories, - FilePatterns: opts.FilePatterns, - IncludeDevDeps: opts.IncludeDevDeps, - } + scanOptions := opts.ScanOpts() if len(opts.ImageConfigScanners) != 0 { log.WithPrefix(log.PrefixContainerImage).Info("Container image config scanners", log.Any("scanners", opts.ImageConfigScanners)) @@ -581,6 +587,7 @@ func (r *runner) initScannerConfig(ctx context.Context, opts flag.Options) (Scan Host: opts.PodmanHost, }, ImageSources: opts.ImageSources, + MaxImageSize: opts.MaxImageSize, }, // For misconfiguration scanning diff --git a/pkg/compliance/spec/compliance.go b/pkg/compliance/spec/compliance.go index 70355eaa926f..794d244ca9b4 100644 --- a/pkg/compliance/spec/compliance.go +++ b/pkg/compliance/spec/compliance.go @@ -6,13 +6,13 @@ import ( "path/filepath" "strings" - "github.com/samber/lo" "golang.org/x/xerrors" "gopkg.in/yaml.v3" - sp "github.com/aquasecurity/trivy-checks/pkg/spec" + "github.com/aquasecurity/trivy-checks/pkg/specs" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/types" ) @@ -31,17 +31,17 @@ const ( // Scanners reads spec control and determines the scanners by check ID prefix func (cs *ComplianceSpec) Scanners() (types.Scanners, error) { - scannerTypes := make(map[types.Scanner]struct{}) + scannerTypes := set.New[types.Scanner]() for _, control := range cs.Spec.Controls { for _, check := range control.Checks { scannerType := scannerByCheckID(check.ID) if scannerType == types.UnknownScanner { return nil, xerrors.Errorf("unsupported check ID: %s", check.ID) } - scannerTypes[scannerType] = struct{}{} + scannerTypes.Append(scannerType) } } - return lo.Keys(scannerTypes), nil + return scannerTypes.Items(), nil } // CheckIDs return list of compliance check IDs @@ -97,7 +97,7 @@ func GetComplianceSpec(specNameOrPath, cacheDir string) (ComplianceSpec, error) } else { _, err := os.Stat(filepath.Join(checksDir(cacheDir), "metadata.json")) if err != nil { // cache corrupt or bundle does not exist, load embedded version - b = []byte(sp.NewSpecLoader().GetSpecByName(specNameOrPath)) + b = []byte(specs.GetSpec(specNameOrPath)) log.Debug("Compliance spec loaded from embedded library", log.String("spec", specNameOrPath)) } else { // load from bundle on disk diff --git a/pkg/compliance/spec/compliance_test.go b/pkg/compliance/spec/compliance_test.go index 0b44702b4159..b49f169ac7a6 100644 --- a/pkg/compliance/spec/compliance_test.go +++ b/pkg/compliance/spec/compliance_test.go @@ -271,7 +271,7 @@ func TestComplianceSpec_LoadFromDiskBundle(t *testing.T) { t.Run("load user specified spec from disk fails", func(t *testing.T) { _, err := spec.GetComplianceSpec("@doesnotexist", "does-not-matter") - assert.Contains(t, err.Error(), "error retrieving compliance spec from path") + require.ErrorContains(t, err, "error retrieving compliance spec from path") }) t.Run("bundle does not exist", func(t *testing.T) { @@ -288,6 +288,6 @@ func TestComplianceSpec_LoadFromDiskBundle(t *testing.T) { t.Run("load spec yaml unmarshal failure", func(t *testing.T) { _, err := spec.GetComplianceSpec("invalid", filepath.Join("testdata", "testcache")) - assert.Contains(t, err.Error(), "spec yaml decode error") + require.ErrorContains(t, err, "spec yaml decode error") }) } diff --git a/pkg/db/db_test.go b/pkg/db/db_test.go index f64c0dc4a5c6..2fd83aa87325 100644 --- a/pkg/db/db_test.go +++ b/pkg/db/db_test.go @@ -127,8 +127,7 @@ func TestClient_NeedsUpdate(t *testing.T) { switch { case tt.wantErr != "": - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) default: require.NoError(t, err, tt.name) } diff --git a/pkg/dependency/id.go b/pkg/dependency/id.go index 12ef6ef773b3..309abe946c5a 100644 --- a/pkg/dependency/id.go +++ b/pkg/dependency/id.go @@ -1,7 +1,7 @@ package dependency import ( - "fmt" + "strconv" "strings" "github.com/mitchellh/hashstructure/v2" @@ -52,5 +52,5 @@ func UID(filePath string, pkg types.Package) string { if err != nil { log.Warn("Failed to calculate the package hash", log.String("pkg", pkg.Name), log.Err(err)) } - return fmt.Sprintf("%x", hash) + return strconv.FormatUint(hash, 16) } diff --git a/pkg/dependency/parser/c/conan/parse.go b/pkg/dependency/parser/c/conan/parse.go index 14da9358fb8a..cb277692bb7e 100644 --- a/pkg/dependency/parser/c/conan/parse.go +++ b/pkg/dependency/parser/c/conan/parse.go @@ -5,10 +5,10 @@ import ( "slices" "strings" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" diff --git a/pkg/dependency/parser/dotnet/core_deps/parse.go b/pkg/dependency/parser/dotnet/core_deps/parse.go index 7fc8d3df5d5e..b7cdfe4c1ba6 100644 --- a/pkg/dependency/parser/dotnet/core_deps/parse.go +++ b/pkg/dependency/parser/dotnet/core_deps/parse.go @@ -6,10 +6,10 @@ import ( "strings" "sync" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" diff --git a/pkg/dependency/parser/dotnet/core_deps/parse_test.go b/pkg/dependency/parser/dotnet/core_deps/parse_test.go index 82bf0e0a1d47..3809bc22df22 100644 --- a/pkg/dependency/parser/dotnet/core_deps/parse_test.go +++ b/pkg/dependency/parser/dotnet/core_deps/parse_test.go @@ -93,8 +93,7 @@ func TestParse(t *testing.T) { got, _, err := NewParser().Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) } else { require.NoError(t, err) diff --git a/pkg/dependency/parser/frameworks/wordpress/parse_test.go b/pkg/dependency/parser/frameworks/wordpress/parse_test.go index b717d9cbc50c..40080f3afd29 100644 --- a/pkg/dependency/parser/frameworks/wordpress/parse_test.go +++ b/pkg/dependency/parser/frameworks/wordpress/parse_test.go @@ -37,8 +37,7 @@ func TestParseWordPress(t *testing.T) { got, err := Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/dependency/parser/java/pom/artifact.go b/pkg/dependency/parser/java/pom/artifact.go index 8fc20b236b51..00f4843f0b9d 100644 --- a/pkg/dependency/parser/java/pom/artifact.go +++ b/pkg/dependency/parser/java/pom/artifact.go @@ -12,6 +12,7 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/version/doc" ) @@ -30,7 +31,7 @@ type artifact struct { Version version Licenses []string - Exclusions map[string]struct{} + Exclusions set.Set[string] Module bool Relationship ftypes.Relationship diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 9f9afc35d99a..2ce4fb4e3936 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -22,6 +22,7 @@ import ( "github.com/aquasecurity/trivy/pkg/dependency/parser/utils" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" xio "github.com/aquasecurity/trivy/pkg/x/io" ) @@ -118,11 +119,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc rootArt := root.artifact() rootArt.Relationship = ftypes.RelationshipRoot - return p.parseRoot(rootArt, make(map[string]struct{})) + return p.parseRoot(rootArt, set.New[string]()) } // nolint: gocyclo -func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ftypes.Package, []ftypes.Dependency, error) { +func (p *Parser) parseRoot(root artifact, uniqModules set.Set[string]) ([]ftypes.Package, []ftypes.Dependency, error) { // Prepare a queue for dependencies queue := newArtifactQueue() @@ -145,10 +146,10 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft // Modules should be handled separately so that they can have independent dependencies. // It means multi-module allows for duplicate dependencies. if art.Module { - if _, ok := uniqModules[art.String()]; ok { + if uniqModules.Contains(art.String()) { continue } - uniqModules[art.String()] = struct{}{} + uniqModules.Append(art.String()) modulePkgs, moduleDeps, err := p.parseRoot(art, uniqModules) if err != nil { @@ -251,7 +252,7 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft // `mvn` shows modules separately from the root package and does not show module nesting. // So we can add all modules as dependencies of root package. if art.Relationship == ftypes.RelationshipRoot { - dependsOn = append(dependsOn, lo.Keys(uniqModules)...) + dependsOn = append(dependsOn, uniqModules.Items()...) } sort.Strings(dependsOn) @@ -340,7 +341,7 @@ type analysisResult struct { } type analysisOptions struct { - exclusions map[string]struct{} + exclusions set.Set[string] depManagement []pomDependency // from the root POM } @@ -348,6 +349,9 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) if pom.nil() { return analysisResult{}, nil } + if opts.exclusions == nil { + opts.exclusions = set.New[string]() + } // Update remoteRepositories pomReleaseRemoteRepos, pomSnapshotRemoteRepos := pom.repositories(p.servers) p.releaseRemoteRepos = lo.Uniq(append(pomReleaseRemoteRepos, p.releaseRemoteRepos...)) @@ -408,16 +412,16 @@ func (p *Parser) resolveParent(pom *pom) error { } func (p *Parser) mergeDependencyManagements(depManagements ...[]pomDependency) []pomDependency { - uniq := make(map[string]struct{}) + uniq := set.New[string]() var depManagement []pomDependency // The preceding argument takes precedence. for _, dm := range depManagements { for _, dep := range dm { - if _, ok := uniq[dep.Name()]; ok { + if uniq.Contains(dep.Name()) { continue } depManagement = append(depManagement, dep) - uniq[dep.Name()] = struct{}{} + uniq.Append(dep.Name()) } } return depManagement @@ -492,19 +496,19 @@ func (p *Parser) mergeDependencies(child, parent []pomDependency) []pomDependenc }) } -func (p *Parser) filterDependencies(artifacts []artifact, exclusions map[string]struct{}) []artifact { +func (p *Parser) filterDependencies(artifacts []artifact, exclusions set.Set[string]) []artifact { return lo.Filter(artifacts, func(art artifact, _ int) bool { return !excludeDep(exclusions, art) }) } -func excludeDep(exclusions map[string]struct{}, art artifact) bool { - if _, ok := exclusions[art.Name()]; ok { +func excludeDep(exclusions set.Set[string], art artifact) bool { + if exclusions.Contains(art.Name()) { return true } // Maven can use "*" in GroupID and ArtifactID fields to exclude dependencies // https://maven.apache.org/pom.html#exclusions - for exlusion := range exclusions { + for exlusion := range exclusions.Iter() { // exclusion format - ":" e := strings.Split(exlusion, ":") if (e[0] == art.GroupID || e[0] == "*") && (e[1] == art.ArtifactID || e[1] == "*") { diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index eb1a7b6b9bb7..e180e53db60e 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1470,6 +1470,52 @@ func TestPom_Parse(t *testing.T) { }, }, }, + { + name: "overwrite artifact version from dependencyManagement in the root POM when dependency uses `project.*` props", + inputFile: filepath.Join("testdata", "root-pom-dep-management-for-deps-with-project-props", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:root-pom-dep-management-for-deps-with-project-props:1.0.0", + Name: "com.example:root-pom-dep-management-for-deps-with-project-props", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "org.example:example-dependency:1.7.30", + Name: "org.example:example-dependency", + Version: "1.7.30", + Relationship: ftypes.RelationshipDirect, + Locations: ftypes.Locations{ + { + StartLine: 21, + EndLine: 25, + }, + }, + }, + { + ID: "org.example:example-api:2.0.0", + Name: "org.example:example-api", + Version: "2.0.0", + Licenses: []string{"The Apache Software License, Version 2.0"}, + Relationship: ftypes.RelationshipIndirect, + }, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:root-pom-dep-management-for-deps-with-project-props:1.0.0", + DependsOn: []string{ + "org.example:example-dependency:1.7.30", + }, + }, + { + ID: "org.example:example-dependency:1.7.30", + DependsOn: []string{ + "org.example:example-api:2.0.0", + }, + }, + }, + }, { name: "transitive dependencyManagement should not be inherited", inputFile: filepath.Join("testdata", "transitive-dependency-management", "pom.xml"), @@ -2114,8 +2160,7 @@ func TestPom_Parse(t *testing.T) { gotPkgs, gotDeps, err := p.Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 83c5d4fec609..695a9feb950a 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -4,7 +4,6 @@ import ( "encoding/xml" "fmt" "io" - "maps" "net/url" "reflect" "strings" @@ -15,6 +14,7 @@ import ( "github.com/aquasecurity/trivy/pkg/dependency/parser/utils" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/x/slices" ) @@ -245,7 +245,7 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa // If this dependency is managed in the root POM, // we need to overwrite fields according to the managed dependency. - if managed, found := findDep(d.Name(), rootDepManagement); found { // dependencyManagement from the root POM + if managed, found := findDep(dep.Name(), rootDepManagement); found { // dependencyManagement from the root POM if managed.Version != "" { dep.Version = evaluateVariable(managed.Version, props, nil) } @@ -264,7 +264,7 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa } // Inherit version, scope and optional from dependencyManagement if empty - if managed, found := findDep(d.Name(), depManagement); found { // dependencyManagement from parent + if managed, found := findDep(dep.Name(), depManagement); found { // dependencyManagement from parent if dep.Version == "" { dep.Version = evaluateVariable(managed.Version, props, nil) } @@ -287,12 +287,12 @@ func (d pomDependency) ToArtifact(opts analysisOptions) artifact { // To avoid shadow adding exclusions to top pom's, // we need to initialize a new map for each new artifact // See `exclusions in child` test for more information - exclusions := make(map[string]struct{}) + exclusions := set.New[string]() if opts.exclusions != nil { - exclusions = maps.Clone(opts.exclusions) + exclusions = opts.exclusions.Clone() } for _, e := range d.Exclusions.Exclusion { - exclusions[fmt.Sprintf("%s:%s", e.GroupID, e.ArtifactID)] = struct{}{} + exclusions.Append(fmt.Sprintf("%s:%s", e.GroupID, e.ArtifactID)) } var locations ftypes.Locations diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-dependency/1.7.30/example-dependency-1.7.30.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-dependency/1.7.30/example-dependency-1.7.30.pom new file mode 100644 index 000000000000..c897c4a7d8c0 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-dependency/1.7.30/example-dependency-1.7.30.pom @@ -0,0 +1,18 @@ + + + 4.0.0 + + org.example + example-dependency + 1.7.30 + + + + ${project.groupId} + example-api + ${project.version} + + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/root-pom-dep-management-for-deps-with-project-props/pom.xml b/pkg/dependency/parser/java/pom/testdata/root-pom-dep-management-for-deps-with-project-props/pom.xml new file mode 100644 index 000000000000..3f8a6a317962 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/root-pom-dep-management-for-deps-with-project-props/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + com.example + root-pom-dep-management-for-deps-with-project-props + 1.0.0 + pom + + + + + org.example + example-api + 2.0.0 + + + + + + + org.example + example-dependency + 1.7.30 + + + + diff --git a/pkg/dependency/parser/nodejs/npm/parse.go b/pkg/dependency/parser/nodejs/npm/parse.go index 05ce6301ff09..1e3a5b8344af 100644 --- a/pkg/dependency/parser/nodejs/npm/parse.go +++ b/pkg/dependency/parser/nodejs/npm/parse.go @@ -9,14 +9,15 @@ import ( "sort" "strings" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" "github.com/aquasecurity/trivy/pkg/dependency/parser/utils" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" xio "github.com/aquasecurity/trivy/pkg/x/io" ) @@ -43,6 +44,7 @@ type Package struct { Dependencies map[string]string `json:"dependencies"` OptionalDependencies map[string]string `json:"optionalDependencies"` DevDependencies map[string]string `json:"devDependencies"` + PeerDependencies map[string]string `json:"peerDependencies"` Resolved string `json:"resolved"` Dev bool `json:"dev"` Link bool `json:"link"` @@ -90,8 +92,8 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype // https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#packages p.resolveLinks(packages) - directDeps := make(map[string]struct{}) - for name, version := range lo.Assign(packages[""].Dependencies, packages[""].OptionalDependencies, packages[""].DevDependencies) { + directDeps := set.New[string]() + for name, version := range lo.Assign(packages[""].Dependencies, packages[""].OptionalDependencies, packages[""].DevDependencies, packages[""].PeerDependencies) { pkgPath := joinPaths(nodeModulesDir, name) if _, ok := packages[pkgPath]; !ok { p.logger.Debug("Unable to find the direct dependency", @@ -100,7 +102,7 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype } // Store the package paths of direct dependencies // e.g. node_modules/body-parser - directDeps[pkgPath] = struct{}{} + directDeps.Append(pkgPath) } for pkgPath, pkg := range packages { @@ -165,7 +167,7 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype // └─┬ watchpack@1.7.5 // ├─┬ chokidar@3.5.3 - optional dependency // │ └── glob-parent@5.1. - dependencies := lo.Assign(pkg.Dependencies, pkg.OptionalDependencies) + dependencies := lo.Assign(pkg.Dependencies, pkg.OptionalDependencies, pkg.PeerDependencies) dependsOn := make([]string, 0, len(dependencies)) for depName, depVersion := range dependencies { depID, err := findDependsOn(pkgPath, depName, packages) @@ -365,13 +367,13 @@ func (p *Parser) pkgNameFromPath(pkgPath string) string { func uniqueDeps(deps []ftypes.Dependency) []ftypes.Dependency { var uniqDeps ftypes.Dependencies - unique := make(map[string]struct{}) + unique := set.New[string]() for _, dep := range deps { sort.Strings(dep.DependsOn) depKey := fmt.Sprintf("%s:%s", dep.ID, strings.Join(dep.DependsOn, ",")) - if _, ok := unique[depKey]; !ok { - unique[depKey] = struct{}{} + if !unique.Contains(depKey) { + unique.Append(depKey) uniqDeps = append(uniqDeps, dep) } } @@ -380,11 +382,11 @@ func uniqueDeps(deps []ftypes.Dependency) []ftypes.Dependency { return uniqDeps } -func isIndirectPkg(pkgPath string, directDeps map[string]struct{}) bool { +func isIndirectPkg(pkgPath string, directDeps set.Set[string]) bool { // A project can contain 2 different versions of the same dependency. // e.g. `node_modules/string-width/node_modules/strip-ansi` and `node_modules/string-ansi` // direct dependencies always have root path (`node_modules/`) - if _, ok := directDeps[pkgPath]; ok { + if directDeps.Contains(pkgPath) { return false } return true diff --git a/pkg/dependency/parser/nodejs/npm/parse_test.go b/pkg/dependency/parser/nodejs/npm/parse_test.go index 7b0b5042c831..4400fab3201b 100644 --- a/pkg/dependency/parser/nodejs/npm/parse_test.go +++ b/pkg/dependency/parser/nodejs/npm/parse_test.go @@ -41,6 +41,12 @@ func TestParse(t *testing.T) { want: npmV3WithWorkspacePkgs, wantDeps: npmV3WithWorkspaceDeps, }, + { + name: "lock version v3 with peer dependencies", + file: "testdata/package-lock_v3_with_peer.json", + want: npmV3WithPeerDependenciesPkgs, + wantDeps: npmV3WithPeerDependenciesDeps, + }, { name: "lock file v3 contains same dev and non-dev dependencies", file: "testdata/package-lock_v3_with-same-dev-and-non-dev.json", diff --git a/pkg/dependency/parser/nodejs/npm/parse_testcase.go b/pkg/dependency/parser/nodejs/npm/parse_testcase.go index 01dcac6711f9..21e99e29c36b 100644 --- a/pkg/dependency/parser/nodejs/npm/parse_testcase.go +++ b/pkg/dependency/parser/nodejs/npm/parse_testcase.go @@ -1442,6 +1442,120 @@ var ( DependsOn: []string{"debug@2.6.9"}, }, } + // docker run --name node --rm -it node@sha256:51dd437f31812df71108b81385e2945071ec813d5815fa3403855669c8f3432b sh + // mkdir node_v3_with_peer && cd node_v3_with_peer + // npm init --force + // npm install --save winston-mail@2.0.0 + // npm install --save-peer lodash@4.17.21 + // npm update + // + // Delete unnecessary packages from package-lock.json + // Packages are filled manually + npmV3WithPeerDependenciesPkgs = []ftypes.Package{ + { + ID: "lodash@4.17.21", + Name: "lodash", + Version: "4.17.21", + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 30, + EndLine: 36, + }, + }, + }, + { + ID: "winston-mail@2.0.0", + Name: "winston-mail", + Version: "2.0.0", + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/winston-mail/-/winston-mail-2.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 60, + EndLine: 74, + }, + }, + }, + { + ID: "mustache@2.3.2", + Name: "mustache", + Version: "2.3.2", + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 18, + EndLine: 29, + }, + }, + }, + { + ID: "triple-beam@1.4.1", + Name: "triple-beam", + Version: "1.4.1", + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 37, + EndLine: 46, + }, + }, + }, + { + ID: "winston@3.17.0", + Name: "winston", + Version: "3.17.0", + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 47, + EndLine: 59, + }, + }, + }, + } + npmV3WithPeerDependenciesDeps = []ftypes.Dependency{ + { + ID: "winston-mail@2.0.0", + DependsOn: []string{ + "mustache@2.3.2", + "winston@3.17.0", + }, + }, + { + ID: "winston@3.17.0", + DependsOn: []string{"triple-beam@1.4.1"}, + }, + } // docker run --name node --rm -it node@sha256:51dd437f31812df71108b81385e2945071ec813d5815fa3403855669c8f3432b sh // mkdir node_v3_without_direct_deps && cd node_v3_without_direct_deps diff --git a/pkg/dependency/parser/nodejs/npm/testdata/package-lock_v3_with_peer.json b/pkg/dependency/parser/nodejs/npm/testdata/package-lock_v3_with_peer.json new file mode 100644 index 000000000000..51e0b7351796 --- /dev/null +++ b/pkg/dependency/parser/nodejs/npm/testdata/package-lock_v3_with_peer.json @@ -0,0 +1,76 @@ +{ + "name": "node_v3_with_peer", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node_v3_with_peer", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "winston-mail": "^2.0.0" + }, + "peerDependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/mustache": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", + "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + }, + "engines": { + "npm": ">=1.4.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT", + "peer": true + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/winston": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "license": "MIT", + "peer": true, + "dependencies": { + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-mail": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/winston-mail/-/winston-mail-2.0.0.tgz", + "integrity": "sha512-Wp+mKiieoV6FAZJNyNMS62Zsf5FBSxe17j0f4fpFYeA+rfW8nEZ2eBGGl7+vq+dr3dEpefV5D+ZI3d9jaqdRfw==", + "license": "MIT", + "dependencies": { + "mustache": "^2.2.1" + }, + "engines": { + "node": ">= 0.6.0" + }, + "peerDependencies": { + "winston": ">=0.5.0" + } + } + } +} \ No newline at end of file diff --git a/pkg/dependency/parser/nodejs/pnpm/parse.go b/pkg/dependency/parser/nodejs/pnpm/parse.go index 6f85411f40d0..0817fd48899f 100644 --- a/pkg/dependency/parser/nodejs/pnpm/parse.go +++ b/pkg/dependency/parser/nodejs/pnpm/parse.go @@ -14,6 +14,7 @@ import ( "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" xio "github.com/aquasecurity/trivy/pkg/x/io" ) @@ -215,7 +216,7 @@ func (p *Parser) parseV9(lockFile LockFile) ([]ftypes.Package, []ftypes.Dependen } } - visited := make(map[string]struct{}) + visited := set.New[string]() // Overwrite the `Dev` field for dev deps and their child dependencies. for _, pkg := range resolvedPkgs { if !pkg.Dev { @@ -227,8 +228,8 @@ func (p *Parser) parseV9(lockFile LockFile) ([]ftypes.Package, []ftypes.Dependen } // markRootPkgs sets `Dev` to false for non dev dependency. -func (p *Parser) markRootPkgs(id string, pkgs map[string]ftypes.Package, deps map[string]ftypes.Dependency, visited map[string]struct{}) { - if _, ok := visited[id]; ok { +func (p *Parser) markRootPkgs(id string, pkgs map[string]ftypes.Package, deps map[string]ftypes.Dependency, visited set.Set[string]) { + if visited.Contains(id) { return } pkg, ok := pkgs[id] @@ -238,7 +239,7 @@ func (p *Parser) markRootPkgs(id string, pkgs map[string]ftypes.Package, deps ma pkg.Dev = false pkgs[id] = pkg - visited[id] = struct{}{} + visited.Append(id) // Update child deps for _, depID := range deps[id].DependsOn { diff --git a/pkg/dependency/parser/nuget/config/parse_test.go b/pkg/dependency/parser/nuget/config/parse_test.go index f7e6d16a0e10..fbf409d68feb 100644 --- a/pkg/dependency/parser/nuget/config/parse_test.go +++ b/pkg/dependency/parser/nuget/config/parse_test.go @@ -46,8 +46,7 @@ func TestParse(t *testing.T) { got, _, err := config.NewParser().Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/dependency/parser/nuget/lock/parse.go b/pkg/dependency/parser/nuget/lock/parse.go index 7852680f5749..3e9bd8b2baef 100644 --- a/pkg/dependency/parser/nuget/lock/parse.go +++ b/pkg/dependency/parser/nuget/lock/parse.go @@ -3,10 +3,10 @@ package lock import ( "io" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" "github.com/aquasecurity/trivy/pkg/dependency/parser/utils" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" @@ -76,7 +76,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc } if savedDependsOn, ok := depsMap[depId]; ok { - dependsOn = utils.UniqueStrings(append(dependsOn, savedDependsOn...)) + dependsOn = lo.Uniq(append(dependsOn, savedDependsOn...)) } if len(dependsOn) > 0 { diff --git a/pkg/dependency/parser/nuget/packagesprops/parse_test.go b/pkg/dependency/parser/nuget/packagesprops/parse_test.go index 16e4e59816d9..801534b69ec7 100644 --- a/pkg/dependency/parser/nuget/packagesprops/parse_test.go +++ b/pkg/dependency/parser/nuget/packagesprops/parse_test.go @@ -70,8 +70,7 @@ func TestParse(t *testing.T) { got, _, err := config.NewParser().Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/dependency/parser/php/composer/parse.go b/pkg/dependency/parser/php/composer/parse.go index af99ceaf8be2..01cdf328ae14 100644 --- a/pkg/dependency/parser/php/composer/parse.go +++ b/pkg/dependency/parser/php/composer/parse.go @@ -5,10 +5,10 @@ import ( "sort" "strings" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/licensing" diff --git a/pkg/dependency/parser/python/packaging/parse.go b/pkg/dependency/parser/python/packaging/parse.go index 58ecac200db5..c7bb54fe9680 100644 --- a/pkg/dependency/parser/python/packaging/parse.go +++ b/pkg/dependency/parser/python/packaging/parse.go @@ -6,6 +6,7 @@ import ( "io" "net/textproto" "strings" + "sync" "golang.org/x/xerrors" @@ -15,6 +16,8 @@ import ( xio "github.com/aquasecurity/trivy/pkg/x/io" ) +var licenseMetadataInfoOnce sync.Once + type Parser struct { logger *log.Logger } @@ -70,7 +73,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc if l := h.Get("License"); l != "" { if len(licenses) != 0 { - p.logger.Info("License acquired from METADATA classifiers may be subject to additional terms", + licenseMetadataInfoOnce.Do(func() { + p.logger.Info("Licenses acquired from one or more METADATA files may be subject to additional terms. Use `--debug` flag to see all affected packages.") + }) + p.logger.Debug("License acquired from METADATA classifiers may be subject to additional terms", log.String("name", name), log.String("version", version)) } else { license = l diff --git a/pkg/dependency/parser/python/pipenv/parse.go b/pkg/dependency/parser/python/pipenv/parse.go index 8fbb70132c05..6538b43cc2e6 100644 --- a/pkg/dependency/parser/python/pipenv/parse.go +++ b/pkg/dependency/parser/python/pipenv/parse.go @@ -4,9 +4,9 @@ import ( "io" "strings" - "github.com/liamg/jfather" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" xio "github.com/aquasecurity/trivy/pkg/x/io" ) diff --git a/pkg/dependency/parser/python/poetry/parse.go b/pkg/dependency/parser/python/poetry/parse.go index 8b06942d3b6b..c8e240e9067f 100644 --- a/pkg/dependency/parser/python/poetry/parse.go +++ b/pkg/dependency/parser/python/poetry/parse.go @@ -2,13 +2,13 @@ package poetry import ( "sort" - "strings" "github.com/BurntSushi/toml" "golang.org/x/xerrors" version "github.com/aquasecurity/go-pep440-version" "github.com/aquasecurity/trivy/pkg/dependency" + "github.com/aquasecurity/trivy/pkg/dependency/parser/python" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" xio "github.com/aquasecurity/trivy/pkg/x/io" @@ -105,7 +105,7 @@ func (p *Parser) parseDependencies(deps map[string]any, pkgVersions map[string][ } func (p *Parser) parseDependency(name string, versRange any, pkgVersions map[string][]string) (string, error) { - name = NormalizePkgName(name) + name = python.NormalizePkgName(name) vers, ok := pkgVersions[name] if !ok { return "", xerrors.Errorf("no version found for %q", name) @@ -149,17 +149,6 @@ func matchVersion(currentVersion, constraint string) (bool, error) { return c.Check(v), nil } -// NormalizePkgName normalizes the package name based on pep-0426 -func NormalizePkgName(name string) string { - // The package names don't use `_`, `.` or upper case, but dependency names can contain them. - // We need to normalize those names. - // cf. https://peps.python.org/pep-0426/#name - name = strings.ToLower(name) // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L819 - name = strings.ReplaceAll(name, "_", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L50 - name = strings.ReplaceAll(name, ".", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L816 - return name -} - func packageID(name, ver string) string { return dependency.ID(ftypes.Poetry, name, ver) } diff --git a/pkg/dependency/parser/python/poetry/parse_testcase.go b/pkg/dependency/parser/python/poetry/parse_testcase.go index 3e54a465c2f1..6f8782e2000d 100644 --- a/pkg/dependency/parser/python/poetry/parse_testcase.go +++ b/pkg/dependency/parser/python/poetry/parse_testcase.go @@ -3,9 +3,9 @@ package poetry import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" var ( - // docker run --name pipenv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // docker run --name poetry --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh // apk add curl - // curl -sSL https://install.python-poetry.org | python3 - + // curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.1.7 python3 - // export PATH=/root/.local/bin:$PATH // poetry new normal && cd normal // poetry add pypi@2.1 @@ -14,9 +14,9 @@ var ( {ID: "pypi@2.1", Name: "pypi", Version: "2.1"}, } - // docker run --name pipenv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // docker run --name poetry --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh // apk add curl - // curl -sSL https://install.python-poetry.org | python3 - + // curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.1.7 python3 - // export PATH=/root/.local/bin:$PATH // poetry new many && cd many // curl -o poetry.lock https://raw.githubusercontent.com/python-poetry/poetry/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock @@ -108,9 +108,9 @@ var ( {ID: "xattr@0.10.1", DependsOn: []string{"cffi@1.15.1"}}, } - // docker run --name pipenv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // docker run --name poetry --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh // apk add curl - // curl -sSL https://install.python-poetry.org | python3 - + // curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.1.7 python3 - // export PATH=/root/.local/bin:$PATH // poetry new web && cd web // poetry add flask@1.0.3 diff --git a/pkg/dependency/parser/python/pyproject/pyproject.go b/pkg/dependency/parser/python/pyproject/pyproject.go index f5d6c748f1e4..cf93ce5630e5 100644 --- a/pkg/dependency/parser/python/pyproject/pyproject.go +++ b/pkg/dependency/parser/python/pyproject/pyproject.go @@ -4,7 +4,11 @@ import ( "io" "github.com/BurntSushi/toml" + "github.com/samber/lo" "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/dependency/parser/python" + "github.com/aquasecurity/trivy/pkg/set" ) type PyProject struct { @@ -16,7 +20,28 @@ type Tool struct { } type Poetry struct { - Dependencies map[string]any `toml:"dependencies"` + Dependencies Dependencies `toml:"dependencies"` + Groups map[string]Group `toml:"group"` +} + +type Group struct { + Dependencies Dependencies `toml:"dependencies"` +} + +type Dependencies struct { + set.Set[string] +} + +func (d *Dependencies) UnmarshalTOML(data any) error { + m, ok := data.(map[string]any) + if !ok { + return xerrors.Errorf("dependencies must be map, but got: %T", data) + } + + d.Set = set.New[string](lo.MapToSlice(m, func(pkgName string, _ any) string { + return python.NormalizePkgName(pkgName) + })...) + return nil } // Parser parses pyproject.toml defined in PEP518. @@ -28,10 +53,10 @@ func NewParser() *Parser { return &Parser{} } -func (p *Parser) Parse(r io.Reader) (map[string]any, error) { +func (p *Parser) Parse(r io.Reader) (PyProject, error) { var conf PyProject if _, err := toml.NewDecoder(r).Decode(&conf); err != nil { - return nil, xerrors.Errorf("toml decode error: %w", err) + return PyProject{}, xerrors.Errorf("toml decode error: %w", err) } - return conf.Tool.Poetry.Dependencies, nil + return conf, nil } diff --git a/pkg/dependency/parser/python/pyproject/pyproject_test.go b/pkg/dependency/parser/python/pyproject/pyproject_test.go index 6d125f1cc61f..670d23393b02 100644 --- a/pkg/dependency/parser/python/pyproject/pyproject_test.go +++ b/pkg/dependency/parser/python/pyproject/pyproject_test.go @@ -9,32 +9,37 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/pkg/dependency/parser/python/pyproject" + "github.com/aquasecurity/trivy/pkg/set" ) func TestParser_Parse(t *testing.T) { tests := []struct { name string file string - want map[string]any + want pyproject.PyProject wantErr assert.ErrorAssertionFunc }{ { name: "happy path", file: "testdata/happy.toml", - want: map[string]any{ - "flask": "^1.0", - "python": "^3.9", - "requests": map[string]any{ - "version": "2.28.1", - "optional": true, - }, - "virtualenv": []any{ - map[string]any{ - "version": "^20.4.3,!=20.4.5,!=20.4.6", - }, - map[string]any{ - "version": "<20.16.6", - "markers": "sys_platform == 'win32' and python_version == '3.9'", + want: pyproject.PyProject{ + Tool: pyproject.Tool{ + Poetry: pyproject.Poetry{ + Dependencies: pyproject.Dependencies{ + Set: set.New[string]("flask", "python", "requests", "virtualenv"), + }, + Groups: map[string]pyproject.Group{ + "dev": { + Dependencies: pyproject.Dependencies{ + Set: set.New[string]("pytest"), + }, + }, + "lint": { + Dependencies: pyproject.Dependencies{ + Set: set.New[string]("ruff"), + }, + }, + }, }, }, }, diff --git a/pkg/dependency/parser/python/pyproject/testdata/happy.toml b/pkg/dependency/parser/python/pyproject/testdata/happy.toml index 2cfd27e2acb2..6fa732721162 100644 --- a/pkg/dependency/parser/python/pyproject/testdata/happy.toml +++ b/pkg/dependency/parser/python/pyproject/testdata/happy.toml @@ -14,6 +14,13 @@ virtualenv = [ [tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +pytest = "8.3.4" + + +[tool.poetry.group.lint.dependencies] +ruff = "0.8.3" + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" diff --git a/pkg/dependency/parser/python/python.go b/pkg/dependency/parser/python/python.go new file mode 100644 index 000000000000..fabe9bae29ab --- /dev/null +++ b/pkg/dependency/parser/python/python.go @@ -0,0 +1,14 @@ +package python + +import "strings" + +// NormalizePkgName normalizes the package name based on pep-0426 +func NormalizePkgName(name string) string { + // The package names don't use `_`, `.` or upper case, but dependency names can contain them. + // We need to normalize those names. + // cf. https://peps.python.org/pep-0426/#name + name = strings.ToLower(name) // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L819 + name = strings.ReplaceAll(name, "_", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L50 + name = strings.ReplaceAll(name, ".", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L816 + return name +} diff --git a/pkg/dependency/parser/python/python_test.go b/pkg/dependency/parser/python/python_test.go new file mode 100644 index 000000000000..6870b0bc716f --- /dev/null +++ b/pkg/dependency/parser/python/python_test.go @@ -0,0 +1,39 @@ +package python_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/aquasecurity/trivy/pkg/dependency/parser/python" +) + +func Test_NormalizePkgName(t *testing.T) { + tests := []struct { + pkgName string + expected string + }{ + { + pkgName: "SecretStorage", + expected: "secretstorage", + }, + { + pkgName: "pywin32-ctypes", + expected: "pywin32-ctypes", + }, + { + pkgName: "jaraco.classes", + expected: "jaraco-classes", + }, + { + pkgName: "green_gdk", + expected: "green-gdk", + }, + } + + for _, tt := range tests { + t.Run(tt.pkgName, func(t *testing.T) { + assert.Equal(t, tt.expected, python.NormalizePkgName(tt.pkgName)) + }) + } +} diff --git a/pkg/dependency/parser/python/uv/parse.go b/pkg/dependency/parser/python/uv/parse.go new file mode 100644 index 000000000000..4368fb6a6db9 --- /dev/null +++ b/pkg/dependency/parser/python/uv/parse.go @@ -0,0 +1,188 @@ +package uv + +import ( + "sort" + + "github.com/BurntSushi/toml" + "github.com/samber/lo" + "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/dependency" + ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/set" + xio "github.com/aquasecurity/trivy/pkg/x/io" +) + +type Lock struct { + Packages []Package `toml:"package"` +} + +func (l Lock) packages() map[string]Package { + return lo.SliceToMap(l.Packages, func(pkg Package) (string, Package) { + return pkg.Name, pkg + }) +} + +func prodDeps(root Package, packages map[string]Package) set.Set[string] { + visited := set.New[string]() + walkPackageDeps(root, packages, visited) + return visited +} + +func walkPackageDeps(pkg Package, packages map[string]Package, visited set.Set[string]) { + if visited.Contains(pkg.Name) { + return + } + visited.Append(pkg.Name) + for depName := range pkg.nonDevDeps().Iter() { + depPkg, exists := packages[depName] + if !exists { + continue + } + walkPackageDeps(depPkg, packages, visited) + } +} + +func (l Lock) root() (Package, error) { + var pkgs []Package + for _, pkg := range l.Packages { + if pkg.isRoot() { + pkgs = append(pkgs, pkg) + } + } + + // lock file must include root package + // cf. https://github.com/astral-sh/uv/blob/f80ddf10b63c3e7b421ca4658e63f97db1e0378c/crates/uv/src/commands/project/lock.rs#L933-L936 + if len(pkgs) != 1 { + return Package{}, xerrors.New("uv lockfile must contain 1 root package") + } + + return pkgs[0], nil +} + +type Package struct { + Name string `toml:"name"` + Version string `toml:"version"` + Source Source `toml:"source"` + Dependencies Dependencies `toml:"dependencies"` + DevDependencies map[string]Dependencies `toml:"dev-dependencies"` + OptionalDependencies map[string]Dependencies `toml:"optional-dependencies"` +} + +func (p Package) directDeps() set.Set[string] { + deps := p.nonDevDeps() + for _, groupDeps := range p.DevDependencies { + deps.Append(groupDeps.toSet().Items()...) + + } + return deps +} + +func (p Package) nonDevDeps() set.Set[string] { + deps := p.Dependencies.toSet() + for _, groupDeps := range p.OptionalDependencies { + deps.Append(groupDeps.toSet().Items()...) + } + return deps +} + +type Dependencies []struct { + Name string `toml:"name"` +} + +func (d Dependencies) toSet() set.Set[string] { + deps := set.New[string]() + for _, dep := range d { + deps.Append(dep.Name) + } + return deps +} + +// https://github.com/astral-sh/uv/blob/f7d647e81d7e1e3be189324b06024ed2057168e6/crates/uv-resolver/src/lock/mod.rs#L572-L579 +func (p Package) isRoot() bool { + return p.Source.Editable == "." || p.Source.Virtual == "." +} + +type Source struct { + Editable string `toml:"editable"` + Virtual string `toml:"virtual"` +} + +type Dependency struct { + Name string `toml:"name"` +} + +type Parser struct{} + +func NewParser() *Parser { + return &Parser{} +} + +func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) { + var lock Lock + if _, err := toml.NewDecoder(r).Decode(&lock); err != nil { + return nil, nil, xerrors.Errorf("failed to decode uv lock file: %w", err) + } + + rootPackage, err := lock.root() + if err != nil { + return nil, nil, err + } + + packages := lock.packages() + directDeps := rootPackage.directDeps() + + // Since each lockfile contains a root package with a list of direct dependencies, + // we can identify all production dependencies by traversing the dependency graph + // and collecting all the dependencies that are reachable from the root. + prodDeps := prodDeps(rootPackage, packages) + + var ( + pkgs ftypes.Packages + deps ftypes.Dependencies + ) + + for _, pkg := range lock.Packages { + pkgID := packageID(pkg.Name, pkg.Version) + relationship := ftypes.RelationshipIndirect + if pkg.isRoot() { + relationship = ftypes.RelationshipRoot + } else if directDeps.Contains(pkg.Name) { + relationship = ftypes.RelationshipDirect + } + + pkgs = append(pkgs, ftypes.Package{ + ID: pkgID, + Name: pkg.Name, + Version: pkg.Version, + Relationship: relationship, + Dev: !prodDeps.Contains(pkg.Name), + }) + + dependsOn := make([]string, 0, len(pkg.Dependencies)) + + for depName := range pkg.directDeps().Iter() { + depPkg, exists := packages[depName] + if !exists { + continue + } + dependsOn = append(dependsOn, packageID(depName, depPkg.Version)) + } + + if len(dependsOn) > 0 { + sort.Strings(dependsOn) + deps = append(deps, ftypes.Dependency{ + ID: pkgID, + DependsOn: dependsOn, + }) + } + } + + sort.Sort(pkgs) + sort.Sort(deps) + return pkgs, deps, nil +} + +func packageID(name, version string) string { + return dependency.ID(ftypes.Uv, name, version) +} diff --git a/pkg/dependency/parser/python/uv/parse_test.go b/pkg/dependency/parser/python/uv/parse_test.go new file mode 100644 index 000000000000..b9e3fc446240 --- /dev/null +++ b/pkg/dependency/parser/python/uv/parse_test.go @@ -0,0 +1,56 @@ +package uv + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func TestParser_Parse(t *testing.T) { + tests := []struct { + name string + file string + wantPkgs []ftypes.Package + wantDeps []ftypes.Dependency + wantErr string + }{ + { + name: "normal", + file: "testdata/uv_normal.lock", + wantPkgs: uvNormal, + wantDeps: uvNormalDeps, + }, + { + name: "lockfile without root", + file: "testdata/uv_without_root.lock", + wantErr: "uv lockfile must contain 1 root package", + }, + { + name: "multiple roots", + file: "testdata/uv_multiple_roots.lock", + wantErr: "uv lockfile must contain 1 root package", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := os.Open(tt.file) + require.NoError(t, err) + defer f.Close() + + p := NewParser() + gotPkgs, gotDeps, err := p.Parse(f) + if tt.wantErr != "" { + assert.ErrorContains(t, err, tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.wantPkgs, gotPkgs) + assert.Equal(t, tt.wantDeps, gotDeps) + }) + } +} diff --git a/pkg/dependency/parser/python/uv/parse_testcase.go b/pkg/dependency/parser/python/uv/parse_testcase.go new file mode 100644 index 000000000000..ec3203c5cd9d --- /dev/null +++ b/pkg/dependency/parser/python/uv/parse_testcase.go @@ -0,0 +1,52 @@ +package uv + +import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" + +var ( + // docker run --name uv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // wget -qO- https://github.com/astral-sh/uv/releases/download/0.5.8/uv-installer.sh | sh + // source $HOME/.local/bin/env + // uv init normal && cd normal + // uv add requests==2.32.0 + // uv add --group dev pytest==8.3.4 + // uv add httpx==0.28.1 --extra socks + // uv add orjson==3.10.12 --optional json + // apk add jq + // uv pip list --format json |jq -c 'sort_by(.name) | .[] | {"ID": (.name + "@" + .version), "Name": .name, "Version": .version}' | sed 's/$/,/' | sed 's/\"\([^"]*\)\":/\1:/g' + + // add a root project + // fill in the relationships between the packages + uvNormal = []ftypes.Package{ + {ID: "normal@0.1.0", Name: "normal", Version: "0.1.0", Relationship: ftypes.RelationshipRoot}, + {ID: "httpx@0.28.1", Name: "httpx", Version: "0.28.1", Relationship: ftypes.RelationshipDirect}, + {ID: "orjson@3.10.12", Name: "orjson", Version: "3.10.12", Relationship: ftypes.RelationshipDirect}, + {ID: "pytest@8.3.4", Name: "pytest", Version: "8.3.4", Relationship: ftypes.RelationshipDirect, Dev: true}, + {ID: "requests@2.32.0", Name: "requests", Version: "2.32.0", Relationship: ftypes.RelationshipDirect}, + {ID: "anyio@4.7.0", Name: "anyio", Version: "4.7.0", Relationship: ftypes.RelationshipIndirect}, + {ID: "certifi@2024.12.14", Name: "certifi", Version: "2024.12.14", Relationship: ftypes.RelationshipIndirect}, + {ID: "charset-normalizer@3.4.0", Name: "charset-normalizer", Version: "3.4.0", Relationship: ftypes.RelationshipIndirect}, + {ID: "colorama@0.4.6", Name: "colorama", Version: "0.4.6", Relationship: ftypes.RelationshipIndirect, Dev: true}, + {ID: "exceptiongroup@1.2.2", Name: "exceptiongroup", Version: "1.2.2", Relationship: ftypes.RelationshipIndirect}, + {ID: "h11@0.14.0", Name: "h11", Version: "0.14.0", Relationship: ftypes.RelationshipIndirect}, + {ID: "httpcore@1.0.7", Name: "httpcore", Version: "1.0.7", Relationship: ftypes.RelationshipIndirect}, + {ID: "idna@3.10", Name: "idna", Version: "3.10", Relationship: ftypes.RelationshipIndirect}, + {ID: "iniconfig@2.0.0", Name: "iniconfig", Version: "2.0.0", Relationship: ftypes.RelationshipIndirect, Dev: true}, + {ID: "packaging@24.2", Name: "packaging", Version: "24.2", Relationship: ftypes.RelationshipIndirect, Dev: true}, + {ID: "pluggy@1.5.0", Name: "pluggy", Version: "1.5.0", Relationship: ftypes.RelationshipIndirect, Dev: true}, + {ID: "sniffio@1.3.1", Name: "sniffio", Version: "1.3.1", Relationship: ftypes.RelationshipIndirect}, + {ID: "socksio@1.0.0", Name: "socksio", Version: "1.0.0", Relationship: ftypes.RelationshipIndirect}, + {ID: "tomli@2.2.1", Name: "tomli", Version: "2.2.1", Relationship: ftypes.RelationshipIndirect, Dev: true}, + {ID: "typing-extensions@4.12.2", Name: "typing-extensions", Version: "4.12.2", Relationship: ftypes.RelationshipIndirect}, + {ID: "urllib3@2.2.3", Name: "urllib3", Version: "2.2.3", Relationship: ftypes.RelationshipIndirect}, + } + + // add a root project + uvNormalDeps = []ftypes.Dependency{ + {ID: "anyio@4.7.0", DependsOn: []string{"exceptiongroup@1.2.2", "idna@3.10", "sniffio@1.3.1", "typing-extensions@4.12.2"}}, + {ID: "httpcore@1.0.7", DependsOn: []string{"certifi@2024.12.14", "h11@0.14.0"}}, + {ID: "httpx@0.28.1", DependsOn: []string{"anyio@4.7.0", "certifi@2024.12.14", "httpcore@1.0.7", "idna@3.10", "socksio@1.0.0"}}, + {ID: "normal@0.1.0", DependsOn: []string{"httpx@0.28.1", "orjson@3.10.12", "pytest@8.3.4", "requests@2.32.0"}}, + {ID: "pytest@8.3.4", DependsOn: []string{"colorama@0.4.6", "exceptiongroup@1.2.2", "iniconfig@2.0.0", "packaging@24.2", "pluggy@1.5.0", "tomli@2.2.1"}}, + {ID: "requests@2.32.0", DependsOn: []string{"certifi@2024.12.14", "charset-normalizer@3.4.0", "idna@3.10", "urllib3@2.2.3"}}, + } +) diff --git a/pkg/dependency/parser/python/uv/testdata/uv_multiple_roots.lock b/pkg/dependency/parser/python/uv/testdata/uv_multiple_roots.lock new file mode 100644 index 000000000000..a0ccda991cb7 --- /dev/null +++ b/pkg/dependency/parser/python/uv/testdata/uv_multiple_roots.lock @@ -0,0 +1,30 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "asyncio" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/54/054bafaf2c0fb8473d423743e191fcdf49b2c1fd5e9af3524efbe097bafd/asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41", size = 204411 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/74/07679c5b9f98a7cb0fc147b1ef1cc1853bc07a4eb9cb5731e24732c5f773/asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d", size = 101767 }, +] + +[[package]] +name = "foo" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "asyncio" }, +] + +[package.metadata] +requires-dist = [{ name = "asyncio", specifier = "==3.4.3" }] + +[[package]] +name = "bar" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "asyncio" }, +] \ No newline at end of file diff --git a/pkg/dependency/parser/python/uv/testdata/uv_normal.lock b/pkg/dependency/parser/python/uv/testdata/uv_normal.lock new file mode 100644 index 000000000000..04c63ff4b687 --- /dev/null +++ b/pkg/dependency/parser/python/uv/testdata/uv_normal.lock @@ -0,0 +1,411 @@ +version = 1 +requires-python = ">=3.9" + +[[package]] +name = "anyio" +version = "4.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/40/318e58f669b1a9e00f5c4453910682e2d9dd594334539c7b7817dabb765f/anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48", size = 177076 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/7a/4daaf3b6c08ad7ceffea4634ec206faeff697526421c20f07628c7372156/anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352", size = 93052 }, +] + +[[package]] +name = "certifi" +version = "2024.12.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8b/825cc84cf13a28bfbcba7c416ec22bf85a9584971be15b21dd8300c65b7f/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6", size = 196363 }, + { url = "https://files.pythonhosted.org/packages/23/81/d7eef6a99e42c77f444fdd7bc894b0ceca6c3a95c51239e74a722039521c/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b", size = 125639 }, + { url = "https://files.pythonhosted.org/packages/21/67/b4564d81f48042f520c948abac7079356e94b30cb8ffb22e747532cf469d/charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99", size = 120451 }, + { url = "https://files.pythonhosted.org/packages/c2/72/12a7f0943dd71fb5b4e7b55c41327ac0a1663046a868ee4d0d8e9c369b85/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca", size = 140041 }, + { url = "https://files.pythonhosted.org/packages/67/56/fa28c2c3e31217c4c52158537a2cf5d98a6c1e89d31faf476c89391cd16b/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d", size = 150333 }, + { url = "https://files.pythonhosted.org/packages/f9/d2/466a9be1f32d89eb1554cf84073a5ed9262047acee1ab39cbaefc19635d2/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7", size = 142921 }, + { url = "https://files.pythonhosted.org/packages/f8/01/344ec40cf5d85c1da3c1f57566c59e0c9b56bcc5566c08804a95a6cc8257/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3", size = 144785 }, + { url = "https://files.pythonhosted.org/packages/73/8b/2102692cb6d7e9f03b9a33a710e0164cadfce312872e3efc7cfe22ed26b4/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907", size = 146631 }, + { url = "https://files.pythonhosted.org/packages/d8/96/cc2c1b5d994119ce9f088a9a0c3ebd489d360a2eb058e2c8049f27092847/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b", size = 140867 }, + { url = "https://files.pythonhosted.org/packages/c9/27/cde291783715b8ec30a61c810d0120411844bc4c23b50189b81188b273db/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912", size = 149273 }, + { url = "https://files.pythonhosted.org/packages/3a/a4/8633b0fc1a2d1834d5393dafecce4a1cc56727bfd82b4dc18fc92f0d3cc3/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95", size = 152437 }, + { url = "https://files.pythonhosted.org/packages/64/ea/69af161062166b5975ccbb0961fd2384853190c70786f288684490913bf5/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e", size = 150087 }, + { url = "https://files.pythonhosted.org/packages/3b/fd/e60a9d9fd967f4ad5a92810138192f825d77b4fa2a557990fd575a47695b/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe", size = 145142 }, + { url = "https://files.pythonhosted.org/packages/6d/02/8cb0988a1e49ac9ce2eed1e07b77ff118f2923e9ebd0ede41ba85f2dcb04/charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc", size = 94701 }, + { url = "https://files.pythonhosted.org/packages/d6/20/f1d4670a8a723c46be695dff449d86d6092916f9e99c53051954ee33a1bc/charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749", size = 102191 }, + { url = "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", size = 193339 }, + { url = "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", size = 124366 }, + { url = "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", size = 118874 }, + { url = "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", size = 138243 }, + { url = "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", size = 148676 }, + { url = "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", size = 141289 }, + { url = "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", size = 142585 }, + { url = "https://files.pythonhosted.org/packages/3b/a0/a68980ab8a1f45a36d9745d35049c1af57d27255eff8c907e3add84cf68f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", size = 144408 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", size = 139076 }, + { url = "https://files.pythonhosted.org/packages/fb/9d/9c13753a5a6e0db4a0a6edb1cef7aee39859177b64e1a1e748a6e3ba62c2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", size = 146874 }, + { url = "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", size = 150871 }, + { url = "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", size = 148546 }, + { url = "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", size = 143048 }, + { url = "https://files.pythonhosted.org/packages/01/f8/38842422988b795220eb8038745d27a675ce066e2ada79516c118f291f07/charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", size = 94389 }, + { url = "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", size = 101752 }, + { url = "https://files.pythonhosted.org/packages/d3/0b/4b7a70987abf9b8196845806198975b6aab4ce016632f817ad758a5aa056/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", size = 194445 }, + { url = "https://files.pythonhosted.org/packages/50/89/354cc56cf4dd2449715bc9a0f54f3aef3dc700d2d62d1fa5bbea53b13426/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", size = 125275 }, + { url = "https://files.pythonhosted.org/packages/fa/44/b730e2a2580110ced837ac083d8ad222343c96bb6b66e9e4e706e4d0b6df/charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", size = 119020 }, + { url = "https://files.pythonhosted.org/packages/9d/e4/9263b8240ed9472a2ae7ddc3e516e71ef46617fe40eaa51221ccd4ad9a27/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", size = 139128 }, + { url = "https://files.pythonhosted.org/packages/6b/e3/9f73e779315a54334240353eaea75854a9a690f3f580e4bd85d977cb2204/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", size = 149277 }, + { url = "https://files.pythonhosted.org/packages/1a/cf/f1f50c2f295312edb8a548d3fa56a5c923b146cd3f24114d5adb7e7be558/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", size = 142174 }, + { url = "https://files.pythonhosted.org/packages/16/92/92a76dc2ff3a12e69ba94e7e05168d37d0345fa08c87e1fe24d0c2a42223/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", size = 143838 }, + { url = "https://files.pythonhosted.org/packages/a4/01/2117ff2b1dfc61695daf2babe4a874bca328489afa85952440b59819e9d7/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", size = 146149 }, + { url = "https://files.pythonhosted.org/packages/f6/9b/93a332b8d25b347f6839ca0a61b7f0287b0930216994e8bf67a75d050255/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", size = 140043 }, + { url = "https://files.pythonhosted.org/packages/ab/f6/7ac4a01adcdecbc7a7587767c776d53d369b8b971382b91211489535acf0/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", size = 148229 }, + { url = "https://files.pythonhosted.org/packages/9d/be/5708ad18161dee7dc6a0f7e6cf3a88ea6279c3e8484844c0590e50e803ef/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", size = 151556 }, + { url = "https://files.pythonhosted.org/packages/5a/bb/3d8bc22bacb9eb89785e83e6723f9888265f3a0de3b9ce724d66bd49884e/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", size = 149772 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/d3fc622de05a86f30beea5fc4e9ac46aead4731e73fd9055496732bcc0a4/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", size = 144800 }, + { url = "https://files.pythonhosted.org/packages/9a/65/bdb9bc496d7d190d725e96816e20e2ae3a6fa42a5cac99c3c3d6ff884118/charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", size = 94836 }, + { url = "https://files.pythonhosted.org/packages/3e/67/7b72b69d25b89c0b3cea583ee372c43aa24df15f0e0f8d3982c57804984b/charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", size = 102187 }, + { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 }, + { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 }, + { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 }, + { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 }, + { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 }, + { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 }, + { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 }, + { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 }, + { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 }, + { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 }, + { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 }, + { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 }, + { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, + { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, + { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, + { url = "https://files.pythonhosted.org/packages/54/2f/28659eee7f5d003e0f5a3b572765bf76d6e0fe6601ab1f1b1dd4cba7e4f1/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa", size = 196326 }, + { url = "https://files.pythonhosted.org/packages/d1/18/92869d5c0057baa973a3ee2af71573be7b084b3c3d428fe6463ce71167f8/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a", size = 125614 }, + { url = "https://files.pythonhosted.org/packages/d6/27/327904c5a54a7796bb9f36810ec4173d2df5d88b401d2b95ef53111d214e/charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0", size = 120450 }, + { url = "https://files.pythonhosted.org/packages/a4/23/65af317914a0308495133b2d654cf67b11bbd6ca16637c4e8a38f80a5a69/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a", size = 140135 }, + { url = "https://files.pythonhosted.org/packages/f2/41/6190102ad521a8aa888519bb014a74251ac4586cde9b38e790901684f9ab/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242", size = 150413 }, + { url = "https://files.pythonhosted.org/packages/7b/ab/f47b0159a69eab9bd915591106859f49670c75f9a19082505ff16f50efc0/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b", size = 142992 }, + { url = "https://files.pythonhosted.org/packages/28/89/60f51ad71f63aaaa7e51a2a2ad37919985a341a1d267070f212cdf6c2d22/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62", size = 144871 }, + { url = "https://files.pythonhosted.org/packages/0c/48/0050550275fea585a6e24460b42465020b53375017d8596c96be57bfabca/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0", size = 146756 }, + { url = "https://files.pythonhosted.org/packages/dc/b5/47f8ee91455946f745e6c9ddbb0f8f50314d2416dd922b213e7d5551ad09/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd", size = 141034 }, + { url = "https://files.pythonhosted.org/packages/84/79/5c731059ebab43e80bf61fa51666b9b18167974b82004f18c76378ed31a3/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be", size = 149434 }, + { url = "https://files.pythonhosted.org/packages/ca/f3/0719cd09fc4dc42066f239cb3c48ced17fc3316afca3e2a30a4756fe49ab/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d", size = 152443 }, + { url = "https://files.pythonhosted.org/packages/f7/0e/c6357297f1157c8e8227ff337e93fd0a90e498e3d6ab96b2782204ecae48/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3", size = 150294 }, + { url = "https://files.pythonhosted.org/packages/54/9a/acfa96dc4ea8c928040b15822b59d0863d6e1757fba8bd7de3dc4f761c13/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742", size = 145314 }, + { url = "https://files.pythonhosted.org/packages/73/1c/b10a63032eaebb8d7bcb8544f12f063f41f5f463778ac61da15d9985e8b6/charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2", size = 94724 }, + { url = "https://files.pythonhosted.org/packages/c5/77/3a78bf28bfaa0863f9cfef278dbeadf55efe064eafff8c7c424ae3c4c1bf/charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca", size = 102159 }, + { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, +] + +[package.optional-dependencies] +socks = [ + { name = "socksio" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + +[[package]] +name = "normal" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "httpx", extra = ["socks"] }, + { name = "requests" }, +] + +[package.optional-dependencies] +json = [ + { name = "orjson" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, +] + +[package.metadata] +requires-dist = [ + { name = "httpx", extras = ["socks"], specifier = "==0.28.1" }, + { name = "orjson", marker = "extra == 'json'", specifier = "==3.10.12" }, + { name = "requests", specifier = "==2.32.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "pytest", specifier = "==8.3.4" }] + +[[package]] +name = "orjson" +version = "3.10.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/04/bb9f72987e7f62fb591d6c880c0caaa16238e4e530cbc3bdc84a7372d75f/orjson-3.10.12.tar.gz", hash = "sha256:0a78bbda3aea0f9f079057ee1ee8a1ecf790d4f1af88dd67493c6b8ee52506ff", size = 5438647 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/d2/78652b67f86d093dca984ce3fa5bf819ee1462627da83e7d0b784a9a7c45/orjson-3.10.12-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ece01a7ec71d9940cc654c482907a6b65df27251255097629d0dea781f255c6d", size = 248688 }, + { url = "https://files.pythonhosted.org/packages/70/cb/f8b6a52f3bc724edf8a62d8d1d8ee17cf19d6ae1cac89f077f0e7c30f396/orjson-3.10.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c34ec9aebc04f11f4b978dd6caf697a2df2dd9b47d35aa4cc606cabcb9df69d7", size = 136952 }, + { url = "https://files.pythonhosted.org/packages/a6/43/c55700df9814545bc8c35d87395ec4b9ee473a3c1f5ed72f8d3ad0298ee9/orjson-3.10.12-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd6ec8658da3480939c79b9e9e27e0db31dffcd4ba69c334e98c9976ac29140e", size = 149089 }, + { url = "https://files.pythonhosted.org/packages/07/da/e7e7d73bd971710b736fbd8330b8830c5fa4fc0ac003b31af61f03b26dfc/orjson-3.10.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17e6baf4cf01534c9de8a16c0c611f3d94925d1701bf5f4aff17003677d8ced", size = 140479 }, + { url = "https://files.pythonhosted.org/packages/08/49/c9dfddba56ff24eecfacf2f01a76cae4d249ac2995b1359bf63a74b1b318/orjson-3.10.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6402ebb74a14ef96f94a868569f5dccf70d791de49feb73180eb3c6fda2ade56", size = 156564 }, + { url = "https://files.pythonhosted.org/packages/96/df/174d2eff227dc23b4540a0c2efa6ec8fe406c442c4b7f0f556242f026d1f/orjson-3.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0000758ae7c7853e0a4a6063f534c61656ebff644391e1f81698c1b2d2fc8cd2", size = 131282 }, + { url = "https://files.pythonhosted.org/packages/6a/96/8628c53a52e2a0a1ee861d809092df72aabbd312c71de9ad6d49e2c039ab/orjson-3.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:888442dcee99fd1e5bd37a4abb94930915ca6af4db50e23e746cdf4d1e63db13", size = 139764 }, + { url = "https://files.pythonhosted.org/packages/38/17/08becb49e59e7bb7b29dc1dad19bc0c48635e627ee27e60eb5b64efcf7b1/orjson-3.10.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c1f7a3ce79246aa0e92f5458d86c54f257fb5dfdc14a192651ba7ec2c00f8a05", size = 131913 }, + { url = "https://files.pythonhosted.org/packages/2a/05/f32acc2500e3fafee9445eb8b2a6ff19c4641035e6059c6c8d7bdb3abc9e/orjson-3.10.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:802a3935f45605c66fb4a586488a38af63cb37aaad1c1d94c982c40dcc452e85", size = 415782 }, + { url = "https://files.pythonhosted.org/packages/06/03/6cc740d998d8bb60e75d4b7e228d18964475239ac842cc1865d49d092545/orjson-3.10.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1da1ef0113a2be19bb6c557fb0ec2d79c92ebd2fed4cfb1b26bab93f021fb885", size = 142383 }, + { url = "https://files.pythonhosted.org/packages/f8/30/39cac82547fe021615376245c558b216d3ae8c99bd6b2274f312e49f1c94/orjson-3.10.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a3273e99f367f137d5b3fecb5e9f45bcdbfac2a8b2f32fbc72129bbd48789c2", size = 130661 }, + { url = "https://files.pythonhosted.org/packages/95/29/c6837f4fc1eaa742eaf5abcd767ab6805493f44fe1f72b37c1743706c1d8/orjson-3.10.12-cp310-none-win32.whl", hash = "sha256:475661bf249fd7907d9b0a2a2421b4e684355a77ceef85b8352439a9163418c3", size = 143625 }, + { url = "https://files.pythonhosted.org/packages/f6/62/c6b955f2144421108fa441b5471e1d5f8654a7df9840b261106e04d5d15c/orjson-3.10.12-cp310-none-win_amd64.whl", hash = "sha256:87251dc1fb2b9e5ab91ce65d8f4caf21910d99ba8fb24b49fd0c118b2362d509", size = 135075 }, + { url = "https://files.pythonhosted.org/packages/d3/48/7c3cd094488f5a3bc58488555244609a8c4d105bc02f2b77e509debf0450/orjson-3.10.12-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a734c62efa42e7df94926d70fe7d37621c783dea9f707a98cdea796964d4cf74", size = 248687 }, + { url = "https://files.pythonhosted.org/packages/ff/90/e55f0e25c7fdd1f82551fe787f85df6f378170caca863c04c810cd8f2730/orjson-3.10.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:750f8b27259d3409eda8350c2919a58b0cfcd2054ddc1bd317a643afc646ef23", size = 136953 }, + { url = "https://files.pythonhosted.org/packages/2a/b3/109c020cf7fee747d400de53b43b183ca9d3ebda3906ad0b858eb5479718/orjson-3.10.12-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb52c22bfffe2857e7aa13b4622afd0dd9d16ea7cc65fd2bf318d3223b1b6252", size = 149090 }, + { url = "https://files.pythonhosted.org/packages/96/d4/35c0275dc1350707d182a1b5da16d1184b9439848060af541285407f18f9/orjson-3.10.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:440d9a337ac8c199ff8251e100c62e9488924c92852362cd27af0e67308c16ef", size = 140480 }, + { url = "https://files.pythonhosted.org/packages/3b/79/f863ff460c291ad2d882cc3b580cc444bd4ec60c9df55f6901e6c9a3f519/orjson-3.10.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9e15c06491c69997dfa067369baab3bf094ecb74be9912bdc4339972323f252", size = 156564 }, + { url = "https://files.pythonhosted.org/packages/98/7e/8d5835449ddd873424ee7b1c4ba73a0369c1055750990d824081652874d6/orjson-3.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:362d204ad4b0b8724cf370d0cd917bb2dc913c394030da748a3bb632445ce7c4", size = 131279 }, + { url = "https://files.pythonhosted.org/packages/46/f5/d34595b6d7f4f984c6fef289269a7f98abcdc2445ebdf90e9273487dda6b/orjson-3.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b57cbb4031153db37b41622eac67329c7810e5f480fda4cfd30542186f006ae", size = 139764 }, + { url = "https://files.pythonhosted.org/packages/b3/5b/ee6e9ddeab54a7b7806768151c2090a2d36025bc346a944f51cf172ef7f7/orjson-3.10.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:165c89b53ef03ce0d7c59ca5c82fa65fe13ddf52eeb22e859e58c237d4e33b9b", size = 131915 }, + { url = "https://files.pythonhosted.org/packages/c4/45/febee5951aef6db5cd8cdb260548101d7ece0ca9d4ddadadf1766306b7a4/orjson-3.10.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5dee91b8dfd54557c1a1596eb90bcd47dbcd26b0baaed919e6861f076583e9da", size = 415783 }, + { url = "https://files.pythonhosted.org/packages/27/a5/5a8569e49f3a6c093bee954a3de95062a231196f59e59df13a48e2420081/orjson-3.10.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a4e1cfb72de6f905bdff061172adfb3caf7a4578ebf481d8f0530879476c07", size = 142387 }, + { url = "https://files.pythonhosted.org/packages/6e/05/02550fb38c5bf758f3994f55401233a2ef304e175f473f2ac6dbf464cc8b/orjson-3.10.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:038d42c7bc0606443459b8fe2d1f121db474c49067d8d14c6a075bbea8bf14dd", size = 130664 }, + { url = "https://files.pythonhosted.org/packages/8c/f4/ba31019d0646ce51f7ac75af6dabf98fd89dbf8ad87a9086da34710738e7/orjson-3.10.12-cp311-none-win32.whl", hash = "sha256:03b553c02ab39bed249bedd4abe37b2118324d1674e639b33fab3d1dafdf4d79", size = 143623 }, + { url = "https://files.pythonhosted.org/packages/83/fe/babf08842b989acf4c46103fefbd7301f026423fab47e6f3ba07b54d7837/orjson-3.10.12-cp311-none-win_amd64.whl", hash = "sha256:8b8713b9e46a45b2af6b96f559bfb13b1e02006f4242c156cbadef27800a55a8", size = 135074 }, + { url = "https://files.pythonhosted.org/packages/a1/2f/989adcafad49afb535da56b95d8f87d82e748548b2a86003ac129314079c/orjson-3.10.12-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53206d72eb656ca5ac7d3a7141e83c5bbd3ac30d5eccfe019409177a57634b0d", size = 248678 }, + { url = "https://files.pythonhosted.org/packages/69/b9/8c075e21a50c387649db262b618ebb7e4d40f4197b949c146fc225dd23da/orjson-3.10.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac8010afc2150d417ebda810e8df08dd3f544e0dd2acab5370cfa6bcc0662f8f", size = 136763 }, + { url = "https://files.pythonhosted.org/packages/87/d3/78edf10b4ab14c19f6d918cf46a145818f4aca2b5a1773c894c5490d3a4c/orjson-3.10.12-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed459b46012ae950dd2e17150e838ab08215421487371fa79d0eced8d1461d70", size = 149137 }, + { url = "https://files.pythonhosted.org/packages/16/81/5db8852bdf990a0ddc997fa8f16b80895b8cc77c0fe3701569ed2b4b9e78/orjson-3.10.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dcb9673f108a93c1b52bfc51b0af422c2d08d4fc710ce9c839faad25020bb69", size = 140567 }, + { url = "https://files.pythonhosted.org/packages/fa/a6/9ce1e3e3db918512efadad489630c25841eb148513d21dab96f6b4157fa1/orjson-3.10.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22a51ae77680c5c4652ebc63a83d5255ac7d65582891d9424b566fb3b5375ee9", size = 156620 }, + { url = "https://files.pythonhosted.org/packages/47/d4/05133d6bea24e292d2f7628b1e19986554f7d97b6412b3e51d812e38db2d/orjson-3.10.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910fdf2ac0637b9a77d1aad65f803bac414f0b06f720073438a7bd8906298192", size = 131555 }, + { url = "https://files.pythonhosted.org/packages/b9/7a/b3fbffda8743135c7811e95dc2ab7cdbc5f04999b83c2957d046f1b3fac9/orjson-3.10.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:24ce85f7100160936bc2116c09d1a8492639418633119a2224114f67f63a4559", size = 139743 }, + { url = "https://files.pythonhosted.org/packages/b5/13/95bbcc9a6584aa083da5ce5004ce3d59ea362a542a0b0938d884fd8790b6/orjson-3.10.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a76ba5fc8dd9c913640292df27bff80a685bed3a3c990d59aa6ce24c352f8fc", size = 131733 }, + { url = "https://files.pythonhosted.org/packages/e8/29/dddbb2ea6e7af426fcc3da65a370618a88141de75c6603313d70768d1df1/orjson-3.10.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ff70ef093895fd53f4055ca75f93f047e088d1430888ca1229393a7c0521100f", size = 415788 }, + { url = "https://files.pythonhosted.org/packages/53/df/4aea59324ac539975919b4705ee086aced38e351a6eb3eea0f5071dd5661/orjson-3.10.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f4244b7018b5753ecd10a6d324ec1f347da130c953a9c88432c7fbc8875d13be", size = 142347 }, + { url = "https://files.pythonhosted.org/packages/55/55/a52d83d7c49f8ff44e0daab10554490447d6c658771569e1c662aa7057fe/orjson-3.10.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16135ccca03445f37921fa4b585cff9a58aa8d81ebcb27622e69bfadd220b32c", size = 130829 }, + { url = "https://files.pythonhosted.org/packages/a1/8b/b1beb1624dd4adf7d72e2d9b73c4b529e7851c0c754f17858ea13e368b33/orjson-3.10.12-cp312-none-win32.whl", hash = "sha256:2d879c81172d583e34153d524fcba5d4adafbab8349a7b9f16ae511c2cee8708", size = 143659 }, + { url = "https://files.pythonhosted.org/packages/13/91/634c9cd0bfc6a857fc8fab9bf1a1bd9f7f3345e0d6ca5c3d4569ceb6dcfa/orjson-3.10.12-cp312-none-win_amd64.whl", hash = "sha256:fc23f691fa0f5c140576b8c365bc942d577d861a9ee1142e4db468e4e17094fb", size = 135221 }, + { url = "https://files.pythonhosted.org/packages/1b/bb/3f560735f46fa6f875a9d7c4c2171a58cfb19f56a633d5ad5037a924f35f/orjson-3.10.12-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47962841b2a8aa9a258b377f5188db31ba49af47d4003a32f55d6f8b19006543", size = 248662 }, + { url = "https://files.pythonhosted.org/packages/a3/df/54817902350636cc9270db20486442ab0e4db33b38555300a1159b439d16/orjson-3.10.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6334730e2532e77b6054e87ca84f3072bee308a45a452ea0bffbbbc40a67e296", size = 126055 }, + { url = "https://files.pythonhosted.org/packages/2e/77/55835914894e00332601a74540840f7665e81f20b3e2b9a97614af8565ed/orjson-3.10.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:accfe93f42713c899fdac2747e8d0d5c659592df2792888c6c5f829472e4f85e", size = 131507 }, + { url = "https://files.pythonhosted.org/packages/33/9e/b91288361898e3158062a876b5013c519a5d13e692ac7686e3486c4133ab/orjson-3.10.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7974c490c014c48810d1dede6c754c3cc46598da758c25ca3b4001ac45b703f", size = 131686 }, + { url = "https://files.pythonhosted.org/packages/b2/15/08ce117d60a4d2d3fd24e6b21db463139a658e9f52d22c9c30af279b4187/orjson-3.10.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3f250ce7727b0b2682f834a3facff88e310f52f07a5dcfd852d99637d386e79e", size = 415710 }, + { url = "https://files.pythonhosted.org/packages/71/af/c09da5ed58f9c002cf83adff7a4cdf3e6cee742aa9723395f8dcdb397233/orjson-3.10.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f31422ff9486ae484f10ffc51b5ab2a60359e92d0716fcce1b3593d7bb8a9af6", size = 142305 }, + { url = "https://files.pythonhosted.org/packages/17/d1/8612038d44f33fae231e9ba480d273bac2b0383ce9e77cb06bede1224ae3/orjson-3.10.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5f29c5d282bb2d577c2a6bbde88d8fdcc4919c593f806aac50133f01b733846e", size = 130815 }, + { url = "https://files.pythonhosted.org/packages/67/2c/d5f87834be3591555cfaf9aecdf28f480a6f0b4afeaac53bad534bf9518f/orjson-3.10.12-cp313-none-win32.whl", hash = "sha256:f45653775f38f63dc0e6cd4f14323984c3149c05d6007b58cb154dd080ddc0dc", size = 143664 }, + { url = "https://files.pythonhosted.org/packages/6a/05/7d768fa3ca23c9b3e1e09117abeded1501119f1d8de0ab722938c91ab25d/orjson-3.10.12-cp313-none-win_amd64.whl", hash = "sha256:229994d0c376d5bdc91d92b3c9e6be2f1fbabd4cc1b59daae1443a46ee5e9825", size = 134944 }, + { url = "https://files.pythonhosted.org/packages/01/50/5a52cfe65fc70e7b843cbe143b850313095d4e45f99aeb278b4b3691f3cf/orjson-3.10.12-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f29de3ef71a42a5822765def1febfb36e0859d33abf5c2ad240acad5c6a1b78d", size = 249130 }, + { url = "https://files.pythonhosted.org/packages/af/42/adb00fc60890e57ee6022257d70d9a20dfd28bfd955401e2d02a60192226/orjson-3.10.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de365a42acc65d74953f05e4772c974dad6c51cfc13c3240899f534d611be967", size = 136784 }, + { url = "https://files.pythonhosted.org/packages/f5/f6/5ef130a2e28a0c633c82da67224212fa84b17f93d9d768c255f389d66641/orjson-3.10.12-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a5a0158648a67ff0004cb0df5df7dcc55bfc9ca154d9c01597a23ad54c8d0c", size = 148936 }, + { url = "https://files.pythonhosted.org/packages/54/80/f40805bb094d3470bcfca8d30ae9f4606bb90c809190fee18c17a4653956/orjson-3.10.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c47ce6b8d90fe9646a25b6fb52284a14ff215c9595914af63a5933a49972ce36", size = 140291 }, + { url = "https://files.pythonhosted.org/packages/b4/0a/c91265a075af28fcb118a9a690dccc0f31c52dd7f486f5cc73aa6f9a69b4/orjson-3.10.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0eee4c2c5bfb5c1b47a5db80d2ac7aaa7e938956ae88089f098aff2c0f35d5d8", size = 156335 }, + { url = "https://files.pythonhosted.org/packages/6f/1f/c8fc64b25e2e4a5fa0fb514a0325719e99461c088a3b659954a57b8c1f3c/orjson-3.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d3081bbe8b86587eb5c98a73b97f13d8f9fea685cf91a579beddacc0d10566", size = 131118 }, + { url = "https://files.pythonhosted.org/packages/b3/f7/f5dba457bbc6aaf8ebd0131a17eb672835d2ea31f763d1462c191902bc10/orjson-3.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c23a6e90383884068bc2dba83d5222c9fcc3b99a0ed2411d38150734236755", size = 139573 }, + { url = "https://files.pythonhosted.org/packages/85/03/87091a1c831076e8d6ed0be19d30bd837d3c27e29f43b6b2dc23efee3d29/orjson-3.10.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5472be7dc3269b4b52acba1433dac239215366f89dc1d8d0e64029abac4e714e", size = 131760 }, + { url = "https://files.pythonhosted.org/packages/53/70/956ca7999fe43b5e2ca51248f732850acaaf00f8fa5b8f7924bc504157bb/orjson-3.10.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:7319cda750fca96ae5973efb31b17d97a5c5225ae0bc79bf5bf84df9e1ec2ab6", size = 415605 }, + { url = "https://files.pythonhosted.org/packages/ca/7f/4f49c1a9da03e383198c0fa418cc4262d01d70931742dfc504c2a495ed7b/orjson-3.10.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:74d5ca5a255bf20b8def6a2b96b1e18ad37b4a122d59b154c458ee9494377f80", size = 142208 }, + { url = "https://files.pythonhosted.org/packages/81/d9/0216c950e295b1c493510ef546b80328dc06e2ae4a82bc693386e4cdebeb/orjson-3.10.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ff31d22ecc5fb85ef62c7d4afe8301d10c558d00dd24274d4bbe464380d3cd69", size = 130495 }, + { url = "https://files.pythonhosted.org/packages/1a/d0/70d97b583d628a307d4bc1f96f7ab6cf137e32849c06ea03d4337ad19e14/orjson-3.10.12-cp39-none-win32.whl", hash = "sha256:c22c3ea6fba91d84fcb4cda30e64aff548fcf0c44c876e681f47d61d24b12e6b", size = 143467 }, + { url = "https://files.pythonhosted.org/packages/ec/a3/725e4cac70d2a88f5fc4f9eed451e12d594063823feb931c30ac1394d26f/orjson-3.10.12-cp39-none-win_amd64.whl", hash = "sha256:be604f60d45ace6b0b33dd990a66b4526f1a7a186ac411c942674625456ca548", size = 134927 }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "pytest" +version = "8.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, +] + +[[package]] +name = "requests" +version = "2.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/a2/423f4d16d6934ef502f10ad56673719dd4345e656aedbd6687ccc359ffc5/requests-2.32.0.tar.gz", hash = "sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8", size = 114373 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/e8/09e8d662a9675a4e4f5dd7a8e6127b463a091d2703ed931a64aa66d00065/requests-2.32.0-py3-none-any.whl", hash = "sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5", size = 63695 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] \ No newline at end of file diff --git a/pkg/dependency/parser/python/uv/testdata/uv_without_root.lock b/pkg/dependency/parser/python/uv/testdata/uv_without_root.lock new file mode 100644 index 000000000000..a105e74f266a --- /dev/null +++ b/pkg/dependency/parser/python/uv/testdata/uv_without_root.lock @@ -0,0 +1,11 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "asyncio" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/54/054bafaf2c0fb8473d423743e191fcdf49b2c1fd5e9af3524efbe097bafd/asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41", size = 204411 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/74/07679c5b9f98a7cb0fc147b1ef1cc1853bc07a4eb9cb5731e24732c5f773/asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d", size = 101767 }, +] \ No newline at end of file diff --git a/pkg/dependency/parser/ruby/gemspec/parse_test.go b/pkg/dependency/parser/ruby/gemspec/parse_test.go index dbf13826f7e0..317af0a2ce00 100644 --- a/pkg/dependency/parser/ruby/gemspec/parse_test.go +++ b/pkg/dependency/parser/ruby/gemspec/parse_test.go @@ -83,8 +83,7 @@ func TestParse(t *testing.T) { got, _, err := gemspec.NewParser().Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } assert.Equal(t, tt.want, got) diff --git a/pkg/dependency/parser/rust/binary/parse_test.go b/pkg/dependency/parser/rust/binary/parse_test.go index 1c1eb1c586f2..b49ce3b65047 100644 --- a/pkg/dependency/parser/rust/binary/parse_test.go +++ b/pkg/dependency/parser/rust/binary/parse_test.go @@ -77,8 +77,7 @@ func TestParse(t *testing.T) { got, gotDeps, err := binary.NewParser().Parse(f) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/dependency/parser/sbt/lockfile/parse.go b/pkg/dependency/parser/sbt/lockfile/parse.go index 3b5b1865903d..040a490c83b3 100644 --- a/pkg/dependency/parser/sbt/lockfile/parse.go +++ b/pkg/dependency/parser/sbt/lockfile/parse.go @@ -5,9 +5,9 @@ import ( "slices" "sort" - "github.com/liamg/jfather" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" xio "github.com/aquasecurity/trivy/pkg/x/io" diff --git a/pkg/dependency/parser/swift/swift/parse.go b/pkg/dependency/parser/swift/swift/parse.go index aefa2a066faf..7ebfb84c8932 100644 --- a/pkg/dependency/parser/swift/swift/parse.go +++ b/pkg/dependency/parser/swift/swift/parse.go @@ -5,10 +5,10 @@ import ( "sort" "strings" - "github.com/liamg/jfather" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/dependency" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" diff --git a/pkg/dependency/parser/utils/utils.go b/pkg/dependency/parser/utils/utils.go index ce2aff36976b..36afd9025310 100644 --- a/pkg/dependency/parser/utils/utils.go +++ b/pkg/dependency/parser/utils/utils.go @@ -10,19 +10,6 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) -func UniqueStrings(ss []string) []string { - var results []string - uniq := make(map[string]struct{}) - for _, s := range ss { - if _, ok := uniq[s]; ok { - continue - } - results = append(results, s) - uniq[s] = struct{}{} - } - return results -} - func UniquePackages(pkgs []ftypes.Package) []ftypes.Package { if len(pkgs) == 0 { return nil diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index 152096c2caea..158bf94c5924 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -48,7 +48,7 @@ func NewDriver(libType ftypes.LangType) (Driver, bool) { case ftypes.NuGet, ftypes.DotNetCore, ftypes.PackagesProps: ecosystem = vulnerability.NuGet comparer = compare.GenericComparer{} - case ftypes.Pipenv, ftypes.Poetry, ftypes.Pip, ftypes.PythonPkg: + case ftypes.Pipenv, ftypes.Poetry, ftypes.Pip, ftypes.PythonPkg, ftypes.Uv: ecosystem = vulnerability.Pip comparer = pep440.Comparer{} case ftypes.Pub: diff --git a/pkg/detector/library/driver_test.go b/pkg/detector/library/driver_test.go index cf8af718f783..dc82b5806701 100644 --- a/pkg/detector/library/driver_test.go +++ b/pkg/detector/library/driver_test.go @@ -220,8 +220,7 @@ func TestDriver_Detect(t *testing.T) { got, err := driver.DetectVulnerabilities("", tt.args.pkgName, tt.args.pkgVer) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/detector/ospkg/alma/alma_test.go b/pkg/detector/ospkg/alma/alma_test.go index c736f4b12c74..220c7886e59d 100644 --- a/pkg/detector/ospkg/alma/alma_test.go +++ b/pkg/detector/ospkg/alma/alma_test.go @@ -165,8 +165,7 @@ func TestScanner_Detect(t *testing.T) { s := alma.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/alpine/alpine.go b/pkg/detector/ospkg/alpine/alpine.go index 063c3018f3f1..a3baa8571aa3 100644 --- a/pkg/detector/ospkg/alpine/alpine.go +++ b/pkg/detector/ospkg/alpine/alpine.go @@ -48,6 +48,7 @@ var ( "3.18": time.Date(2025, 5, 9, 23, 59, 59, 0, time.UTC), "3.19": time.Date(2025, 11, 1, 23, 59, 59, 0, time.UTC), "3.20": time.Date(2026, 04, 1, 23, 59, 59, 0, time.UTC), + "3.21": time.Date(2026, 12, 5, 23, 59, 59, 0, time.UTC), "edge": time.Date(9999, 1, 1, 0, 0, 0, 0, time.UTC), } ) diff --git a/pkg/detector/ospkg/alpine/alpine_test.go b/pkg/detector/ospkg/alpine/alpine_test.go index 9dad87c4b50d..cf8e62dc953e 100644 --- a/pkg/detector/ospkg/alpine/alpine_test.go +++ b/pkg/detector/ospkg/alpine/alpine_test.go @@ -254,8 +254,7 @@ func TestScanner_Detect(t *testing.T) { s := alpine.NewScanner() got, err := s.Detect(nil, tt.args.osVer, tt.args.repo, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/detector/ospkg/amazon/amazon_test.go b/pkg/detector/ospkg/amazon/amazon_test.go index 98adad931959..10baa8b70599 100644 --- a/pkg/detector/ospkg/amazon/amazon_test.go +++ b/pkg/detector/ospkg/amazon/amazon_test.go @@ -180,8 +180,7 @@ func TestScanner_Detect(t *testing.T) { s := amazon.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/azure/azure_test.go b/pkg/detector/ospkg/azure/azure_test.go index cc9f0a92d2af..dd428f197e4d 100644 --- a/pkg/detector/ospkg/azure/azure_test.go +++ b/pkg/detector/ospkg/azure/azure_test.go @@ -187,8 +187,7 @@ func TestScanner_Detect(t *testing.T) { } got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/chainguard/chainguard_test.go b/pkg/detector/ospkg/chainguard/chainguard_test.go index 0c49077aee3e..cd5d7daea335 100644 --- a/pkg/detector/ospkg/chainguard/chainguard_test.go +++ b/pkg/detector/ospkg/chainguard/chainguard_test.go @@ -196,8 +196,7 @@ func TestScanner_Detect(t *testing.T) { s := chainguard.NewScanner() got, err := s.Detect(nil, "", tt.args.repo, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/detector/ospkg/debian/debian_test.go b/pkg/detector/ospkg/debian/debian_test.go index 790067c293ff..ef7edbb7a1f4 100644 --- a/pkg/detector/ospkg/debian/debian_test.go +++ b/pkg/detector/ospkg/debian/debian_test.go @@ -118,8 +118,7 @@ func TestScanner_Detect(t *testing.T) { s := debian.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/detector/ospkg/oracle/oracle.go b/pkg/detector/ospkg/oracle/oracle.go index 3dbc8c90677f..2d3dd0237211 100644 --- a/pkg/detector/ospkg/oracle/oracle.go +++ b/pkg/detector/ospkg/oracle/oracle.go @@ -50,7 +50,7 @@ func (s *Scanner) Detect(ctx context.Context, osVer string, _ *ftypes.Repository var vulns []types.DetectedVulnerability for _, pkg := range pkgs { - advisories, err := s.vs.Get(osVer, pkg.Name) + advisories, err := s.vs.Get(osVer, pkg.Name, pkg.Arch) if err != nil { return nil, xerrors.Errorf("failed to get Oracle Linux advisory: %w", err) } diff --git a/pkg/detector/ospkg/oracle/oracle_test.go b/pkg/detector/ospkg/oracle/oracle_test.go index 834bc06d9406..d33c42f416f7 100644 --- a/pkg/detector/ospkg/oracle/oracle_test.go +++ b/pkg/detector/ospkg/oracle/oracle_test.go @@ -139,6 +139,60 @@ func TestScanner_Detect(t *testing.T) { }, }, }, + { + name: "different fixed versions for different arches", + fixtures: []string{ + "testdata/fixtures/oracle7.yaml", + "testdata/fixtures/data-source.yaml", + }, + args: args{ + osVer: "7", + pkgs: []ftypes.Package{ + { + Name: "rsyslog", + Version: "8.24.0", + Release: "57.0.0.el7", + Arch: "x86_64", + SrcName: "rsyslog", + SrcVersion: "8.24.0", + SrcRelease: "57.0.0.el7", + }, + { + Name: "rsyslog", + Version: "8.24.0", + Release: "57.0.0.el7", + Arch: "aarch64", + SrcName: "rsyslog", + SrcVersion: "8.24.0", + SrcRelease: "57.0.0.el7", + }, + }, + }, + want: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2022-24903", + PkgName: "rsyslog", + InstalledVersion: "8.24.0-57.0.0.el7", + FixedVersion: "8.24.0-57.0.1.el7_9.3", + DataSource: &dbTypes.DataSource{ + ID: vulnerability.OracleOVAL, + Name: "Oracle Linux OVAL definitions", + URL: "https://linux.oracle.com/security/oval/", + }, + }, + { + VulnerabilityID: "CVE-2022-24903", + PkgName: "rsyslog", + InstalledVersion: "8.24.0-57.0.0.el7", + FixedVersion: "8.24.0-57.0.4.el7_9.3", + DataSource: &dbTypes.DataSource{ + ID: vulnerability.OracleOVAL, + Name: "Oracle Linux OVAL definitions", + URL: "https://linux.oracle.com/security/oval/", + }, + }, + }, + }, { name: "without ksplice", fixtures: []string{ @@ -289,8 +343,7 @@ func TestScanner_Detect(t *testing.T) { s := NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/detector/ospkg/oracle/testdata/fixtures/oracle7.yaml b/pkg/detector/ospkg/oracle/testdata/fixtures/oracle7.yaml index 7dce7818c32e..2b5e1e4e3c39 100644 --- a/pkg/detector/ospkg/oracle/testdata/fixtures/oracle7.yaml +++ b/pkg/detector/ospkg/oracle/testdata/fixtures/oracle7.yaml @@ -7,6 +7,9 @@ FixedVersion: "7.29.0-59.0.1.el7_9.1" Entries: - FixedVersion: "7.29.0-59.0.1.el7_9.1" + Arches: + - x86_64 + - aarch64 - bucket: glibc pairs: - key: CVE-2017-1000364 @@ -14,6 +17,9 @@ FixedVersion: "2:2.17-157.ksplice1.el7_3.4" Entries: - FixedVersion: "2:2.17-157.ksplice1.el7_3.4" + Arches: + - x86_64 + - aarch64 - bucket: gnutls pairs: - key: CVE-2021-20232 @@ -21,5 +27,20 @@ FixedVersion: "3.6.16-4.el8" Entries: - FixedVersion: "10:3.6.16-4.0.1.el8_fips" + Arches: + - x86_64 - FixedVersion: "3.6.16-4.el8" - + Arches: + - x86_64 + - bucket: rsyslog + pairs: + - key: CVE-2022-24903 + value: + FixedVersion: "8.24.0-57.0.1.el7_9.3" + Entries: + - FixedVersion: "8.24.0-57.0.1.el7_9.3" + Arches: + - x86_64 + - FixedVersion: "8.24.0-57.0.4.el7_9.3" + Arches: + - aarch64 diff --git a/pkg/detector/ospkg/photon/photon_test.go b/pkg/detector/ospkg/photon/photon_test.go index 8d68ea08680e..c450960f4c11 100644 --- a/pkg/detector/ospkg/photon/photon_test.go +++ b/pkg/detector/ospkg/photon/photon_test.go @@ -97,8 +97,7 @@ func TestScanner_Detect(t *testing.T) { s := photon.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/redhat/redhat.go b/pkg/detector/ospkg/redhat/redhat.go index d8d9e0052920..d029dcfed945 100644 --- a/pkg/detector/ospkg/redhat/redhat.go +++ b/pkg/detector/ospkg/redhat/redhat.go @@ -9,11 +9,9 @@ import ( "time" version "github.com/knqyf263/go-rpm-version" - "github.com/samber/lo" "golang.org/x/xerrors" dbTypes "github.com/aquasecurity/trivy-db/pkg/types" - ustrings "github.com/aquasecurity/trivy-db/pkg/utils/strings" redhat "github.com/aquasecurity/trivy-db/pkg/vulnsrc/redhat-oval" "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version" @@ -116,24 +114,35 @@ func (s *Scanner) detect(osVer string, pkg ftypes.Package) ([]types.DetectedVuln return nil, xerrors.Errorf("failed to get Red Hat advisories: %w", err) } - installed := utils.FormatVersion(pkg) - installedVersion := version.NewVersion(installed) - - uniqVulns := make(map[string]types.DetectedVulnerability) + // Choose the latest fixed version for each CVE-ID (empty for unpatched vulns). + // Take the single RHSA-ID with the latest fixed version (for patched vulns). + uniqAdvisories := make(map[string]dbTypes.Advisory) for _, adv := range advisories { - // if Arches for advisory is empty or pkg.Arch is "noarch", then any Arches are affected + // If Arches for advisory are empty or pkg.Arch is "noarch", then any Arches are affected if len(adv.Arches) != 0 && pkg.Arch != "noarch" { if !slices.Contains(adv.Arches, pkg.Arch) { continue } } - vulnID := adv.VulnerabilityID + if a, ok := uniqAdvisories[adv.VulnerabilityID]; ok { + if version.NewVersion(a.FixedVersion).LessThan(version.NewVersion(adv.FixedVersion)) { + uniqAdvisories[adv.VulnerabilityID] = adv + } + } else { + uniqAdvisories[adv.VulnerabilityID] = adv + } + } + + var vulns []types.DetectedVulnerability + for _, adv := range uniqAdvisories { vuln := types.DetectedVulnerability{ - VulnerabilityID: vulnID, + VulnerabilityID: adv.VulnerabilityID, + VendorIDs: adv.VendorIDs, // Will be empty for unpatched vulnerabilities PkgID: pkg.ID, PkgName: pkg.Name, InstalledVersion: utils.FormatVersion(pkg), + FixedVersion: version.NewVersion(adv.FixedVersion).String(), // Will be empty for unpatched vulnerabilities PkgIdentifier: pkg.Identifier, Status: adv.Status, Layer: pkg.Layer, @@ -144,43 +153,15 @@ func (s *Scanner) detect(osVer string, pkg ftypes.Package) ([]types.DetectedVuln Custom: adv.Custom, } - // unpatched vulnerabilities - if adv.FixedVersion == "" { - // Red Hat may contain several advisories for the same vulnerability (RHSA advisories). - // To avoid overwriting the fixed version by mistake, we should skip unpatched vulnerabilities if they were added earlier - if _, ok := uniqVulns[vulnID]; !ok { - uniqVulns[vulnID] = vuln - } - continue - } - - // patched vulnerabilities - fixedVersion := version.NewVersion(adv.FixedVersion) - if installedVersion.LessThan(fixedVersion) { - vuln.VendorIDs = adv.VendorIDs - vuln.FixedVersion = fixedVersion.String() - - if v, ok := uniqVulns[vulnID]; ok { - // In case two advisories resolve the same CVE-ID. - // e.g. The first fix might be incomplete. - v.VendorIDs = ustrings.Unique(append(v.VendorIDs, vuln.VendorIDs...)) - - // The newer fixed version should be taken. - if version.NewVersion(v.FixedVersion).LessThan(fixedVersion) { - v.FixedVersion = vuln.FixedVersion - } - uniqVulns[vulnID] = v - } else { - uniqVulns[vulnID] = vuln - } + // Keep unpatched and affected vulnerabilities + if adv.FixedVersion == "" || version.NewVersion(vuln.InstalledVersion).LessThan(version.NewVersion(adv.FixedVersion)) { + vulns = append(vulns, vuln) } } - vulns := lo.Values(uniqVulns) sort.Slice(vulns, func(i, j int) bool { return vulns[i].VulnerabilityID < vulns[j].VulnerabilityID }) - return vulns, nil } diff --git a/pkg/detector/ospkg/redhat/redhat_test.go b/pkg/detector/ospkg/redhat/redhat_test.go index a1a62ac7666e..459aba6f071e 100644 --- a/pkg/detector/ospkg/redhat/redhat_test.go +++ b/pkg/detector/ospkg/redhat/redhat_test.go @@ -79,8 +79,10 @@ func TestScanner_Detect(t *testing.T) { }, }, { - VulnerabilityID: "CVE-2019-12735", - VendorIDs: []string{"RHSA-2019:1619"}, + VulnerabilityID: "CVE-2019-12735", + VendorIDs: []string{ + "RHSA-2019:1619", + }, PkgName: "vim-minimal", InstalledVersion: "2:7.4.160-5.el7", FixedVersion: "2:7.4.160-6.el7_6", @@ -124,8 +126,10 @@ func TestScanner_Detect(t *testing.T) { }, want: []types.DetectedVulnerability{ { - VulnerabilityID: "CVE-2019-17007", - VendorIDs: []string{"RHSA-2021:0876"}, + VulnerabilityID: "CVE-2019-17007", + VendorIDs: []string{ + "RHSA-2021:0876", + }, PkgName: "nss", InstalledVersion: "3.36.0-7.1.el7_6", FixedVersion: "3.36.0-9.el7_6", @@ -141,7 +145,6 @@ func TestScanner_Detect(t *testing.T) { VulnerabilityID: "CVE-2020-12403", VendorIDs: []string{ "RHSA-2021:0538", - "RHSA-2021:0876", }, PkgName: "nss", InstalledVersion: "3.36.0-7.1.el7_6", @@ -156,6 +159,53 @@ func TestScanner_Detect(t *testing.T) { }, }, }, + { + name: "happy path: CVE-ID and RHSA-ID for same vulnerability", + fixtures: []string{ + "testdata/fixtures/redhat.yaml", + "testdata/fixtures/cpe.yaml", + }, + args: args{ + osVer: "8.3", + pkgs: []ftypes.Package{ + { + Name: "expat", + Version: "2.2.5", + Release: "16.el8_10", + Epoch: 0, + Arch: "x86_64", + SrcName: "expat", + SrcVersion: "2.2.5", + SrcRelease: "16.el8_10", + SrcEpoch: 0, + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + BuildInfo: &ftypes.BuildInfo{ + ContentSets: []string{"rhel-8-for-x86_64-baseos-rpms"}, + }, + }, + }, + }, + want: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2024-45490", + VendorIDs: []string{ + "RHSA-2024:6989-3", + }, + PkgName: "expat", + InstalledVersion: "2.2.5-16.el8_10", + FixedVersion: "2.2.5-18.el8_10", + SeveritySource: vulnerability.RedHat, + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityMedium.String(), + }, + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + }, + }, + }, { name: "happy path: package without architecture", fixtures: []string{ @@ -186,8 +236,10 @@ func TestScanner_Detect(t *testing.T) { }, want: []types.DetectedVulnerability{ { - VulnerabilityID: "CVE-2016-5195", - VendorIDs: []string{"RHSA-2017:0372"}, + VulnerabilityID: "CVE-2016-5195", + VendorIDs: []string{ + "RHSA-2017:0372", + }, PkgName: "kernel-headers", InstalledVersion: "3.10.0-1127.19-1.el7", FixedVersion: "4.5.0-15.2.1.el7", @@ -231,8 +283,10 @@ func TestScanner_Detect(t *testing.T) { }, want: []types.DetectedVulnerability{ { - VulnerabilityID: "CVE-2016-5195", - VendorIDs: []string{"RHSA-2016:2098"}, + VulnerabilityID: "CVE-2016-5195", + VendorIDs: []string{ + "RHSA-2016:2098", + }, PkgName: "kernel-headers", InstalledVersion: "3.10.0-326.36-3.el7", FixedVersion: "3.10.0-327.36.3.el7", @@ -266,8 +320,10 @@ func TestScanner_Detect(t *testing.T) { }, want: []types.DetectedVulnerability{ { - VulnerabilityID: "CVE-2019-12735", - VendorIDs: []string{"RHSA-2019:1619"}, + VulnerabilityID: "CVE-2019-12735", + VendorIDs: []string{ + "RHSA-2019:1619", + }, PkgName: "vim-minimal", InstalledVersion: "2:7.4.160-5.el8", FixedVersion: "2:7.4.160-7.el8_7", @@ -308,8 +364,10 @@ func TestScanner_Detect(t *testing.T) { }, want: []types.DetectedVulnerability{ { - VulnerabilityID: "CVE-2019-11043", - VendorIDs: []string{"RHSA-2020:0322"}, + VulnerabilityID: "CVE-2019-11043", + VendorIDs: []string{ + "RHSA-2020:0322", + }, PkgName: "php", InstalledVersion: "7.2.10-1.module_el8.2.0+313+b04d0a66", FixedVersion: "7.2.11-1.1.module+el8.0.0+4664+17bd8d65", diff --git a/pkg/detector/ospkg/redhat/testdata/fixtures/redhat.yaml b/pkg/detector/ospkg/redhat/testdata/fixtures/redhat.yaml index c3ba48072111..74f6805ad052 100644 --- a/pkg/detector/ospkg/redhat/testdata/fixtures/redhat.yaml +++ b/pkg/detector/ospkg/redhat/testdata/fixtures/redhat.yaml @@ -104,4 +104,67 @@ - ID: CVE-2016-5195 Severity: 3 Arches: - - aarch64 \ No newline at end of file + - aarch64 + - bucket: expat + pairs: + - key: RHSA-2024:6989-2 # created for test only + value: + Entries: + - FixedVersion: 0:2.2.5-17.el8_10 + Affected: + - 4 + Arches: + - x86_64 + Cves: + - ID: CVE-2024-45490 + Severity: 2 + - key: RHSA-2024:6989-3 # created for test only + value: + Entries: + - FixedVersion: 0:2.2.5-18.el8_10 + Affected: + - 4 + Arches: + - x86_64 + Cves: + - ID: CVE-2024-45490 + Severity: 2 + - key: CVE-2024-45490 + value: + Entries: + - Affected: + - 4 + Cves: + - Severity: 2 + Status: 5 + - key: CVE-2024-45491 + value: + Entries: + - Affected: + - 4 + Cves: + - Severity: 2 + Status: 5 + - key: RHSA-2024:6989 + value: + Entries: + - FixedVersion: 0:2.2.5-15.el8_10 + Affected: + - 4 + Arches: + - x86_64 + Cves: + - ID: CVE-2024-45490 + Severity: 2 + - ID: CVE-2024-45491 + Severity: 2 + - ID: CVE-2024-45492 + Severity: 2 + - key: CVE-2024-45492 + value: + Entries: + - Affected: + - 4 + Cves: + - Severity: 2 + Status: 5 \ No newline at end of file diff --git a/pkg/detector/ospkg/rocky/rocky_test.go b/pkg/detector/ospkg/rocky/rocky_test.go index ce5ad893bfc2..21ef589b35c0 100644 --- a/pkg/detector/ospkg/rocky/rocky_test.go +++ b/pkg/detector/ospkg/rocky/rocky_test.go @@ -125,8 +125,7 @@ func TestScanner_Detect(t *testing.T) { s := rocky.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/suse/suse_test.go b/pkg/detector/ospkg/suse/suse_test.go index abd21c6478a7..420eb2a0d0d1 100644 --- a/pkg/detector/ospkg/suse/suse_test.go +++ b/pkg/detector/ospkg/suse/suse_test.go @@ -220,8 +220,7 @@ func TestScanner_Detect(t *testing.T) { s := suse.NewScanner(tt.distribution) got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/detector/ospkg/ubuntu/ubuntu_test.go b/pkg/detector/ospkg/ubuntu/ubuntu_test.go index 044ea69b1056..071bbb842240 100644 --- a/pkg/detector/ospkg/ubuntu/ubuntu_test.go +++ b/pkg/detector/ospkg/ubuntu/ubuntu_test.go @@ -182,8 +182,7 @@ func TestScanner_Detect(t *testing.T) { s := ubuntu.NewScanner() got, err := s.Detect(nil, tt.args.osVer, nil, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } sort.Slice(got, func(i, j int) bool { diff --git a/pkg/detector/ospkg/wolfi/wolfi_test.go b/pkg/detector/ospkg/wolfi/wolfi_test.go index 019d6627dc7c..92e9b5fc2d48 100644 --- a/pkg/detector/ospkg/wolfi/wolfi_test.go +++ b/pkg/detector/ospkg/wolfi/wolfi_test.go @@ -196,8 +196,7 @@ func TestScanner_Detect(t *testing.T) { s := wolfi.NewScanner() got, err := s.Detect(nil, "", tt.args.repo, tt.args.pkgs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/fanal/analyzer/all/import.go b/pkg/fanal/analyzer/all/import.go index 5345073fd3cf..c9d50dd4f924 100644 --- a/pkg/fanal/analyzer/all/import.go +++ b/pkg/fanal/analyzer/all/import.go @@ -31,6 +31,7 @@ import ( _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/pip" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/pipenv" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/poetry" + _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/uv" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/ruby/bundler" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/ruby/gemspec" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/rust/binary" diff --git a/pkg/fanal/analyzer/analyzer_test.go b/pkg/fanal/analyzer/analyzer_test.go index d8f93c0aa420..458586447f17 100644 --- a/pkg/fanal/analyzer/analyzer_test.go +++ b/pkg/fanal/analyzer/analyzer_test.go @@ -522,8 +522,7 @@ func TestAnalyzerGroup_AnalyzeFile(t *testing.T) { DisabledAnalyzers: tt.args.disabledAnalyzers, }) if err != nil && tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) @@ -549,8 +548,7 @@ func TestAnalyzerGroup_AnalyzeFile(t *testing.T) { wg.Wait() if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/fanal/analyzer/buildinfo/content_manifest.go b/pkg/fanal/analyzer/buildinfo/content_manifest.go index 7d5372dc7266..ccb4b175a645 100644 --- a/pkg/fanal/analyzer/buildinfo/content_manifest.go +++ b/pkg/fanal/analyzer/buildinfo/content_manifest.go @@ -10,12 +10,18 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/set" ) func init() { analyzer.RegisterAnalyzer(&contentManifestAnalyzer{}) } +var contentSetsDirs = set.New[string]( + "root/buildinfo/content_manifests/", + "usr/share/buildinfo/", // for RHCOS +) + const contentManifestAnalyzerVersion = 1 type contentManifest struct { @@ -44,7 +50,7 @@ func (a contentManifestAnalyzer) Analyze(_ context.Context, target analyzer.Anal func (a contentManifestAnalyzer) Required(filePath string, _ os.FileInfo) bool { dir, file := filepath.Split(filepath.ToSlash(filePath)) - if dir != "root/buildinfo/content_manifests/" { + if !contentSetsDirs.Contains(dir) { return false } return filepath.Ext(file) == ".json" diff --git a/pkg/fanal/analyzer/buildinfo/content_manifest_test.go b/pkg/fanal/analyzer/buildinfo/content_manifest_test.go index 61ad8ebde1cb..e0be767da0c1 100644 --- a/pkg/fanal/analyzer/buildinfo/content_manifest_test.go +++ b/pkg/fanal/analyzer/buildinfo/content_manifest_test.go @@ -55,8 +55,7 @@ func Test_contentManifestAnalyzer_Analyze(t *testing.T) { }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } @@ -73,12 +72,22 @@ func Test_contentManifestAnalyzer_Required(t *testing.T) { want bool }{ { - name: "happy path", + name: "happy path root dir", filePath: "root/buildinfo/content_manifests/nodejs-12-container-1-66.json", want: true, }, { - name: "sad path", + name: "happy path usr dir", + filePath: "usr/share/buildinfo/nodejs-12-container-1-66.json", + want: true, + }, + { + name: "sad path wrong dir", + filePath: "foo/bar/nodejs-12-container-1-66.json", + want: false, + }, + { + name: "sad path wrong extension", filePath: "root/buildinfo/content_manifests/nodejs-12-container-1-66.xml", want: false, }, diff --git a/pkg/fanal/analyzer/const.go b/pkg/fanal/analyzer/const.go index a9733d4b6076..d59d7285c189 100644 --- a/pkg/fanal/analyzer/const.go +++ b/pkg/fanal/analyzer/const.go @@ -81,6 +81,7 @@ const ( TypePip Type = "pip" TypePipenv Type = "pipenv" TypePoetry Type = "poetry" + TypeUv Type = "uv" // Go TypeGoBinary Type = "gobinary" @@ -194,6 +195,7 @@ var ( TypePip, TypePipenv, TypePoetry, + TypeUv, TypeGoBinary, TypeGoMod, TypeRustBinary, @@ -214,6 +216,7 @@ var ( TypePip, TypePipenv, TypePoetry, + TypeUv, TypeGoMod, TypePom, TypeConanLock, diff --git a/pkg/fanal/analyzer/imgconf/apk/apk.go b/pkg/fanal/analyzer/imgconf/apk/apk.go index 04aa244313c1..a43e4838221e 100644 --- a/pkg/fanal/analyzer/imgconf/apk/apk.go +++ b/pkg/fanal/analyzer/imgconf/apk/apk.go @@ -19,6 +19,7 @@ import ( "github.com/aquasecurity/trivy/pkg/dependency" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/set" ) const ( @@ -179,33 +180,30 @@ func (a alpineCmdAnalyzer) parseCommand(command string, envs map[string]string) return pkgs } func (a alpineCmdAnalyzer) resolveDependencies(apkIndexArchive *apkIndex, originalPkgs []string) (pkgs []string) { - uniqPkgs := make(map[string]struct{}) + uniqPkgs := set.New[string]() for _, pkgName := range originalPkgs { - if _, ok := uniqPkgs[pkgName]; ok { + if uniqPkgs.Contains(pkgName) { continue } - seenPkgs := make(map[string]struct{}) + seenPkgs := set.New[string]() for _, p := range a.resolveDependency(apkIndexArchive, pkgName, seenPkgs) { - uniqPkgs[p] = struct{}{} + uniqPkgs.Append(p) } } - for pkg := range uniqPkgs { - pkgs = append(pkgs, pkg) - } - return pkgs + return uniqPkgs.Items() } func (a alpineCmdAnalyzer) resolveDependency(apkIndexArchive *apkIndex, pkgName string, - seenPkgs map[string]struct{}) (pkgNames []string) { + seenPkgs set.Set[string]) (pkgNames []string) { pkg, ok := apkIndexArchive.Package[pkgName] if !ok { return nil } - if _, ok = seenPkgs[pkgName]; ok { + if seenPkgs.Contains(pkgName) { return nil } - seenPkgs[pkgName] = struct{}{} + seenPkgs.Append(pkgName) pkgNames = append(pkgNames, pkgName) for _, dependency := range pkg.Dependencies { diff --git a/pkg/fanal/analyzer/imgconf/apk/apk_test.go b/pkg/fanal/analyzer/imgconf/apk/apk_test.go index 93da80f87e0b..d5e13abccee7 100644 --- a/pkg/fanal/analyzer/imgconf/apk/apk_test.go +++ b/pkg/fanal/analyzer/imgconf/apk/apk_test.go @@ -19,6 +19,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/set" ) var ( @@ -1508,86 +1509,86 @@ func TestResolveDependency(t *testing.T) { var tests = map[string]struct { pkgName string apkIndexArchivePath string - expected map[string]struct{} + want set.Set[string] }{ "low": { pkgName: "libblkid", apkIndexArchivePath: "testdata/history_v3.9.json", - expected: map[string]struct{}{ - "libblkid": {}, - "libuuid": {}, - "musl": {}, - }, + want: set.New( + "libblkid", + "libuuid", + "musl", + ), }, "medium": { pkgName: "libgcab", apkIndexArchivePath: "testdata/history_v3.9.json", - expected: map[string]struct{}{ - "busybox": {}, - "libblkid": {}, - "libuuid": {}, - "musl": {}, - "libmount": {}, - "pcre": {}, - "glib": {}, - "libgcab": {}, - "libintl": {}, - "zlib": {}, - "libffi": {}, - }, + want: set.New( + "busybox", + "libblkid", + "libuuid", + "musl", + "libmount", + "pcre", + "glib", + "libgcab", + "libintl", + "zlib", + "libffi", + ), }, "high": { pkgName: "postgresql", apkIndexArchivePath: "testdata/history_v3.9.json", - expected: map[string]struct{}{ - "busybox": {}, - "ncurses-terminfo-base": {}, - "ncurses-terminfo": {}, - "libedit": {}, - "db": {}, - "libsasl": {}, - "libldap": {}, - "libpq": {}, - "postgresql-client": {}, - "tzdata": {}, - "libxml2": {}, - "postgresql": {}, - "musl": {}, - "libcrypto1.1": {}, - "libssl1.1": {}, - "ncurses-libs": {}, - "zlib": {}, - }, + want: set.New( + "busybox", + "ncurses-terminfo-base", + "ncurses-terminfo", + "libedit", + "db", + "libsasl", + "libldap", + "libpq", + "postgresql-client", + "tzdata", + "libxml2", + "postgresql", + "musl", + "libcrypto1.1", + "libssl1.1", + "ncurses-libs", + "zlib", + ), }, "package alias": { pkgName: "sqlite-dev", apkIndexArchivePath: "testdata/history_v3.9.json", - expected: map[string]struct{}{ - "sqlite-dev": {}, - "sqlite-libs": {}, - "pkgconf": {}, // pkgconfig => pkgconf - "musl": {}, - }, + want: set.New( + "sqlite-dev", + "sqlite-libs", + "pkgconf", // pkgconfig => pkgconf + "musl", + ), }, "circular dependencies": { pkgName: "nodejs", apkIndexArchivePath: "testdata/history_v3.7.json", - expected: map[string]struct{}{ - "busybox": {}, - "c-ares": {}, - "ca-certificates": {}, - "http-parser": {}, - "libcrypto1.0": {}, - "libgcc": {}, - "libressl2.6-libcrypto": {}, - "libssl1.0": {}, - "libstdc++": {}, - "libuv": {}, - "musl": {}, - "nodejs": {}, - "nodejs-npm": {}, - "zlib": {}, - }, + want: set.New( + "busybox", + "c-ares", + "ca-certificates", + "http-parser", + "libcrypto1.0", + "libgcc", + "libressl2.6-libcrypto", + "libssl1.0", + "libstdc++", + "libuv", + "musl", + "nodejs", + "nodejs-npm", + "zlib", + ), }, } analyzer := alpineCmdAnalyzer{} @@ -1600,15 +1601,10 @@ func TestResolveDependency(t *testing.T) { if err = json.NewDecoder(f).Decode(&apkIndexArchive); err != nil { t.Fatalf("unexpected error: %s", err) } - circularDependencyCheck := make(map[string]struct{}) + circularDependencyCheck := set.New[string]() pkgs := analyzer.resolveDependency(apkIndexArchive, v.pkgName, circularDependencyCheck) - actual := make(map[string]struct{}) - for _, pkg := range pkgs { - actual[pkg] = struct{}{} - } - if !reflect.DeepEqual(v.expected, actual) { - t.Errorf("[%s]\n%s", testName, pretty.Compare(v.expected, actual)) - } + got := set.New(pkgs...) + assert.Equal(t, v.want, got, testName) } } diff --git a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go index 35a4fc12fea1..d6aea6d65873 100644 --- a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go +++ b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + v1 "github.com/google/go-containerregistry/pkg/v1" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" @@ -49,11 +50,33 @@ func (a *historyAnalyzer) Analyze(ctx context.Context, input analyzer.ConfigAnal if input.Config == nil { return nil, nil } + + fsys := mapfs.New() + if err := fsys.WriteVirtualFile( + "Dockerfile", imageConfigToDockerfile(input.Config), 0600); err != nil { + return nil, xerrors.Errorf("mapfs write error: %w", err) + } + + misconfs, err := a.scanner.Scan(ctx, fsys) + if err != nil { + return nil, xerrors.Errorf("history scan error: %w", err) + } + // The result should be a single element as it passes one Dockerfile. + if len(misconfs) != 1 { + return nil, nil + } + + return &analyzer.ConfigAnalysisResult{ + Misconfiguration: &misconfs[0], + }, nil +} + +func imageConfigToDockerfile(cfg *v1.ConfigFile) []byte { dockerfile := new(bytes.Buffer) var userFound bool - baseLayerIndex := image.GuessBaseImageIndex(input.Config.History) - for i := baseLayerIndex + 1; i < len(input.Config.History); i++ { - h := input.Config.History[i] + baseLayerIndex := image.GuessBaseImageIndex(cfg.History) + for i := baseLayerIndex + 1; i < len(cfg.History); i++ { + h := cfg.History[i] var createdBy string switch { case strings.HasPrefix(h.CreatedBy, "/bin/sh -c #(nop)"): @@ -61,64 +84,64 @@ func (a *historyAnalyzer) Analyze(ctx context.Context, input analyzer.ConfigAnal createdBy = strings.TrimPrefix(h.CreatedBy, "/bin/sh -c #(nop)") case strings.HasPrefix(h.CreatedBy, "/bin/sh -c"): // RUN instruction - createdBy = strings.ReplaceAll(h.CreatedBy, "/bin/sh -c", "RUN") + createdBy = buildRunInstruction(createdBy) case strings.HasSuffix(h.CreatedBy, "# buildkit"): // buildkit instructions // COPY ./foo /foo # buildkit // ADD ./foo.txt /foo.txt # buildkit // RUN /bin/sh -c ls -hl /foo # buildkit createdBy = strings.TrimSuffix(h.CreatedBy, "# buildkit") - if strings.HasPrefix(h.CreatedBy, "RUN /bin/sh -c") { - createdBy = strings.ReplaceAll(createdBy, "RUN /bin/sh -c", "RUN") - } + createdBy = buildRunInstruction(createdBy) case strings.HasPrefix(h.CreatedBy, "USER"): // USER instruction createdBy = h.CreatedBy userFound = true case strings.HasPrefix(h.CreatedBy, "HEALTHCHECK"): // HEALTHCHECK instruction - var interval, timeout, startPeriod, retries, command string - if input.Config.Config.Healthcheck.Interval != 0 { - interval = fmt.Sprintf("--interval=%s ", input.Config.Config.Healthcheck.Interval) + createdBy = buildHealthcheckInstruction(cfg.Config.Healthcheck) + default: + for _, prefix := range []string{"ARG", "ENV", "ENTRYPOINT"} { + strings.HasPrefix(h.CreatedBy, prefix) + createdBy = h.CreatedBy + break } - if input.Config.Config.Healthcheck.Timeout != 0 { - timeout = fmt.Sprintf("--timeout=%s ", input.Config.Config.Healthcheck.Timeout) - } - if input.Config.Config.Healthcheck.StartPeriod != 0 { - startPeriod = fmt.Sprintf("--startPeriod=%s ", input.Config.Config.Healthcheck.StartPeriod) - } - if input.Config.Config.Healthcheck.Retries != 0 { - retries = fmt.Sprintf("--retries=%d ", input.Config.Config.Healthcheck.Retries) - } - command = strings.Join(input.Config.Config.Healthcheck.Test, " ") - command = strings.ReplaceAll(command, "CMD-SHELL", "CMD") - createdBy = fmt.Sprintf("HEALTHCHECK %s%s%s%s%s", interval, timeout, startPeriod, retries, command) } dockerfile.WriteString(strings.TrimSpace(createdBy) + "\n") } - if !userFound && input.Config.Config.User != "" { - user := fmt.Sprintf("USER %s", input.Config.Config.User) + if !userFound && cfg.Config.User != "" { + user := fmt.Sprintf("USER %s", cfg.Config.User) dockerfile.WriteString(user) } - fsys := mapfs.New() - if err := fsys.WriteVirtualFile("Dockerfile", dockerfile.Bytes(), 0600); err != nil { - return nil, xerrors.Errorf("mapfs write error: %w", err) + return dockerfile.Bytes() +} + +func buildRunInstruction(s string) string { + pos := strings.Index(s, "/bin/sh -c") + if pos == -1 { + return s } + return "RUN" + s[pos+len("/bin/sh -c"):] +} - misconfs, err := a.scanner.Scan(ctx, fsys) - if err != nil { - return nil, xerrors.Errorf("history scan error: %w", err) +func buildHealthcheckInstruction(health *v1.HealthConfig) string { + var interval, timeout, startPeriod, retries, command string + if health.Interval != 0 { + interval = fmt.Sprintf("--interval=%s ", health.Interval) } - // The result should be a single element as it passes one Dockerfile. - if len(misconfs) != 1 { - return nil, nil + if health.Timeout != 0 { + timeout = fmt.Sprintf("--timeout=%s ", health.Timeout) } - - return &analyzer.ConfigAnalysisResult{ - Misconfiguration: &misconfs[0], - }, nil + if health.StartPeriod != 0 { + startPeriod = fmt.Sprintf("--startPeriod=%s ", health.StartPeriod) + } + if health.Retries != 0 { + retries = fmt.Sprintf("--retries=%d ", health.Retries) + } + command = strings.Join(health.Test, " ") + command = strings.ReplaceAll(command, "CMD-SHELL", "CMD") + return fmt.Sprintf("HEALTHCHECK %s%s%s%s%s", interval, timeout, startPeriod, retries, command) } func (a *historyAnalyzer) Required(_ types.OS) bool { diff --git a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go index c454de8ba3d4..cd36944a6621 100644 --- a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go +++ b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go @@ -1,11 +1,13 @@ package dockerfile import ( + "bytes" "context" "testing" "time" v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -343,3 +345,101 @@ func Test_historyAnalyzer_Analyze(t *testing.T) { }) } } + +func Test_ImageConfigToDockerfile(t *testing.T) { + tests := []struct { + name string + input *v1.ConfigFile + expected string + }{ + { + name: "run instruction with build args", + input: &v1.ConfigFile{ + History: []v1.History{ + { + CreatedBy: "RUN |1 pkg=curl /bin/sh -c apk add $pkg # buildkit", + }, + }, + }, + expected: "RUN apk add $pkg\n", + }, + { + name: "healthcheck instruction with system's default shell", + input: &v1.ConfigFile{ + History: []v1.History{ + { + CreatedBy: "HEALTHCHECK &{[\"CMD-SHELL\" \"curl -f http://localhost/ || exit 1\"] \"5m0s\" \"3s\" \"1s\" \"5s\" '\\x03'}", + }, + }, + Config: v1.Config{ + Healthcheck: &v1.HealthConfig{ + Test: []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}, + Interval: time.Minute * 5, + Timeout: time.Second * 3, + StartPeriod: time.Second * 1, + Retries: 3, + }, + }, + }, + expected: "HEALTHCHECK --interval=5m0s --timeout=3s --startPeriod=1s --retries=3 CMD curl -f http://localhost/ || exit 1\n", + }, + { + name: "healthcheck instruction exec arguments directly", + input: &v1.ConfigFile{ + History: []v1.History{ + { + CreatedBy: "HEALTHCHECK &{[\"CMD\" \"curl\" \"-f\" \"http://localhost/\" \"||\" \"exit 1\"] \"0s\" \"0s\" \"0s\" \"0s\" '\x03'}", + }, + }, + Config: v1.Config{ + Healthcheck: &v1.HealthConfig{ + Test: []string{"CMD", "curl", "-f", "http://localhost/", "||", "exit 1"}, + Retries: 3, + }, + }, + }, + expected: "HEALTHCHECK --retries=3 CMD curl -f http://localhost/ || exit 1\n", + }, + { + name: "nop, no run instruction", + input: &v1.ConfigFile{ + History: []v1.History{ + { + CreatedBy: "/bin/sh -c #(nop) ARG TAG=latest", + }, + }, + }, + expected: "ARG TAG=latest\n", + }, + { + name: "buildkit metadata instructions", + input: &v1.ConfigFile{ + History: []v1.History{ + { + CreatedBy: "ARG TAG=latest", + }, + { + CreatedBy: "ENV TAG=latest", + }, + { + CreatedBy: "ENTRYPOINT [\"/bin/sh\" \"-c\" \"echo test\"]", + }, + }, + }, + expected: `ARG TAG=latest +ENV TAG=latest +ENTRYPOINT ["/bin/sh" "-c" "echo test"] +`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := imageConfigToDockerfile(tt.input) + _, err := parser.Parse(bytes.NewReader(got)) + require.NoError(t, err) + + assert.Equal(t, tt.expected, string(got)) + }) + } +} diff --git a/pkg/fanal/analyzer/language/analyze_test.go b/pkg/fanal/analyzer/language/analyze_test.go index 6a996fc03172..3f343b6b8366 100644 --- a/pkg/fanal/analyzer/language/analyze_test.go +++ b/pkg/fanal/analyzer/language/analyze_test.go @@ -97,8 +97,7 @@ func TestAnalyze(t *testing.T) { got, err := language.Analyze(tt.args.fileType, tt.args.filePath, tt.args.content, mp) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/fanal/analyzer/language/dotnet/deps/deps_test.go b/pkg/fanal/analyzer/language/dotnet/deps/deps_test.go index d6a86c78084e..c6c7172fb460 100644 --- a/pkg/fanal/analyzer/language/dotnet/deps/deps_test.go +++ b/pkg/fanal/analyzer/language/dotnet/deps/deps_test.go @@ -64,8 +64,7 @@ func Test_depsLibraryAnalyzer_Analyze(t *testing.T) { }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/fanal/analyzer/language/java/pom/pom_test.go b/pkg/fanal/analyzer/language/java/pom/pom_test.go index ea147a4d1141..53896d518e68 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom_test.go +++ b/pkg/fanal/analyzer/language/java/pom/pom_test.go @@ -191,8 +191,7 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { }, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/fanal/analyzer/language/nodejs/pkg/pkg_test.go b/pkg/fanal/analyzer/language/nodejs/pkg/pkg_test.go index 62eebb5a5f09..3facf662d4a7 100644 --- a/pkg/fanal/analyzer/language/nodejs/pkg/pkg_test.go +++ b/pkg/fanal/analyzer/language/nodejs/pkg/pkg_test.go @@ -89,8 +89,7 @@ func Test_nodePkgLibraryAnalyzer_Analyze(t *testing.T) { }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } diff --git a/pkg/fanal/analyzer/language/python/packaging/packaging_test.go b/pkg/fanal/analyzer/language/python/packaging/packaging_test.go index 47a9cca901b6..663cd52fe8c2 100644 --- a/pkg/fanal/analyzer/language/python/packaging/packaging_test.go +++ b/pkg/fanal/analyzer/language/python/packaging/packaging_test.go @@ -141,8 +141,7 @@ func Test_packagingAnalyzer_Analyze(t *testing.T) { }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/fanal/analyzer/language/python/pipenv/pipenv.go b/pkg/fanal/analyzer/language/python/pipenv/pipenv.go index 06fc1f35dccf..aa82480bf4f5 100644 --- a/pkg/fanal/analyzer/language/python/pipenv/pipenv.go +++ b/pkg/fanal/analyzer/language/python/pipenv/pipenv.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "slices" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) func init() { @@ -34,7 +34,7 @@ func (a pipenvLibraryAnalyzer) Analyze(_ context.Context, input analyzer.Analysi func (a pipenvLibraryAnalyzer) Required(filePath string, _ os.FileInfo) bool { fileName := filepath.Base(filePath) - return utils.StringInSlice(fileName, requiredFiles) + return slices.Contains(requiredFiles, fileName) } func (a pipenvLibraryAnalyzer) Type() analyzer.Type { diff --git a/pkg/fanal/analyzer/language/python/poetry/poetry.go b/pkg/fanal/analyzer/language/python/poetry/poetry.go index 3b751f747621..c9e2e1f6d8ac 100644 --- a/pkg/fanal/analyzer/language/python/poetry/poetry.go +++ b/pkg/fanal/analyzer/language/python/poetry/poetry.go @@ -17,6 +17,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) @@ -94,7 +95,7 @@ func (a poetryAnalyzer) parsePoetryLock(path string, r io.Reader) (*types.Applic func (a poetryAnalyzer) mergePyProject(fsys fs.FS, dir string, app *types.Application) error { // Parse pyproject.toml to identify the direct dependencies path := filepath.Join(dir, types.PyProject) - p, err := a.parsePyProject(fsys, path) + project, err := a.parsePyProject(fsys, path) if errors.Is(err, fs.ErrNotExist) { // Assume all the packages are direct dependencies as it cannot identify them from poetry.lock a.logger.Debug("pyproject.toml not found", log.FilePath(path)) @@ -103,36 +104,69 @@ func (a poetryAnalyzer) mergePyProject(fsys fs.FS, dir string, app *types.Applic return xerrors.Errorf("unable to parse %s: %w", path, err) } - // Identify the direct/transitive dependencies + directDeps := directDeps(project) + prodDeps := prodPackages(app, project.Tool.Poetry.Dependencies) + + // Identify the direct/transitive/dev dependencies for i, pkg := range app.Packages { - if _, ok := p[pkg.Name]; ok { + app.Packages[i].Dev = !prodDeps.Contains(pkg.ID) + if directDeps.Contains(pkg.Name) { app.Packages[i].Relationship = types.RelationshipDirect } else { app.Packages[i].Indirect = true app.Packages[i].Relationship = types.RelationshipIndirect } } - return nil } -func (a poetryAnalyzer) parsePyProject(fsys fs.FS, path string) (map[string]any, error) { +func directDeps(project pyproject.PyProject) set.Set[string] { + deps := project.Tool.Poetry.Dependencies.Clone() + for _, groupDeps := range project.Tool.Poetry.Groups { + deps.Append(groupDeps.Dependencies.Items()...) + } + return deps +} + +func prodPackages(app *types.Application, prodRootDeps set.Set[string]) set.Set[string] { + packages := lo.SliceToMap(app.Packages, func(pkg types.Package) (string, types.Package) { + return pkg.ID, pkg + }) + + visited := set.New[string]() + + for _, pkg := range packages { + if !prodRootDeps.Contains(pkg.Name) { + continue + } + walkPackageDeps(pkg.ID, packages, visited) + } + + return visited +} + +func walkPackageDeps(pkgID string, packages map[string]types.Package, visited set.Set[string]) { + if visited.Contains(pkgID) { + return + } + visited.Append(pkgID) + for _, dep := range packages[pkgID].DependsOn { + walkPackageDeps(dep, packages, visited) + } +} + +func (a poetryAnalyzer) parsePyProject(fsys fs.FS, path string) (pyproject.PyProject, error) { // Parse pyproject.toml f, err := fsys.Open(path) if err != nil { - return nil, xerrors.Errorf("file open error: %w", err) + return pyproject.PyProject{}, xerrors.Errorf("file open error: %w", err) } defer f.Close() - parsed, err := a.pyprojectParser.Parse(f) + project, err := a.pyprojectParser.Parse(f) if err != nil { - return nil, err + return pyproject.PyProject{}, err } - // Packages from `pyproject.toml` can use uppercase characters, `.` and `_`. - parsed = lo.MapKeys(parsed, func(_ any, pkgName string) string { - return poetry.NormalizePkgName(pkgName) - }) - - return parsed, nil + return project, nil } diff --git a/pkg/fanal/analyzer/language/python/poetry/poetry_test.go b/pkg/fanal/analyzer/language/python/poetry/poetry_test.go index 08de4d92d4ef..618b9c8c5d9c 100644 --- a/pkg/fanal/analyzer/language/python/poetry/poetry_test.go +++ b/pkg/fanal/analyzer/language/python/poetry/poetry_test.go @@ -181,6 +181,220 @@ func Test_poetryLibraryAnalyzer_Analyze(t *testing.T) { dir: "testdata/sad", want: &analyzer.AnalysisResult{}, }, + { + // docker run --name poetry --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // wget -qO- https://install.python-poetry.org | POETRY_VERSION=1.8.5 python3 - + // export PATH="/root/.local/bin:$PATH" + // poetry new groups && cd groups + // poetry add requests@2.32.3 + // poetry add httpx@0.28.1 --extras socks + // poetry add --optional typing-inspect@0.9.0 + // poetry add --group dev pytest@8.3.4 + // poetry add --group lint ruff@0.8.3 + name: "with groups", + dir: "testdata/with-groups", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Poetry, + FilePath: "poetry.lock", + Packages: types.Packages{ + { + ID: "anyio@4.7.0", + Name: "anyio", + Version: "4.7.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + DependsOn: []string{ + "exceptiongroup@1.2.2", + "idna@3.10", + "sniffio@1.3.1", + "typing-extensions@4.12.2", + }, + }, + { + ID: "certifi@2024.12.14", + Name: "certifi", + Version: "2024.12.14", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "charset-normalizer@3.4.0", + Name: "charset-normalizer", + Version: "3.4.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "colorama@0.4.6", + Name: "colorama", + Version: "0.4.6", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "exceptiongroup@1.2.2", + Name: "exceptiongroup", + Version: "1.2.2", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "h11@0.14.0", + Name: "h11", + Version: "0.14.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "httpcore@1.0.7", + Name: "httpcore", + Version: "1.0.7", + Indirect: true, + Relationship: types.RelationshipIndirect, + DependsOn: []string{ + "certifi@2024.12.14", + "h11@0.14.0", + }, + }, + { + ID: "httpx@0.28.1", + Name: "httpx", + Version: "0.28.1", + Relationship: types.RelationshipDirect, + DependsOn: []string{ + "anyio@4.7.0", + "certifi@2024.12.14", + "httpcore@1.0.7", + "idna@3.10", + "socksio@1.0.0", + }, + }, + { + ID: "idna@3.10", + Name: "idna", + Version: "3.10", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "iniconfig@2.0.0", + Name: "iniconfig", + Version: "2.0.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "mypy-extensions@1.0.0", + Name: "mypy-extensions", + Version: "1.0.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "packaging@24.2", + Name: "packaging", + Version: "24.2", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "pluggy@1.5.0", + Name: "pluggy", + Version: "1.5.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "pytest@8.3.4", + Name: "pytest", + Version: "8.3.4", + Relationship: types.RelationshipDirect, + Dev: true, + DependsOn: []string{ + "colorama@0.4.6", + "exceptiongroup@1.2.2", + "iniconfig@2.0.0", + "packaging@24.2", + "pluggy@1.5.0", + "tomli@2.2.1", + }, + }, + { + ID: "requests@2.32.3", + Name: "requests", + Version: "2.32.3", + DependsOn: []string{ + "certifi@2024.12.14", + "charset-normalizer@3.4.0", + "idna@3.10", + "urllib3@2.2.3", + }, + Relationship: types.RelationshipDirect, + }, + { + ID: "ruff@0.8.3", + Name: "ruff", + Version: "0.8.3", + Relationship: types.RelationshipDirect, + Dev: true, + }, + { + ID: "sniffio@1.3.1", + Name: "sniffio", + Version: "1.3.1", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "socksio@1.0.0", + Name: "socksio", + Version: "1.0.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "tomli@2.2.1", + Name: "tomli", + Version: "2.2.1", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "typing-extensions@4.12.2", + Name: "typing-extensions", + Version: "4.12.2", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "typing-inspect@0.9.0", + Name: "typing-inspect", + Version: "0.9.0", + DependsOn: []string{ + "mypy-extensions@1.0.0", + "typing-extensions@4.12.2", + }, + Relationship: types.RelationshipDirect, + }, + { + ID: "urllib3@2.2.3", + Name: "urllib3", + Version: "2.2.3", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + }, + }, + }, + }, + }, } for _, tt := range tests { diff --git a/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/poetry.lock b/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/poetry.lock new file mode 100644 index 000000000000..f90fb4513a70 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/poetry.lock @@ -0,0 +1,473 @@ +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.7.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.9" +files = [ + {file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"}, + {file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} + +[package.extras] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +trio = ["trio (>=0.26.1)"] + +[[package]] +name = "certifi" +version = "2024.12.14" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, + {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +socksio = {version = "==1.*", optional = true, markers = "extra == \"socks\""} + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = true +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "24.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "8.3.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruff" +version = "0.8.3" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:8d5d273ffffff0acd3db5bf626d4b131aa5a5ada1276126231c4174543ce20d6"}, + {file = "ruff-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e4d66a21de39f15c9757d00c50c8cdd20ac84f55684ca56def7891a025d7e939"}, + {file = "ruff-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c356e770811858bd20832af696ff6c7e884701115094f427b64b25093d6d932d"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c0a60a825e3e177116c84009d5ebaa90cf40dfab56e1358d1df4e29a9a14b13"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fb782f4db39501210ac093c79c3de581d306624575eddd7e4e13747e61ba18"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f26bc76a133ecb09a38b7868737eded6941b70a6d34ef53a4027e83913b6502"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:01b14b2f72a37390c1b13477c1c02d53184f728be2f3ffc3ace5b44e9e87b90d"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53babd6e63e31f4e96ec95ea0d962298f9f0d9cc5990a1bbb023a6baf2503a82"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ae441ce4cf925b7f363d33cd6570c51435972d697e3e58928973994e56e1452"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c65bc0cadce32255e93c57d57ecc2cca23149edd52714c0c5d6fa11ec328cd"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5be450bb18f23f0edc5a4e5585c17a56ba88920d598f04a06bd9fd76d324cb20"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8faeae3827eaa77f5721f09b9472a18c749139c891dbc17f45e72d8f2ca1f8fc"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:db503486e1cf074b9808403991663e4277f5c664d3fe237ee0d994d1305bb060"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6567be9fb62fbd7a099209257fef4ad2c3153b60579818b31a23c886ed4147ea"}, + {file = "ruff-0.8.3-py3-none-win32.whl", hash = "sha256:19048f2f878f3ee4583fc6cb23fb636e48c2635e30fb2022b3a1cd293402f964"}, + {file = "ruff-0.8.3-py3-none-win_amd64.whl", hash = "sha256:f7df94f57d7418fa7c3ffb650757e0c2b96cf2501a0b192c18e4fb5571dfada9"}, + {file = "ruff-0.8.3-py3-none-win_arm64.whl", hash = "sha256:fe2756edf68ea79707c8d68b78ca9a58ed9af22e430430491ee03e718b5e4936"}, + {file = "ruff-0.8.3.tar.gz", hash = "sha256:5e7558304353b84279042fc584a4f4cb8a07ae79b2bf3da1a7551d960b5626d3"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "socksio" +version = "1.0.0" +description = "Sans-I/O implementation of SOCKS4, SOCKS4A, and SOCKS5." +optional = false +python-versions = ">=3.6" +files = [ + {file = "socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3"}, + {file = "socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac"}, +] + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + +[[package]] +name = "typing-inspect" +version = "0.9.0" +description = "Runtime inspection utilities for typing module." +optional = true +python-versions = "*" +files = [ + {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, + {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, +] + +[package.dependencies] +mypy-extensions = ">=0.3.0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "urllib3" +version = "2.2.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9" +content-hash = "eb9992c7bdd3f378ae8559495b790f625f0368d978b5664820fa06b2db854bff" \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/pyproject.toml b/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/pyproject.toml new file mode 100644 index 000000000000..919afb32bb68 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/poetry/testdata/with-groups/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "groups" +version = "0.1.0" +description = "" +authors = ["Your Name "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.9" +requests = "2.32.3" +typing-inspect = {version = "0.9.0", optional = true} +httpx = {version = "0.28.1", extras = ["socks"]} + + +[tool.poetry.group.dev.dependencies] +pytest = "8.3.4" + + +[tool.poetry.group.lint.dependencies] +ruff = "0.8.3" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/python/uv/testdata/broken-lock/uv.lock b/pkg/fanal/analyzer/language/python/uv/testdata/broken-lock/uv.lock new file mode 100644 index 000000000000..74e0f12e3246 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/uv/testdata/broken-lock/uv.lock @@ -0,0 +1 @@ +! \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/python/uv/testdata/happy/uv.lock b/pkg/fanal/analyzer/language/python/uv/testdata/happy/uv.lock new file mode 100644 index 000000000000..ac34c2270333 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/uv/testdata/happy/uv.lock @@ -0,0 +1,252 @@ +version = 1 +requires-python = ">=3.9" + +[[package]] +name = "certifi" +version = "2024.12.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8b/825cc84cf13a28bfbcba7c416ec22bf85a9584971be15b21dd8300c65b7f/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6", size = 196363 }, + { url = "https://files.pythonhosted.org/packages/23/81/d7eef6a99e42c77f444fdd7bc894b0ceca6c3a95c51239e74a722039521c/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b", size = 125639 }, + { url = "https://files.pythonhosted.org/packages/21/67/b4564d81f48042f520c948abac7079356e94b30cb8ffb22e747532cf469d/charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99", size = 120451 }, + { url = "https://files.pythonhosted.org/packages/c2/72/12a7f0943dd71fb5b4e7b55c41327ac0a1663046a868ee4d0d8e9c369b85/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca", size = 140041 }, + { url = "https://files.pythonhosted.org/packages/67/56/fa28c2c3e31217c4c52158537a2cf5d98a6c1e89d31faf476c89391cd16b/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d", size = 150333 }, + { url = "https://files.pythonhosted.org/packages/f9/d2/466a9be1f32d89eb1554cf84073a5ed9262047acee1ab39cbaefc19635d2/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7", size = 142921 }, + { url = "https://files.pythonhosted.org/packages/f8/01/344ec40cf5d85c1da3c1f57566c59e0c9b56bcc5566c08804a95a6cc8257/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3", size = 144785 }, + { url = "https://files.pythonhosted.org/packages/73/8b/2102692cb6d7e9f03b9a33a710e0164cadfce312872e3efc7cfe22ed26b4/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907", size = 146631 }, + { url = "https://files.pythonhosted.org/packages/d8/96/cc2c1b5d994119ce9f088a9a0c3ebd489d360a2eb058e2c8049f27092847/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b", size = 140867 }, + { url = "https://files.pythonhosted.org/packages/c9/27/cde291783715b8ec30a61c810d0120411844bc4c23b50189b81188b273db/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912", size = 149273 }, + { url = "https://files.pythonhosted.org/packages/3a/a4/8633b0fc1a2d1834d5393dafecce4a1cc56727bfd82b4dc18fc92f0d3cc3/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95", size = 152437 }, + { url = "https://files.pythonhosted.org/packages/64/ea/69af161062166b5975ccbb0961fd2384853190c70786f288684490913bf5/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e", size = 150087 }, + { url = "https://files.pythonhosted.org/packages/3b/fd/e60a9d9fd967f4ad5a92810138192f825d77b4fa2a557990fd575a47695b/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe", size = 145142 }, + { url = "https://files.pythonhosted.org/packages/6d/02/8cb0988a1e49ac9ce2eed1e07b77ff118f2923e9ebd0ede41ba85f2dcb04/charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc", size = 94701 }, + { url = "https://files.pythonhosted.org/packages/d6/20/f1d4670a8a723c46be695dff449d86d6092916f9e99c53051954ee33a1bc/charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749", size = 102191 }, + { url = "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", size = 193339 }, + { url = "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", size = 124366 }, + { url = "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", size = 118874 }, + { url = "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", size = 138243 }, + { url = "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", size = 148676 }, + { url = "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", size = 141289 }, + { url = "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", size = 142585 }, + { url = "https://files.pythonhosted.org/packages/3b/a0/a68980ab8a1f45a36d9745d35049c1af57d27255eff8c907e3add84cf68f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", size = 144408 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", size = 139076 }, + { url = "https://files.pythonhosted.org/packages/fb/9d/9c13753a5a6e0db4a0a6edb1cef7aee39859177b64e1a1e748a6e3ba62c2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", size = 146874 }, + { url = "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", size = 150871 }, + { url = "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", size = 148546 }, + { url = "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", size = 143048 }, + { url = "https://files.pythonhosted.org/packages/01/f8/38842422988b795220eb8038745d27a675ce066e2ada79516c118f291f07/charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", size = 94389 }, + { url = "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", size = 101752 }, + { url = "https://files.pythonhosted.org/packages/d3/0b/4b7a70987abf9b8196845806198975b6aab4ce016632f817ad758a5aa056/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", size = 194445 }, + { url = "https://files.pythonhosted.org/packages/50/89/354cc56cf4dd2449715bc9a0f54f3aef3dc700d2d62d1fa5bbea53b13426/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", size = 125275 }, + { url = "https://files.pythonhosted.org/packages/fa/44/b730e2a2580110ced837ac083d8ad222343c96bb6b66e9e4e706e4d0b6df/charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", size = 119020 }, + { url = "https://files.pythonhosted.org/packages/9d/e4/9263b8240ed9472a2ae7ddc3e516e71ef46617fe40eaa51221ccd4ad9a27/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", size = 139128 }, + { url = "https://files.pythonhosted.org/packages/6b/e3/9f73e779315a54334240353eaea75854a9a690f3f580e4bd85d977cb2204/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", size = 149277 }, + { url = "https://files.pythonhosted.org/packages/1a/cf/f1f50c2f295312edb8a548d3fa56a5c923b146cd3f24114d5adb7e7be558/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", size = 142174 }, + { url = "https://files.pythonhosted.org/packages/16/92/92a76dc2ff3a12e69ba94e7e05168d37d0345fa08c87e1fe24d0c2a42223/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", size = 143838 }, + { url = "https://files.pythonhosted.org/packages/a4/01/2117ff2b1dfc61695daf2babe4a874bca328489afa85952440b59819e9d7/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", size = 146149 }, + { url = "https://files.pythonhosted.org/packages/f6/9b/93a332b8d25b347f6839ca0a61b7f0287b0930216994e8bf67a75d050255/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", size = 140043 }, + { url = "https://files.pythonhosted.org/packages/ab/f6/7ac4a01adcdecbc7a7587767c776d53d369b8b971382b91211489535acf0/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", size = 148229 }, + { url = "https://files.pythonhosted.org/packages/9d/be/5708ad18161dee7dc6a0f7e6cf3a88ea6279c3e8484844c0590e50e803ef/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", size = 151556 }, + { url = "https://files.pythonhosted.org/packages/5a/bb/3d8bc22bacb9eb89785e83e6723f9888265f3a0de3b9ce724d66bd49884e/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", size = 149772 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/d3fc622de05a86f30beea5fc4e9ac46aead4731e73fd9055496732bcc0a4/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", size = 144800 }, + { url = "https://files.pythonhosted.org/packages/9a/65/bdb9bc496d7d190d725e96816e20e2ae3a6fa42a5cac99c3c3d6ff884118/charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", size = 94836 }, + { url = "https://files.pythonhosted.org/packages/3e/67/7b72b69d25b89c0b3cea583ee372c43aa24df15f0e0f8d3982c57804984b/charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", size = 102187 }, + { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 }, + { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 }, + { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 }, + { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 }, + { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 }, + { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 }, + { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 }, + { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 }, + { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 }, + { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 }, + { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 }, + { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 }, + { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, + { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, + { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, + { url = "https://files.pythonhosted.org/packages/54/2f/28659eee7f5d003e0f5a3b572765bf76d6e0fe6601ab1f1b1dd4cba7e4f1/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa", size = 196326 }, + { url = "https://files.pythonhosted.org/packages/d1/18/92869d5c0057baa973a3ee2af71573be7b084b3c3d428fe6463ce71167f8/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a", size = 125614 }, + { url = "https://files.pythonhosted.org/packages/d6/27/327904c5a54a7796bb9f36810ec4173d2df5d88b401d2b95ef53111d214e/charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0", size = 120450 }, + { url = "https://files.pythonhosted.org/packages/a4/23/65af317914a0308495133b2d654cf67b11bbd6ca16637c4e8a38f80a5a69/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a", size = 140135 }, + { url = "https://files.pythonhosted.org/packages/f2/41/6190102ad521a8aa888519bb014a74251ac4586cde9b38e790901684f9ab/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242", size = 150413 }, + { url = "https://files.pythonhosted.org/packages/7b/ab/f47b0159a69eab9bd915591106859f49670c75f9a19082505ff16f50efc0/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b", size = 142992 }, + { url = "https://files.pythonhosted.org/packages/28/89/60f51ad71f63aaaa7e51a2a2ad37919985a341a1d267070f212cdf6c2d22/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62", size = 144871 }, + { url = "https://files.pythonhosted.org/packages/0c/48/0050550275fea585a6e24460b42465020b53375017d8596c96be57bfabca/charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0", size = 146756 }, + { url = "https://files.pythonhosted.org/packages/dc/b5/47f8ee91455946f745e6c9ddbb0f8f50314d2416dd922b213e7d5551ad09/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd", size = 141034 }, + { url = "https://files.pythonhosted.org/packages/84/79/5c731059ebab43e80bf61fa51666b9b18167974b82004f18c76378ed31a3/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be", size = 149434 }, + { url = "https://files.pythonhosted.org/packages/ca/f3/0719cd09fc4dc42066f239cb3c48ced17fc3316afca3e2a30a4756fe49ab/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d", size = 152443 }, + { url = "https://files.pythonhosted.org/packages/f7/0e/c6357297f1157c8e8227ff337e93fd0a90e498e3d6ab96b2782204ecae48/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3", size = 150294 }, + { url = "https://files.pythonhosted.org/packages/54/9a/acfa96dc4ea8c928040b15822b59d0863d6e1757fba8bd7de3dc4f761c13/charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742", size = 145314 }, + { url = "https://files.pythonhosted.org/packages/73/1c/b10a63032eaebb8d7bcb8544f12f063f41f5f463778ac61da15d9985e8b6/charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2", size = 94724 }, + { url = "https://files.pythonhosted.org/packages/c5/77/3a78bf28bfaa0863f9cfef278dbeadf55efe064eafff8c7c424ae3c4c1bf/charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca", size = 102159 }, + { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "happy" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pluggy" }, + { name = "requests" }, +] + +[package.dev-dependencies] +test = [ + { name = "pytest" }, +] + +[package.metadata] +requires-dist = [ + { name = "pluggy", specifier = "==1.5.0" }, + { name = "requests", specifier = "==2.32.3" }, +] + +[package.metadata.requires-dev] +test = [{ name = "pytest", specifier = "==8.3.4" }] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "pytest" +version = "8.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/python/uv/uv.go b/pkg/fanal/analyzer/language/python/uv/uv.go new file mode 100644 index 000000000000..b192815a6322 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/uv/uv.go @@ -0,0 +1,77 @@ +package uv + +import ( + "context" + "io" + "io/fs" + "os" + "path/filepath" + + "golang.org/x/xerrors" + + uvparser "github.com/aquasecurity/trivy/pkg/dependency/parser/python/uv" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/utils/fsutils" +) + +func init() { + analyzer.RegisterPostAnalyzer(analyzer.TypeUv, NewUvAnalyzer) +} + +const version = 1 + +type uvAnalyzer struct { + logger *log.Logger + lockParser language.Parser +} + +func NewUvAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { + return &uvAnalyzer{ + logger: log.WithPrefix("uv"), + lockParser: uvparser.NewParser(), + }, nil +} + +func (a *uvAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) { + var apps []types.Application + required := func(path string, d fs.DirEntry) bool { + return filepath.Base(path) == types.UvLock + } + + err := fsutils.WalkDir(input.FS, ".", required, func(path string, d fs.DirEntry, r io.Reader) error { + // Parse uv.lock + app, err := language.Parse(types.Uv, path, r, a.lockParser) + if err != nil { + a.logger.Warn("Failed to parse uv lockfile", log.Err(err)) + return nil + } else if app == nil { + return nil + } + + apps = append(apps, *app) + + return nil + }) + if err != nil { + return nil, xerrors.Errorf("walk error: %w", err) + } + + return &analyzer.AnalysisResult{ + Applications: apps, + }, nil +} + +func (a *uvAnalyzer) Required(filePath string, _ os.FileInfo) bool { + return filepath.Base(filePath) == types.UvLock +} + +func (a *uvAnalyzer) Type() analyzer.Type { + return analyzer.TypeUv +} + +func (a *uvAnalyzer) Version() int { + return version +} diff --git a/pkg/fanal/analyzer/language/python/uv/uv_test.go b/pkg/fanal/analyzer/language/python/uv/uv_test.go new file mode 100644 index 000000000000..c26120cae105 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/uv/uv_test.go @@ -0,0 +1,171 @@ +package uv_test + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/uv" + "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func Test_uvAnalyzer_PostAnalyze(t *testing.T) { + tests := []struct { + dir string + want *analyzer.AnalysisResult + }{ + // docker run --name uv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh + // wget -qO- https://github.com/astral-sh/uv/releases/download/0.5.8/uv-installer.sh | sh + // source $HOME/.local/bin/env + // uv init happy && cd happy + // uv add pluggy==1.5.0 requests==2.32.3 + // uv add --group test pytest==8.3.4 + { + dir: "testdata/happy", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Uv, + FilePath: "uv.lock", + Packages: types.Packages{ + { + ID: "happy@0.1.0", + Name: "happy", + Version: "0.1.0", + Relationship: types.RelationshipRoot, + DependsOn: []string{ + "pluggy@1.5.0", + "pytest@8.3.4", + "requests@2.32.3", + }, + }, + { + ID: "pluggy@1.5.0", + Name: "pluggy", + Version: "1.5.0", + Relationship: types.RelationshipDirect, + }, + { + ID: "pytest@8.3.4", + Name: "pytest", + Version: "8.3.4", + Relationship: types.RelationshipDirect, + Dev: true, + DependsOn: []string{ + "colorama@0.4.6", + "exceptiongroup@1.2.2", + "iniconfig@2.0.0", + "packaging@24.2", + "pluggy@1.5.0", + "tomli@2.2.1", + }, + }, + { + ID: "requests@2.32.3", + Name: "requests", + Version: "2.32.3", + Relationship: types.RelationshipDirect, + DependsOn: []string{ + "certifi@2024.12.14", + "charset-normalizer@3.4.0", + "idna@3.10", + "urllib3@2.2.3", + }, + }, + { + ID: "certifi@2024.12.14", + Name: "certifi", + Version: "2024.12.14", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "charset-normalizer@3.4.0", + Name: "charset-normalizer", + Version: "3.4.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "colorama@0.4.6", + Name: "colorama", + Version: "0.4.6", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "exceptiongroup@1.2.2", + Name: "exceptiongroup", + Version: "1.2.2", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "idna@3.10", + Name: "idna", + Version: "3.10", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + { + ID: "iniconfig@2.0.0", + Name: "iniconfig", + Version: "2.0.0", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "packaging@24.2", + Name: "packaging", + Version: "24.2", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "tomli@2.2.1", + Name: "tomli", + Version: "2.2.1", + Indirect: true, + Relationship: types.RelationshipIndirect, + Dev: true, + }, + { + ID: "urllib3@2.2.3", + Name: "urllib3", + Version: "2.2.3", + Indirect: true, + Relationship: types.RelationshipIndirect, + }, + }, + }, + }, + }, + }, + { + dir: "testdata/broken-lock", + want: &analyzer.AnalysisResult{}, + }, + } + + for _, tt := range tests { + t.Run(tt.dir, func(t *testing.T) { + a, err := uv.NewUvAnalyzer(analyzer.AnalyzerOptions{}) + require.NoError(t, err) + + got, err := a.PostAnalyze(context.Background(), analyzer.PostAnalysisInput{ + FS: os.DirFS(tt.dir), + }) + + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/fanal/analyzer/language/ruby/gemspec/gemspec_test.go b/pkg/fanal/analyzer/language/ruby/gemspec/gemspec_test.go index 76c91476dd02..46deaa2a0abc 100644 --- a/pkg/fanal/analyzer/language/ruby/gemspec/gemspec_test.go +++ b/pkg/fanal/analyzer/language/ruby/gemspec/gemspec_test.go @@ -92,8 +92,7 @@ func Test_gemspecLibraryAnalyzer_Analyze(t *testing.T) { }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/amazonlinux/amazonlinux.go b/pkg/fanal/analyzer/os/amazonlinux/amazonlinux.go index 2dc96646719f..1c3302088e80 100644 --- a/pkg/fanal/analyzer/os/amazonlinux/amazonlinux.go +++ b/pkg/fanal/analyzer/os/amazonlinux/amazonlinux.go @@ -5,6 +5,7 @@ import ( "context" "io" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -12,7 +13,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) func init() { @@ -63,7 +63,7 @@ func (a amazonlinuxOSAnalyzer) parseRelease(r io.Reader) (types.OS, error) { } func (a amazonlinuxOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, requiredFiles) + return slices.Contains(requiredFiles, filePath) } func (a amazonlinuxOSAnalyzer) Type() analyzer.Type { diff --git a/pkg/fanal/analyzer/os/amazonlinux/amazonlinux_test.go b/pkg/fanal/analyzer/os/amazonlinux/amazonlinux_test.go index 5ae7bc0d0f79..8cd1f0828f2b 100644 --- a/pkg/fanal/analyzer/os/amazonlinux/amazonlinux_test.go +++ b/pkg/fanal/analyzer/os/amazonlinux/amazonlinux_test.go @@ -95,8 +95,7 @@ func Test_amazonlinuxOSAnalyzer_Analyze(t *testing.T) { ctx := context.Background() got, err := a.Analyze(ctx, tt.input) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/debian/debian.go b/pkg/fanal/analyzer/os/debian/debian.go index 5c5f3c766229..8d6c7a9014df 100644 --- a/pkg/fanal/analyzer/os/debian/debian.go +++ b/pkg/fanal/analyzer/os/debian/debian.go @@ -4,13 +4,13 @@ import ( "bufio" "context" "os" + "slices" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) func init() { @@ -38,7 +38,7 @@ func (a debianOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInpu } func (a debianOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, requiredFiles) + return slices.Contains(requiredFiles, filePath) } func (a debianOSAnalyzer) Type() analyzer.Type { diff --git a/pkg/fanal/analyzer/os/debian/debian_test.go b/pkg/fanal/analyzer/os/debian/debian_test.go index 1fa36db41b07..56750d797162 100644 --- a/pkg/fanal/analyzer/os/debian/debian_test.go +++ b/pkg/fanal/analyzer/os/debian/debian_test.go @@ -59,8 +59,7 @@ func Test_debianOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/alma.go b/pkg/fanal/analyzer/os/redhatbase/alma.go index eddf7d82f80b..11b4aa94008b 100644 --- a/pkg/fanal/analyzer/os/redhatbase/alma.go +++ b/pkg/fanal/analyzer/os/redhatbase/alma.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const almaAnalyzerVersion = 1 @@ -46,7 +46,7 @@ func (a almaOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) } func (a almaOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a almaOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/alma_test.go b/pkg/fanal/analyzer/os/redhatbase/alma_test.go index 7356652a8234..689ed7e6165a 100644 --- a/pkg/fanal/analyzer/os/redhatbase/alma_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/alma_test.go @@ -46,8 +46,7 @@ func Test_almaOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/centos.go b/pkg/fanal/analyzer/os/redhatbase/centos.go index 4a57e3e9eac1..2401e6a76b21 100644 --- a/pkg/fanal/analyzer/os/redhatbase/centos.go +++ b/pkg/fanal/analyzer/os/redhatbase/centos.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const centosAnalyzerVersion = 1 @@ -46,7 +46,7 @@ func (a centOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) } func (a centOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a centOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/centos_test.go b/pkg/fanal/analyzer/os/redhatbase/centos_test.go index bee789865363..f0daab700937 100644 --- a/pkg/fanal/analyzer/os/redhatbase/centos_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/centos_test.go @@ -45,8 +45,7 @@ func Test_centosOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/fedora.go b/pkg/fanal/analyzer/os/redhatbase/fedora.go index d5b2458e1c5b..1391544ccf75 100644 --- a/pkg/fanal/analyzer/os/redhatbase/fedora.go +++ b/pkg/fanal/analyzer/os/redhatbase/fedora.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const fedoraAnalyzerVersion = 1 @@ -45,7 +45,7 @@ func (a fedoraOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInpu } func (a fedoraOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a fedoraOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/fedora_test.go b/pkg/fanal/analyzer/os/redhatbase/fedora_test.go index 405bbd5356ba..cbed013b0cef 100644 --- a/pkg/fanal/analyzer/os/redhatbase/fedora_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/fedora_test.go @@ -45,8 +45,7 @@ func Test_fedoraOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/oracle.go b/pkg/fanal/analyzer/os/redhatbase/oracle.go index 90864aefd848..d487b1bae9aa 100644 --- a/pkg/fanal/analyzer/os/redhatbase/oracle.go +++ b/pkg/fanal/analyzer/os/redhatbase/oracle.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const oracleAnalyzerVersion = 1 @@ -42,7 +42,7 @@ func (a oracleOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInpu } func (a oracleOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a oracleOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/oracle_test.go b/pkg/fanal/analyzer/os/redhatbase/oracle_test.go index 1f3120b47763..be7aa6f8dc76 100644 --- a/pkg/fanal/analyzer/os/redhatbase/oracle_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/oracle_test.go @@ -45,8 +45,7 @@ func Test_oracleOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/redhatbase.go b/pkg/fanal/analyzer/os/redhatbase/redhatbase.go index 9fc69a8753ca..f3a9df357bab 100644 --- a/pkg/fanal/analyzer/os/redhatbase/redhatbase.go +++ b/pkg/fanal/analyzer/os/redhatbase/redhatbase.go @@ -6,6 +6,7 @@ import ( "io" "os" "regexp" + "slices" "strings" "golang.org/x/xerrors" @@ -13,7 +14,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const redhatAnalyzerVersion = 1 @@ -83,7 +83,7 @@ func (a redhatOSAnalyzer) parseRelease(r io.Reader) (types.OS, error) { } func (a redhatOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a redhatOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/redhatbase_test.go b/pkg/fanal/analyzer/os/redhatbase/redhatbase_test.go index b47174523a16..27895e609280 100644 --- a/pkg/fanal/analyzer/os/redhatbase/redhatbase_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/redhatbase_test.go @@ -45,8 +45,7 @@ func Test_redhatOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/redhatbase/rocky.go b/pkg/fanal/analyzer/os/redhatbase/rocky.go index ac443d29ae83..95043ec2d3c3 100644 --- a/pkg/fanal/analyzer/os/redhatbase/rocky.go +++ b/pkg/fanal/analyzer/os/redhatbase/rocky.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "os" + "slices" "strings" "golang.org/x/xerrors" @@ -11,7 +12,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" fos "github.com/aquasecurity/trivy/pkg/fanal/analyzer/os" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" ) const rockyAnalyzerVersion = 1 @@ -46,7 +46,7 @@ func (a rockyOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput } func (a rockyOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, a.requiredFiles()) + return slices.Contains(a.requiredFiles(), filePath) } func (a rockyOSAnalyzer) requiredFiles() []string { diff --git a/pkg/fanal/analyzer/os/redhatbase/rocky_test.go b/pkg/fanal/analyzer/os/redhatbase/rocky_test.go index 7b9f3152ea41..75ab9627e7c1 100644 --- a/pkg/fanal/analyzer/os/redhatbase/rocky_test.go +++ b/pkg/fanal/analyzer/os/redhatbase/rocky_test.go @@ -45,8 +45,7 @@ func Test_rockyOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/fanal/analyzer/os/ubuntu/ubuntu_test.go b/pkg/fanal/analyzer/os/ubuntu/ubuntu_test.go index 1aad32e8f124..8c923f33b973 100644 --- a/pkg/fanal/analyzer/os/ubuntu/ubuntu_test.go +++ b/pkg/fanal/analyzer/os/ubuntu/ubuntu_test.go @@ -45,8 +45,7 @@ func Test_ubuntuOSAnalyzer_Analyze(t *testing.T) { Content: f, }) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) diff --git a/pkg/fanal/analyzer/pkg/apk/apk.go b/pkg/fanal/analyzer/pkg/apk/apk.go index 962398600fc5..69cc72eb5d3f 100644 --- a/pkg/fanal/analyzer/pkg/apk/apk.go +++ b/pkg/fanal/analyzer/pkg/apk/apk.go @@ -20,6 +20,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/licensing" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) func init() { @@ -185,13 +186,13 @@ func (a alpinePkgAnalyzer) consolidateDependencies(pkgs []types.Package, provide } func (a alpinePkgAnalyzer) uniquePkgs(pkgs []types.Package) (uniqPkgs []types.Package) { - uniq := make(map[string]struct{}) + uniq := set.New[string]() for _, pkg := range pkgs { - if _, ok := uniq[pkg.Name]; ok { + if uniq.Contains(pkg.Name) { continue } uniqPkgs = append(uniqPkgs, pkg) - uniq[pkg.Name] = struct{}{} + uniq.Append(pkg.Name) } return uniqPkgs } diff --git a/pkg/fanal/analyzer/pkg/rpm/rpm.go b/pkg/fanal/analyzer/pkg/rpm/rpm.go index 70d4de217418..54caec1994b2 100644 --- a/pkg/fanal/analyzer/pkg/rpm/rpm.go +++ b/pkg/fanal/analyzer/pkg/rpm/rpm.go @@ -17,7 +17,6 @@ import ( "github.com/aquasecurity/trivy/pkg/digest" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/fanal/utils" "github.com/aquasecurity/trivy/pkg/log" ) @@ -198,7 +197,7 @@ func (a rpmPkgAnalyzer) listPkgs(ctx context.Context, db RPMDB) (types.Packages, } func (a rpmPkgAnalyzer) Required(filePath string, _ os.FileInfo) bool { - return utils.StringInSlice(filePath, requiredFiles) + return slices.Contains(requiredFiles, filePath) } func (a rpmPkgAnalyzer) Type() analyzer.Type { diff --git a/pkg/fanal/analyzer/sbom/sbom.go b/pkg/fanal/analyzer/sbom/sbom.go index 55768cff3a9b..20a069d52961 100644 --- a/pkg/fanal/analyzer/sbom/sbom.go +++ b/pkg/fanal/analyzer/sbom/sbom.go @@ -4,6 +4,7 @@ import ( "context" "os" "path" + "slices" "strings" "golang.org/x/xerrors" @@ -51,6 +52,14 @@ func (a sbomAnalyzer) Analyze(ctx context.Context, input analyzer.AnalysisInput) handleBitnamiImages(path.Dir(input.FilePath), bom) } + // FilePath for apps with aggregatingTypes is empty. + // Set the SBOM file path as Application.FilePath to correctly overwrite applications when merging layers. + for i, app := range bom.Applications { + if slices.Contains(ftypes.AggregatingTypes, app.Type) && app.FilePath == "" { + bom.Applications[i].FilePath = input.FilePath + } + } + return &analyzer.AnalysisResult{ PackageInfos: bom.Packages, Applications: bom.Applications, diff --git a/pkg/fanal/analyzer/sbom/sbom_test.go b/pkg/fanal/analyzer/sbom/sbom_test.go index 542a7f50addd..3e0f252b17d7 100644 --- a/pkg/fanal/analyzer/sbom/sbom_test.go +++ b/pkg/fanal/analyzer/sbom/sbom_test.go @@ -28,7 +28,34 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) { want: &analyzer.AnalysisResult{ Applications: []types.Application{ { - Type: types.Jar, + Type: types.Bitnami, + FilePath: "opt/bitnami/elasticsearch", + Packages: types.Packages{ + { + ID: "elasticsearch@8.9.1", + Name: "elasticsearch", + Version: "8.9.1", + Arch: "arm64", + Licenses: []string{"Elastic-2.0"}, + Identifier: types.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeBitnami, + Name: "elasticsearch", + Version: "8.9.1", + Qualifiers: packageurl.Qualifiers{ + { + Key: "arch", + Value: "arm64", + }, + }, + }, + }, + }, + }, + }, + { + Type: types.Jar, + FilePath: "opt/bitnami/elasticsearch/.spdx-elasticsearch.spdx", Packages: types.Packages{ { ID: "co.elastic.apm:apm-agent:1.36.0", @@ -88,32 +115,6 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) { }, }, }, - { - Type: types.Bitnami, - FilePath: "opt/bitnami/elasticsearch", - Packages: types.Packages{ - { - ID: "elasticsearch@8.9.1", - Name: "elasticsearch", - Version: "8.9.1", - Arch: "arm64", - Licenses: []string{"Elastic-2.0"}, - Identifier: types.PkgIdentifier{ - PURL: &packageurl.PackageURL{ - Type: packageurl.TypeBitnami, - Name: "elasticsearch", - Version: "8.9.1", - Qualifiers: packageurl.Qualifiers{ - { - Key: "arch", - Value: "arm64", - }, - }, - }, - }, - }, - }, - }, }, }, wantErr: require.NoError, @@ -125,7 +126,8 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) { want: &analyzer.AnalysisResult{ Applications: []types.Application{ { - Type: types.Jar, + Type: types.Jar, + FilePath: "opt/bitnami/elasticsearch/.spdx-elasticsearch.cdx", Packages: types.Packages{ { FilePath: "opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar", diff --git a/pkg/fanal/applier/applier_test.go b/pkg/fanal/applier/applier_test.go index b2a992f80012..95f4d0e8258a 100644 --- a/pkg/fanal/applier/applier_test.go +++ b/pkg/fanal/applier/applier_test.go @@ -961,6 +961,91 @@ func TestApplier_ApplyLayers(t *testing.T) { }, wantErr: "unknown OS", }, + { + name: "SUSE images - legacy OS name with backward compatibility", + args: args{ + imageID: "sha256:fb44d01953611ba18d43d88e158c25579d18eff42db671182245010620a283f3", + layerIDs: []string{ + "sha256:2615f175cf3da67c48c6542914744943ee5e9c253547b03e3cfe8aae605c3199", + }, + }, + getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{ + { + Args: cache.LocalArtifactCacheGetBlobArgs{ + BlobID: "sha256:2615f175cf3da67c48c6542914744943ee5e9c253547b03e3cfe8aae605c3199", + }, + Returns: cache.LocalArtifactCacheGetBlobReturns{ + BlobInfo: types.BlobInfo{ + SchemaVersion: 1, + Digest: "sha256:fb44d01953611ba18d43d88e158c25579d18eff42db671182245010620a283f3", + DiffID: "sha256:d555e1b0b42f21a1cf198e52bcb12fe66aa015348e4390d2d5acddd327d79073", + OS: types.OS{ + Family: "suse linux enterprise server", + Name: "15.4", + }, + PackageInfos: []types.PackageInfo{ + { + FilePath: "usr/lib/sysimage/rpm/Packages.db", + Packages: types.Packages{ + { + Name: "curl", + Version: "7.79.1", + SrcName: "curl", + SrcVersion: "7.79.1", + }, + }, + }, + }, + }, + }, + }, + }, + getArtifactExpectations: []cache.LocalArtifactCacheGetArtifactExpectation{ + { + Args: cache.LocalArtifactCacheGetArtifactArgs{ + ArtifactID: "sha256:fb44d01953611ba18d43d88e158c25579d18eff42db671182245010620a283f3", + }, + Returns: cache.LocalArtifactCacheGetArtifactReturns{ + ArtifactInfo: types.ArtifactInfo{ + SchemaVersion: 1, + }, + }, + }, + }, + want: types.ArtifactDetail{ + OS: types.OS{ + Family: "sles", + Name: "15.4", + }, + Packages: types.Packages{ + { + Name: "curl", + Version: "7.79.1", + SrcName: "curl", + SrcVersion: "7.79.1", + Identifier: types.PkgIdentifier{ + UID: "1e9b3d3a73785651", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeRPM, + Namespace: "suse", + Name: "curl", + Version: "7.79.1", + Qualifiers: packageurl.Qualifiers{ + { + Key: "distro", + Value: "sles-15.4", + }, + }, + }, + }, + Layer: types.Layer{ + Digest: "sha256:fb44d01953611ba18d43d88e158c25579d18eff42db671182245010620a283f3", + DiffID: "sha256:d555e1b0b42f21a1cf198e52bcb12fe66aa015348e4390d2d5acddd327d79073", + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -972,8 +1057,7 @@ func TestApplier_ApplyLayers(t *testing.T) { got, err := a.ApplyLayers(tt.args.imageID, tt.args.layerIDs) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) } else { require.NoError(t, err, tt.name) } diff --git a/pkg/fanal/applier/docker.go b/pkg/fanal/applier/docker.go index 6d1967497ab9..6a12eafddfb4 100644 --- a/pkg/fanal/applier/docker.go +++ b/pkg/fanal/applier/docker.go @@ -1,6 +1,7 @@ package applier import ( + "cmp" "fmt" "strings" "time" @@ -13,7 +14,9 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/purl" + "github.com/aquasecurity/trivy/pkg/scanner/utils" "github.com/aquasecurity/trivy/pkg/types" + xslices "github.com/aquasecurity/trivy/pkg/x/slices" ) type Config struct { @@ -31,9 +34,10 @@ type History struct { } func findPackage(e ftypes.Package, s []ftypes.Package) *ftypes.Package { - for _, a := range s { + for i := range s { + a := &s[i] // do not range by value to avoid heap allocations if a.Name == e.Name && a.Version == e.Version && a.Release == e.Release { - return &a + return a } } return nil @@ -231,6 +235,12 @@ func ApplyLayers(layers []ftypes.BlobInfo) ftypes.ArtifactDetail { } } + // De-duplicate same debian packages from different dirs + // cf. https://github.com/aquasecurity/trivy/issues/8297 + mergedLayer.Packages = xslices.ZeroToNil(lo.UniqBy(mergedLayer.Packages, func(pkg ftypes.Package) string { + return cmp.Or(pkg.ID, fmt.Sprintf("%s@%s", pkg.Name, utils.FormatVersion(pkg))) + })) + for _, app := range mergedLayer.Applications { for i, pkg := range app.Packages { // Skip lookup for SBOM diff --git a/pkg/fanal/applier/docker_test.go b/pkg/fanal/applier/docker_test.go index 93facbd39186..0269bbc7442c 100644 --- a/pkg/fanal/applier/docker_test.go +++ b/pkg/fanal/applier/docker_test.go @@ -254,6 +254,61 @@ func TestApplyLayers(t *testing.T) { }, }, }, + { + name: "happy path with duplicate of debian packages", + inputLayers: []types.BlobInfo{ + { + SchemaVersion: 2, + DiffID: "sha256:96e320b34b5478d8b369ca43ffaa88ff6dd9499ec72b792ca21b1e8b0c55670f", + PackageInfos: []types.PackageInfo{ + { + FilePath: "var/lib/dpkg/status.d/libssl1", + Packages: types.Packages{ + { + ID: "libssl1.1@1.1.1n-0+deb11u3", + Name: "libssl1.1", + Version: "1.1.1n", + Release: "0+deb11u3", + }, + }, + }, + }, + }, + { + SchemaVersion: 2, + DiffID: "sha256:5e087d956f3e62bd034dd0712bc4cbef8fda55fba0b11a7d0564f294887c7079", + PackageInfos: []types.PackageInfo{ + { + FilePath: "var/lib/dpkg/status.d/libssl1.1", + Packages: types.Packages{ + { + ID: "libssl1.1@1.1.1n-0+deb11u3", + Name: "libssl1.1", + Version: "1.1.1n", + Release: "0+deb11u3", + }, + }, + }, + }, + }, + }, + want: types.ArtifactDetail{ + Packages: types.Packages{ + { + ID: "libssl1.1@1.1.1n-0+deb11u3", + Name: "libssl1.1", + Version: "1.1.1n", + Release: "0+deb11u3", + Identifier: types.PkgIdentifier{ + UID: "522a5c3b263d1357", + }, + Layer: types.Layer{ + DiffID: "sha256:96e320b34b5478d8b369ca43ffaa88ff6dd9499ec72b792ca21b1e8b0c55670f", + }, + }, + }, + }, + }, { name: "happy path with digests in libs/packages (as for SBOM)", inputLayers: []types.BlobInfo{ diff --git a/pkg/fanal/artifact/artifact.go b/pkg/fanal/artifact/artifact.go index b6034cb5ac63..6dfa81fa735c 100644 --- a/pkg/fanal/artifact/artifact.go +++ b/pkg/fanal/artifact/artifact.go @@ -14,6 +14,7 @@ import ( ) type Option struct { + Type Type AnalyzerGroup analyzer.Group // It is empty in OSS DisabledAnalyzers []analyzer.Type DisabledHandlers []types.HandlerType @@ -30,6 +31,10 @@ type Option struct { FileChecksum bool // For SPDX DetectionPriority types.DetectionPriority + // Original is the original target location, e.g. "github.com/aquasecurity/trivy" + // Currently, it is used only for remote git repositories + Original string + // Git repositories RepoBranch string RepoCommit string diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index b4350b25b866..cfded3028c78 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -3,13 +3,16 @@ package image import ( "context" "errors" + "fmt" "io" "os" + "path/filepath" "reflect" "slices" "strings" "sync" + "github.com/docker/go-units" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/samber/lo" "golang.org/x/xerrors" @@ -24,6 +27,7 @@ import ( "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/parallel" "github.com/aquasecurity/trivy/pkg/semaphore" + trivyTypes "github.com/aquasecurity/trivy/pkg/types" ) type Artifact struct { @@ -36,6 +40,8 @@ type Artifact struct { handlerManager handler.Manager artifactOption artifact.Option + + layerCacheDir string } type LayerInfo struct { @@ -60,6 +66,11 @@ func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (a return nil, xerrors.Errorf("config analyzer group error: %w", err) } + cacheDir, err := os.MkdirTemp("", "layers") + if err != nil { + return nil, xerrors.Errorf("failed to create a cache layers temp dir: %w", err) + } + return Artifact{ logger: log.WithPrefix("image"), image: img, @@ -70,10 +81,11 @@ func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (a handlerManager: handlerManager, artifactOption: opt, + layerCacheDir: cacheDir, }, nil } -func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { +func (a Artifact) Inspect(ctx context.Context) (ref artifact.Reference, err error) { imageID, err := a.image.ID() if err != nil { return artifact.Reference{}, xerrors.Errorf("unable to get the image ID: %w", err) @@ -88,6 +100,15 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { diffIDs := a.diffIDs(configFile) a.logger.Debug("Detected diff ID", log.Any("diff_ids", diffIDs)) + defer func() { + if rerr := os.RemoveAll(a.layerCacheDir); rerr != nil { + log.Error("Failed to remove layer cache", log.Err(rerr)) + } + }() + if err := a.checkImageSize(ctx, diffIDs); err != nil { + return artifact.Reference{}, err + } + // Try retrieving a remote SBOM document if res, err := a.retrieveRemoteSBOM(ctx); err == nil { // Found SBOM @@ -141,7 +162,7 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { }, nil } -func (Artifact) Clean(_ artifact.Reference) error { +func (a Artifact) Clean(_ artifact.Reference) error { return nil } @@ -198,6 +219,102 @@ func (a Artifact) consolidateCreatedBy(diffIDs, layerKeys []string, configFile * return layerKeyMap } +func (a Artifact) imageSizeError(typ string, size int64) error { + return &trivyTypes.UserError{ + Message: fmt.Sprintf( + "%s size %s exceeds maximum allowed size %s", typ, + units.HumanSizeWithPrecision(float64(size), 3), + units.HumanSize(float64(a.artifactOption.ImageOption.MaxImageSize)), + ), + } +} + +func (a Artifact) checkImageSize(ctx context.Context, diffIDs []string) error { + if a.artifactOption.ImageOption.MaxImageSize == 0 { + return nil + } + + if err := a.checkCompressedImageSize(diffIDs); err != nil { + return xerrors.Errorf("failed to get compressed image size: %w", err) + } + + if err := a.checkUncompressedImageSize(ctx, diffIDs); err != nil { + return xerrors.Errorf("failed to calculate image size: %w", err) + } + return nil +} + +func (a Artifact) checkCompressedImageSize(diffIDs []string) error { + var totalSize int64 + + for _, diffID := range diffIDs { + h, err := v1.NewHash(diffID) + if err != nil { + return xerrors.Errorf("invalid layer ID (%s): %w", diffID, err) + } + + layer, err := a.image.LayerByDiffID(h) + if err != nil { + return xerrors.Errorf("failed to get the layer (%s): %w", diffID, err) + } + layerSize, err := layer.Size() + if err != nil { + return xerrors.Errorf("failed to get layer size: %w", err) + } + totalSize += layerSize + } + + if totalSize > a.artifactOption.ImageOption.MaxImageSize { + return a.imageSizeError("compressed image", totalSize) + } + + return nil +} + +func (a Artifact) checkUncompressedImageSize(ctx context.Context, diffIDs []string) error { + var totalSize int64 + + p := parallel.NewPipeline(a.artifactOption.Parallel, false, diffIDs, + func(_ context.Context, diffID string) (int64, error) { + layerSize, err := a.saveLayer(diffID) + if err != nil { + return -1, xerrors.Errorf("failed to save layer: %w", err) + } + return layerSize, nil + }, + func(layerSize int64) error { + totalSize += layerSize + if totalSize > a.artifactOption.ImageOption.MaxImageSize { + return a.imageSizeError("uncompressed layers", totalSize) + } + return nil + }, + ) + + if err := p.Do(ctx); err != nil { + return xerrors.Errorf("pipeline error: %w", err) + } + + return nil +} + +func (a Artifact) saveLayer(diffID string) (int64, error) { + a.logger.Debug("Pulling the layer to the local cache", log.String("diff_id", diffID)) + _, rc, err := a.uncompressedLayer(diffID) + if err != nil { + return -1, xerrors.Errorf("unable to get uncompressed layer %s: %w", diffID, err) + } + defer rc.Close() + + f, err := os.Create(filepath.Join(a.layerCacheDir, diffID)) + if err != nil { + return -1, xerrors.Errorf("failed to create a file: %w", err) + } + defer f.Close() + + return io.Copy(f, rc) +} + func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]LayerInfo, configFile *v1.ConfigFile) error { @@ -361,6 +478,12 @@ func (a Artifact) uncompressedLayer(diffID string) (string, io.ReadCloser, error digest = d.String() } + f, err := os.Open(filepath.Join(a.layerCacheDir, diffID)) + if err == nil { + a.logger.Debug("Loaded the layer from the local cache", log.String("diff_id", diffID)) + return digest, f, nil + } + rc, err := layer.Uncompressed() if err != nil { return "", nil, xerrors.Errorf("failed to get the layer content (%s): %w", diffID, err) diff --git a/pkg/fanal/artifact/image/image_test.go b/pkg/fanal/artifact/image/image_test.go index f7e80e3cf578..ec8f44c68d01 100644 --- a/pkg/fanal/artifact/image/image_test.go +++ b/pkg/fanal/artifact/image/image_test.go @@ -3,10 +3,13 @@ package image_test import ( "context" "errors" + "math/rand" "testing" "time" + "github.com/docker/go-units" v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/random" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/xerrors" @@ -348,6 +351,7 @@ func TestArtifact_Inspect(t *testing.T) { imagePath: "../../test/testdata/alpine-311.tar.gz", artifactOpt: artifact.Option{ LicenseScannerOption: analyzer.LicenseScannerOption{Full: true}, + ImageOption: types.ImageOptions{MaxImageSize: units.GB}, }, missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{ Args: cache.ArtifactCacheMissingBlobsArgs{ @@ -2262,8 +2266,49 @@ func TestArtifact_Inspect(t *testing.T) { assert.ErrorContains(t, err, tt.wantErr, tt.name) return } + defer a.Clean(got) + require.NoError(t, err, tt.name) assert.Equal(t, tt.want, got) }) } } + +func TestArtifact_InspectWithMaxImageSize(t *testing.T) { + randomImage, err := random.Image(1000, 2, random.WithSource(rand.NewSource(0))) + require.NoError(t, err) + + img := &fakeImage{Image: randomImage} + mockCache := new(cache.MockArtifactCache) + + tests := []struct { + name string + artifactOpt artifact.Option + wantErr string + }{ + { + name: "compressed image size is larger than the maximum", + artifactOpt: artifact.Option{ + ImageOption: types.ImageOptions{MaxImageSize: units.KB * 1}, + }, + wantErr: "compressed image size 2.44kB exceeds maximum allowed size 1kB", + }, + { + name: "uncompressed layers size is larger than the maximum", + artifactOpt: artifact.Option{ + ImageOption: types.ImageOptions{MaxImageSize: units.KB * 3}, + }, + wantErr: "uncompressed layers size 5.12kB exceeds maximum allowed size 3kB", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + artifact, err := image2.NewArtifact(img, mockCache, tt.artifactOpt) + require.NoError(t, err) + + _, err = artifact.Inspect(context.Background()) + require.ErrorContains(t, err, tt.wantErr) + }) + } +} diff --git a/pkg/fanal/artifact/image/remote_sbom_test.go b/pkg/fanal/artifact/image/remote_sbom_test.go index bdd2562101f1..c8059071fee4 100644 --- a/pkg/fanal/artifact/image/remote_sbom_test.go +++ b/pkg/fanal/artifact/image/remote_sbom_test.go @@ -31,7 +31,7 @@ func TestMain(m *testing.M) { type fakeImage struct { name string repoDigests []string - *fakei.FakeImage + v1.Image types.ImageExtension } @@ -160,7 +160,7 @@ func TestArtifact_InspectRekorAttestation(t *testing.T) { img := &fakeImage{ name: tt.fields.imageName, repoDigests: tt.fields.repoDigests, - FakeImage: fi, + Image: fi, } a, err := image2.NewArtifact(img, mockCache, tt.artifactOpt) require.NoError(t, err) @@ -170,6 +170,8 @@ func TestArtifact_InspectRekorAttestation(t *testing.T) { assert.ErrorContains(t, err, tt.wantErr) return } + defer a.Clean(got) + require.NoError(t, err, tt.name) got.BOM = nil assert.Equal(t, tt.want, got) @@ -302,7 +304,7 @@ func TestArtifact_inspectOCIReferrerSBOM(t *testing.T) { img := &fakeImage{ name: tt.fields.imageName, repoDigests: tt.fields.repoDigests, - FakeImage: fi, + Image: fi, } a, err := image2.NewArtifact(img, mockCache, tt.artifactOpt) require.NoError(t, err) @@ -312,6 +314,7 @@ func TestArtifact_inspectOCIReferrerSBOM(t *testing.T) { assert.ErrorContains(t, err, tt.wantErr) return } + defer a.Clean(got) require.NoError(t, err, tt.name) got.BOM = nil diff --git a/pkg/fanal/artifact/local/fs.go b/pkg/fanal/artifact/local/fs.go index b6c2d46c839a..a0f220bbe9cf 100644 --- a/pkg/fanal/artifact/local/fs.go +++ b/pkg/fanal/artifact/local/fs.go @@ -1,17 +1,20 @@ package local import ( + "cmp" "context" "crypto/sha256" - "encoding/json" + "errors" "os" "path" "path/filepath" "strings" "sync" + "github.com/go-git/go-git/v5" "github.com/google/wire" "github.com/opencontainers/go-digest" + "github.com/samber/lo" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/cache" @@ -20,7 +23,9 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/handler" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" + "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/semaphore" + "github.com/aquasecurity/trivy/pkg/uuid" ) var ( @@ -39,12 +44,15 @@ type Walker interface { type Artifact struct { rootPath string + logger *log.Logger cache cache.ArtifactCache walker Walker analyzer analyzer.AnalyzerGroup handlerManager handler.Manager artifactOption artifact.Option + + commitHash string // only set when the git repository is clean } func NewArtifact(rootPath string, c cache.ArtifactCache, w Walker, opt artifact.Option) (artifact.Artifact, error) { @@ -58,17 +66,92 @@ func NewArtifact(rootPath string, c cache.ArtifactCache, w Walker, opt artifact. return nil, xerrors.Errorf("analyzer group error: %w", err) } - return Artifact{ + opt.Type = cmp.Or(opt.Type, artifact.TypeFilesystem) + prefix := lo.Ternary(opt.Type == artifact.TypeRepository, "repo", "fs") + + art := Artifact{ rootPath: filepath.ToSlash(filepath.Clean(rootPath)), + logger: log.WithPrefix(prefix), cache: c, walker: w, analyzer: a, handlerManager: handlerManager, artifactOption: opt, - }, nil + } + + art.logger.Debug("Analyzing...", log.String("root", art.rootPath), + lo.Ternary(opt.Original != "", log.String("original", opt.Original), log.Nil)) + + // Check if the directory is a git repository and clean + if hash, err := gitCommitHash(art.rootPath); err == nil { + art.logger.Debug("Using the latest commit hash for calculating cache key", log.String("commit_hash", hash)) + art.commitHash = hash + } else if !errors.Is(err, git.ErrRepositoryNotExists) { + // Only log if the file path is a git repository + art.logger.Debug("Random cache key will be used", log.Err(err)) + } + + return art, nil +} + +// gitCommitHash returns the latest commit hash if the git repository is clean, otherwise returns an error +func gitCommitHash(dir string) (string, error) { + repo, err := git.PlainOpen(dir) + if err != nil { + return "", xerrors.Errorf("failed to open git repository: %w", err) + } + + // Get the working tree + worktree, err := repo.Worktree() + if err != nil { + return "", xerrors.Errorf("failed to get worktree: %w", err) + } + + // Get the current status + status, err := worktree.Status() + if err != nil { + return "", xerrors.Errorf("failed to get status: %w", err) + } + + if !status.IsClean() { + return "", xerrors.New("repository is dirty") + } + + // Get the HEAD commit hash + head, err := repo.Head() + if err != nil { + return "", xerrors.Errorf("failed to get HEAD: %w", err) + } + + return head.Hash().String(), nil } func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { + // Calculate cache key + cacheKey, err := a.calcCacheKey() + if err != nil { + return artifact.Reference{}, xerrors.Errorf("failed to calculate a cache key: %w", err) + } + + // Check if the cache exists only when it's a clean git repository + if a.commitHash != "" { + _, missingBlobs, err := a.cache.MissingBlobs(cacheKey, []string{cacheKey}) + if err != nil { + return artifact.Reference{}, xerrors.Errorf("unable to get missing blob: %w", err) + } + + if len(missingBlobs) == 0 { + // Cache hit + a.logger.DebugContext(ctx, "Cache hit", log.String("key", cacheKey)) + return artifact.Reference{ + Name: cmp.Or(a.artifactOption.Original, a.rootPath), + Type: a.artifactOption.Type, + ID: cacheKey, + BlobIDs: []string{cacheKey}, + }, nil + } + } + var wg sync.WaitGroup result := analyzer.NewAnalysisResult() limit := semaphore.New(a.artifactOption.Parallel) @@ -141,11 +224,6 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { return artifact.Reference{}, xerrors.Errorf("failed to call hooks: %w", err) } - cacheKey, err := a.calcCacheKey(blobInfo) - if err != nil { - return artifact.Reference{}, xerrors.Errorf("failed to calculate a cache key: %w", err) - } - if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil { return artifact.Reference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err) } @@ -156,34 +234,39 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { if err == nil && len(b) != 0 { hostName = strings.TrimSpace(string(b)) } else { - // To slash for Windows - hostName = filepath.ToSlash(a.rootPath) + target := cmp.Or(a.artifactOption.Original, a.rootPath) + hostName = filepath.ToSlash(target) // To slash for Windows } return artifact.Reference{ Name: hostName, - Type: artifact.TypeFilesystem, + Type: a.artifactOption.Type, ID: cacheKey, // use a cache key as pseudo artifact ID BlobIDs: []string{cacheKey}, }, nil } func (a Artifact) Clean(reference artifact.Reference) error { + // Don't delete cache if it's a clean git repository + if a.commitHash != "" { + return nil + } return a.cache.DeleteBlobs(reference.BlobIDs) } -func (a Artifact) calcCacheKey(blobInfo types.BlobInfo) (string, error) { - // calculate hash of JSON and use it as pseudo artifactID and blobID - h := sha256.New() - if err := json.NewEncoder(h).Encode(blobInfo); err != nil { - return "", xerrors.Errorf("json error: %w", err) +func (a Artifact) calcCacheKey() (string, error) { + // If this is a clean git repository, use the commit hash as cache key + if a.commitHash != "" { + return cache.CalcKey(a.commitHash, a.analyzer.AnalyzerVersions(), a.handlerManager.Versions(), a.artifactOption) } - d := digest.NewDigest(digest.SHA256, h) - cacheKey, err := cache.CalcKey(d.String(), a.analyzer.AnalyzerVersions(), a.handlerManager.Versions(), a.artifactOption) - if err != nil { - return "", xerrors.Errorf("cache key: %w", err) + // For non-git repositories or dirty git repositories, use UUID as cache key + h := sha256.New() + if _, err := h.Write([]byte(uuid.New().String())); err != nil { + return "", xerrors.Errorf("sha256 calculation error: %w", err) } - return cacheKey, nil + // Format as sha256 digest + d := digest.NewDigest(digest.SHA256, h) + return d.String(), nil } diff --git a/pkg/fanal/artifact/local/fs_test.go b/pkg/fanal/artifact/local/fs_test.go index 868bdf6a8b8d..7b7ed4503ac4 100644 --- a/pkg/fanal/artifact/local/fs_test.go +++ b/pkg/fanal/artifact/local/fs_test.go @@ -16,6 +16,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" "github.com/aquasecurity/trivy/pkg/misconf" + "github.com/aquasecurity/trivy/pkg/uuid" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/config/all" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/python/pip" @@ -47,7 +48,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:5ba63074e071e3f0247d03dd7e544b6a75f7224ee238618482c490b36f4792dc", + BlobID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, OS: types.OS{ @@ -82,9 +83,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "host", Type: artifact.TypeFilesystem, - ID: "sha256:5ba63074e071e3f0247d03dd7e544b6a75f7224ee238618482c490b36f4792dc", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:5ba63074e071e3f0247d03dd7e544b6a75f7224ee238618482c490b36f4792dc", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -102,7 +103,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:649ddb291d142363aafcf9e9cf8a6e32dc0a6ae5a95ab43d09b8201d86ed8f7a", + BlobID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, }, @@ -112,9 +113,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "host", Type: artifact.TypeFilesystem, - ID: "sha256:649ddb291d142363aafcf9e9cf8a6e32dc0a6ae5a95ab43d09b8201d86ed8f7a", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:649ddb291d142363aafcf9e9cf8a6e32dc0a6ae5a95ab43d09b8201d86ed8f7a", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -125,7 +126,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:5ba63074e071e3f0247d03dd7e544b6a75f7224ee238618482c490b36f4792dc", + BlobID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, OS: types.OS{ @@ -175,7 +176,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + BlobID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Applications: []types.Application{ @@ -203,9 +204,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "testdata/requirements.txt", Type: artifact.TypeFilesystem, - ID: "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -216,7 +217,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + BlobID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Applications: []types.Application{ @@ -244,15 +245,18 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "testdata/requirements.txt", Type: artifact.TypeFilesystem, - ID: "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:00e49bf14e0a8c15b2d611d8e5c231276f1e10f22b3307177e513605fd18d807", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) @@ -261,8 +265,7 @@ func TestArtifact_Inspect(t *testing.T) { got, err := a.Inspect(context.Background()) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } else { require.NoError(t, err) @@ -332,9 +335,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/single-failure", Type: artifact.TypeFilesystem, - ID: "sha256:4f2a334086f1d175c0ee57cd4220f20b187b456dc36bbe39a63c42b5637b2179", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:4f2a334086f1d175c0ee57cd4220f20b187b456dc36bbe39a63c42b5637b2179", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -408,9 +411,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/multiple-failures", Type: artifact.TypeFilesystem, - ID: "sha256:ff7a84de97729e169c94107a89bc9da88f5ecf94873cdbd9bf0844e1af5f5b30", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:ff7a84de97729e169c94107a89bc9da88f5ecf94873cdbd9bf0844e1af5f5b30", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -431,9 +434,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/no-results", Type: artifact.TypeFilesystem, - ID: "sha256:06406e9bb7ba09d8d24c73c0995ac3b94fc1d6ce059e5a45418d7c0ab2b6dca4", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:06406e9bb7ba09d8d24c73c0995ac3b94fc1d6ce059e5a45418d7c0ab2b6dca4", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -471,9 +474,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/passed", Type: artifact.TypeFilesystem, - ID: "sha256:107251e6ee7312c8c27ff04e71dd943b92021777c575971809f57b60bf41bba4", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:107251e6ee7312c8c27ff04e71dd943b92021777c575971809f57b60bf41bba4", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -528,9 +531,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/busted-relative-paths/child/main.tf", Type: artifact.TypeFilesystem, - ID: "sha256:f2f07f41dbd6816d41ce6f28b3922fcedab611b8602d95e328571afd5c53b31d", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:f2f07f41dbd6816d41ce6f28b3922fcedab611b8602d95e328571afd5c53b31d", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -573,9 +576,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/tfvar-outside/tf", Type: artifact.TypeFilesystem, - ID: "sha256:107251e6ee7312c8c27ff04e71dd943b92021777c575971809f57b60bf41bba4", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:107251e6ee7312c8c27ff04e71dd943b92021777c575971809f57b60bf41bba4", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -655,15 +658,18 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/relative-paths/child", Type: artifact.TypeFilesystem, - ID: "sha256:f04c37d8e5300ce9344c795c2d4e0bb1dbef251b15538a6e0c11d6d9a86664d1", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:f04c37d8e5300ce9344c795c2d4e0bb1dbef251b15538a6e0c11d6d9a86664d1", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) tt.artifactOpt.DisabledHandlers = []types.HandlerType{ @@ -776,9 +782,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/single-failure", Type: artifact.TypeFilesystem, - ID: "sha256:c21e15d7d0cfe7c1ef1e1933b443f781d1411b864500431302a1e45fe0950529", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:c21e15d7d0cfe7c1ef1e1933b443f781d1411b864500431302a1e45fe0950529", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -852,9 +858,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/multiple-failures", Type: artifact.TypeFilesystem, - ID: "sha256:800c9ce07be36c7f4d1a4876ecfaaa77c1d90b15f43c58eaf52ea27670afcc42", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:800c9ce07be36c7f4d1a4876ecfaaa77c1d90b15f43c58eaf52ea27670afcc42", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -892,15 +898,17 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/passed", Type: artifact.TypeFilesystem, - ID: "sha256:3d90bb96d2dc0af277ab0ce28972670eb81968d00775d1e92edce54ae2d165c0", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:3d90bb96d2dc0af277ab0ce28972670eb81968d00775d1e92edce54ae2d165c0", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") tmpDir := t.TempDir() f, err := os.Create(filepath.Join(tmpDir, "policy.rego")) @@ -1002,9 +1010,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:bd481a673eb07ed7b51e1ff2a6e7aca08b433d11288eb9f5e9aa2d2f482a0c16", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:bd481a673eb07ed7b51e1ff2a6e7aca08b433d11288eb9f5e9aa2d2f482a0c16", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1084,9 +1092,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:c25676d23114b9c912067d45285cd9e662cefae5e3cc82c40f67df5fee39f92a", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:c25676d23114b9c912067d45285cd9e662cefae5e3cc82c40f67df5fee39f92a", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1114,9 +1122,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:522b19ad182f50b7b04217831c914df52c2d2eb1bdddb02eb9cd2b4e14c9a32b", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:522b19ad182f50b7b04217831c914df52c2d2eb1bdddb02eb9cd2b4e14c9a32b", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1170,9 +1178,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/params/code/src", Type: artifact.TypeFilesystem, - ID: "sha256:40d6550292de7518fd7229f7b14803c67cbffbad3376e773ad7e6dc003846e87", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:40d6550292de7518fd7229f7b14803c67cbffbad3376e773ad7e6dc003846e87", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1226,15 +1234,18 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:e2269b8ea44e29aedeaeea83368f879b3fb0cb97bfe46bcca4383a637280cace", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:e2269b8ea44e29aedeaeea83368f879b3fb0cb97bfe46bcca4383a637280cace", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) tt.artifactOpt.DisabledHandlers = []types.HandlerType{ @@ -1312,9 +1323,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:3551bddb0f53fb9e0c32390e3ac33f841e3cc15a52ddbcbd9ea07f7e6d1d4437", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:3551bddb0f53fb9e0c32390e3ac33f841e3cc15a52ddbcbd9ea07f7e6d1d4437", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1368,9 +1379,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:3551bddb0f53fb9e0c32390e3ac33f841e3cc15a52ddbcbd9ea07f7e6d1d4437", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:3551bddb0f53fb9e0c32390e3ac33f841e3cc15a52ddbcbd9ea07f7e6d1d4437", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1397,9 +1408,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:e57ad1b0be7370a131e1265a25ac8790bbfec2bb5867315916cf92799e5855d3", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:e57ad1b0be7370a131e1265a25ac8790bbfec2bb5867315916cf92799e5855d3", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1455,15 +1466,18 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:ff4a3a7aed57bd8190277cf2cc16213eef43b7a37f26f8458525f2efd9793e8f", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:ff4a3a7aed57bd8190277cf2cc16213eef43b7a37f26f8458525f2efd9793e8f", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) tt.artifactOpt.DisabledHandlers = []types.HandlerType{ @@ -1546,9 +1560,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:63ceedb6582e29ee4184b8b776ee27efe226d07a932461639c05bfbe47bf7efa", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:63ceedb6582e29ee4184b8b776ee27efe226d07a932461639c05bfbe47bf7efa", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1630,9 +1644,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:47fcc85b182385fc6cd7ca08270efff33281ba7717c7a97c7b28a47bef24fae3", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:47fcc85b182385fc6cd7ca08270efff33281ba7717c7a97c7b28a47bef24fae3", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1659,9 +1673,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:4aad6cb079f406935fa383e126616cee6c82e326a92c163042d6043596f18e04", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:4aad6cb079f406935fa383e126616cee6c82e326a92c163042d6043596f18e04", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1717,15 +1731,18 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:b781859c685b32a25e96e54b331957d696cedfc98162146819ac64d3f157660e", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:b781859c685b32a25e96e54b331957d696cedfc98162146819ac64d3f157660e", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) tt.artifactOpt.DisabledHandlers = []types.HandlerType{ @@ -1806,9 +1823,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:62a167d993f603f5552042e4b3c7ac3a65dbbe62bad28e72631c69c9a8f5e2b5", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:62a167d993f603f5552042e4b3c7ac3a65dbbe62bad28e72631c69c9a8f5e2b5", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1887,9 +1904,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:3cc8c966f10a75dc902589329cf202168176243ef8fdec7219452bb54d02af8e", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:3cc8c966f10a75dc902589329cf202168176243ef8fdec7219452bb54d02af8e", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1916,9 +1933,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:522b19ad182f50b7b04217831c914df52c2d2eb1bdddb02eb9cd2b4e14c9a32b", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:522b19ad182f50b7b04217831c914df52c2d2eb1bdddb02eb9cd2b4e14c9a32b", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, @@ -1971,15 +1988,18 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:d6a4722cb6865cac6f55c1789d64c57479539e9198722519918764a230586b4b", + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", BlobIDs: []string{ - "sha256:d6a4722cb6865cac6f55c1789d64c57479539e9198722519918764a230586b4b", + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + // Set fake UUID for consistent test results + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + c := new(cache.MockArtifactCache) c.ApplyPutBlobExpectation(tt.putBlobExpectation) tt.artifactOpt.DisabledHandlers = []types.HandlerType{ diff --git a/pkg/fanal/artifact/repo/git.go b/pkg/fanal/artifact/repo/git.go index 4532b631c6b7..ebd7458f33c7 100644 --- a/pkg/fanal/artifact/repo/git.go +++ b/pkg/fanal/artifact/repo/git.go @@ -1,7 +1,6 @@ package repo import ( - "context" "net/url" "os" @@ -32,17 +31,12 @@ type Walker interface { Walk(root string, opt walker.Option, fn walker.WalkFunc) error } -type Artifact struct { - url string - local artifact.Artifact -} - -func NewArtifact(target string, c cache.ArtifactCache, w Walker, artifactOpt artifact.Option) ( - artifact.Artifact, func(), error) { - +func NewArtifact(target string, c cache.ArtifactCache, w Walker, artifactOpt artifact.Option) (artifact.Artifact, func(), error) { var cleanup func() var errs error + artifactOpt.Type = artifact.TypeRepository + // Try the local repository art, err := tryLocalRepo(target, c, w, artifactOpt) if err == nil { @@ -61,24 +55,6 @@ func NewArtifact(target string, c cache.ArtifactCache, w Walker, artifactOpt art return nil, cleanup, errs } -func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { - ref, err := a.local.Inspect(ctx) - if err != nil { - return artifact.Reference{}, xerrors.Errorf("remote repository error: %w", err) - } - - if a.url != "" { - ref.Name = a.url - } - ref.Type = artifact.TypeRepository - - return ref, nil -} - -func (Artifact) Clean(_ artifact.Reference) error { - return nil -} - func tryLocalRepo(target string, c cache.ArtifactCache, w Walker, artifactOpt artifact.Option) (artifact.Artifact, error) { if _, err := os.Stat(target); err != nil { return nil, xerrors.Errorf("no such path: %w", err) @@ -88,9 +64,7 @@ func tryLocalRepo(target string, c cache.ArtifactCache, w Walker, artifactOpt ar if err != nil { return nil, xerrors.Errorf("local repo artifact error: %w", err) } - return Artifact{ - local: art, - }, nil + return art, nil } func tryRemoteRepo(target string, c cache.ArtifactCache, w Walker, artifactOpt artifact.Option) (artifact.Artifact, func(), error) { @@ -107,15 +81,13 @@ func tryRemoteRepo(target string, c cache.ArtifactCache, w Walker, artifactOpt a cleanup = func() { _ = os.RemoveAll(tmpDir) } + artifactOpt.Original = target art, err := local.NewArtifact(tmpDir, c, w, artifactOpt) if err != nil { return nil, cleanup, xerrors.Errorf("fs artifact: %w", err) } - return Artifact{ - url: target, - local: art, - }, cleanup, nil + return art, cleanup, nil } diff --git a/pkg/fanal/artifact/repo/git_test.go b/pkg/fanal/artifact/repo/git_test.go index fbfbe39ff85f..8d2dbd037fdb 100644 --- a/pkg/fanal/artifact/repo/git_test.go +++ b/pkg/fanal/artifact/repo/git_test.go @@ -4,45 +4,28 @@ package repo import ( "context" - "net/http/httptest" + "os" + "path/filepath" "testing" - "github.com/go-git/go-git/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/gittest" "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" + "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" + "github.com/aquasecurity/trivy/pkg/uuid" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/config/all" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/secret" ) -func setupGitRepository(t *testing.T, repo, dir string) (*httptest.Server, *git.Repository) { - gs := gittest.NewServer(t, repo, dir) - - worktree := t.TempDir() - r := gittest.Clone(t, gs, repo, worktree) - - // Branch - gittest.CreateRemoteBranch(t, r, "valid-branch") - - // Tag - gittest.SetTag(t, r, "v1.0.0") - gittest.PushTags(t, r) - - return gs, r -} - func TestNewArtifact(t *testing.T) { - ts, repo := setupGitRepository(t, "test-repo", "testdata/test-repo") + ts := gittest.NewTestServer(t) defer ts.Close() - head, err := repo.Head() - require.NoError(t, err) - type args struct { target string c cache.ArtifactCache @@ -68,7 +51,7 @@ func TestNewArtifact(t *testing.T) { { name: "local repo", args: args{ - target: "testdata", + target: "../../../../internal/gittest/testdata/test-repo", c: nil, noProgress: false, }, @@ -97,7 +80,7 @@ func TestNewArtifact(t *testing.T) { args: args{ target: ts.URL + "/test-repo.git", c: nil, - repoTag: "v1.0.0", + repoTag: "v0.0.1", }, assertion: assert.NoError, }, @@ -106,7 +89,7 @@ func TestNewArtifact(t *testing.T) { args: args{ target: ts.URL + "/test-repo.git", c: nil, - repoCommit: head.String(), + repoCommit: "8a19b492a589955c3e70c6ad8efd1e4ec6ae0d35", }, assertion: assert.NoError, }, @@ -182,24 +165,97 @@ func TestNewArtifact(t *testing.T) { } func TestArtifact_Inspect(t *testing.T) { - ts, _ := setupGitRepository(t, "test-repo", "testdata/test-repo") + ts := gittest.NewTestServer(t) defer ts.Close() tests := []struct { - name string - rawurl string - want artifact.Reference - wantErr bool + name string + rawurl string + setup func(t *testing.T, dir string, c cache.ArtifactCache) + want artifact.Reference + wantBlobInfo *types.BlobInfo + wantErr bool }{ { - name: "happy path", + name: "remote repo", rawurl: ts.URL + "/test-repo.git", want: artifact.Reference{ Name: ts.URL + "/test-repo.git", Type: artifact.TypeRepository, - ID: "sha256:88233504639eb201433a0505956309ba0c48156f45beb786f95ccd3e8a343e9d", + ID: "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", // Calculated from commit hash BlobIDs: []string{ - "sha256:88233504639eb201433a0505956309ba0c48156f45beb786f95ccd3e8a343e9d", + "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", // Calculated from commit hash + }, + }, + wantBlobInfo: &types.BlobInfo{ + SchemaVersion: types.BlobJSONSchemaVersion, + }, + }, + { + name: "local repo", + rawurl: "../../../../internal/gittest/testdata/test-repo", + want: artifact.Reference{ + Name: "../../../../internal/gittest/testdata/test-repo", + Type: artifact.TypeRepository, + ID: "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", // Calculated from commit hash + BlobIDs: []string{ + "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", // Calculated from commit hash + }, + }, + wantBlobInfo: &types.BlobInfo{ + SchemaVersion: types.BlobJSONSchemaVersion, + }, + }, + { + name: "dirty repository", + rawurl: "../../../../internal/gittest/testdata/test-repo", + setup: func(t *testing.T, dir string, _ cache.ArtifactCache) { + require.NoError(t, os.WriteFile(filepath.Join(dir, "new-file.txt"), []byte("test"), 0644)) + t.Cleanup(func() { + require.NoError(t, os.Remove(filepath.Join(dir, "new-file.txt"))) + }) + }, + want: artifact.Reference{ + Name: "../../../../internal/gittest/testdata/test-repo", + Type: artifact.TypeRepository, + ID: "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", + BlobIDs: []string{ + "sha256:6f4672e139d4066fd00391df614cdf42bda5f7a3f005d39e1d8600be86157098", + }, + }, + wantBlobInfo: &types.BlobInfo{ + SchemaVersion: types.BlobJSONSchemaVersion, + }, + }, + { + name: "cache hit", + rawurl: "../../../../internal/gittest/testdata/test-repo", + setup: func(t *testing.T, dir string, c cache.ArtifactCache) { + blobInfo := types.BlobInfo{ + SchemaVersion: types.BlobJSONSchemaVersion, + OS: types.OS{ + Family: types.Alpine, + Name: "3.16.0", + }, + } + // Store the blob info in the cache to test cache hit + cacheKey := "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c" + err := c.PutBlob(cacheKey, blobInfo) + require.NoError(t, err) + }, + want: artifact.Reference{ + Name: "../../../../internal/gittest/testdata/test-repo", + Type: artifact.TypeRepository, + ID: "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", + BlobIDs: []string{ + "sha256:dc7c6039424c9fce969d3c2972d261af442a33f13e7494464386dbe280612d4c", + }, + }, + wantBlobInfo: &types.BlobInfo{ + SchemaVersion: types.BlobJSONSchemaVersion, + OS: types.OS{ + Family: types.Alpine, + Name: "3.16.0", }, }, }, @@ -207,16 +263,34 @@ func TestArtifact_Inspect(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - fsCache, err := cache.NewFSCache(t.TempDir()) - require.NoError(t, err) + // Set fake UUID for consistency + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + + // Create memory cache + c := cache.NewMemoryCache() + + // Apply setup if specified + if tt.setup != nil { + tt.setup(t, tt.rawurl, c) + } - art, cleanup, err := NewArtifact(tt.rawurl, fsCache, walker.NewFS(), artifact.Option{}) + art, cleanup, err := NewArtifact(tt.rawurl, c, walker.NewFS(), artifact.Option{}) require.NoError(t, err) defer cleanup() ref, err := art.Inspect(context.Background()) + if tt.wantErr { + assert.Error(t, err) + return + } + require.NoError(t, err) assert.Equal(t, tt.want, ref) + + // Verify cache contents after inspection + blobInfo, err := c.GetBlob(tt.want.BlobIDs[0]) + require.NoError(t, err) + assert.Equal(t, tt.wantBlobInfo, &blobInfo, "cache content mismatch") }) } } @@ -257,13 +331,10 @@ func Test_newURL(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := newURL(tt.args.rawurl) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return - } else { - require.NoError(t, err) } - + require.NoError(t, err) assert.Equal(t, tt.want, got.String()) }) } diff --git a/pkg/fanal/artifact/repo/testdata/test-repo/anothertest.txt b/pkg/fanal/artifact/repo/testdata/test-repo/anothertest.txt deleted file mode 100644 index f4836be6497e..000000000000 --- a/pkg/fanal/artifact/repo/testdata/test-repo/anothertest.txt +++ /dev/null @@ -1 +0,0 @@ -this is another text file. \ No newline at end of file diff --git a/pkg/fanal/artifact/repo/testdata/test-repo/test.txt b/pkg/fanal/artifact/repo/testdata/test-repo/test.txt deleted file mode 100644 index c042cd14d2b9..000000000000 --- a/pkg/fanal/artifact/repo/testdata/test-repo/test.txt +++ /dev/null @@ -1 +0,0 @@ -this is a text file. \ No newline at end of file diff --git a/pkg/fanal/image/daemon/image.go b/pkg/fanal/image/daemon/image.go index d3787cc0abc7..d650851ad242 100644 --- a/pkg/fanal/image/daemon/image.go +++ b/pkg/fanal/image/daemon/image.go @@ -226,9 +226,9 @@ func (img *image) imageConfig(config *container.Config) v1.Config { } if len(config.ExposedPorts) > 0 { - c.ExposedPorts = make(map[string]struct{}) - for port := range c.ExposedPorts { - c.ExposedPorts[port] = struct{}{} + c.ExposedPorts = make(map[string]struct{}) //nolint: gocritic + for port := range config.ExposedPorts { + c.ExposedPorts[port.Port()] = struct{}{} } } diff --git a/pkg/fanal/image/image_test.go b/pkg/fanal/image/image_test.go index 2728ddc45184..555fe79cf509 100644 --- a/pkg/fanal/image/image_test.go +++ b/pkg/fanal/image/image_test.go @@ -397,8 +397,7 @@ func TestNewDockerImageWithPrivateRegistry(t *testing.T) { defer cleanup() if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, err) + require.ErrorContains(t, err, tt.wantErr, err) } else { require.NoError(t, err) } @@ -488,8 +487,7 @@ func TestNewArchiveImage(t *testing.T) { img, err := NewArchiveImage(tt.args.fileName) switch { case tt.wantErr != "": - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return default: require.NoError(t, err, tt.name) diff --git a/pkg/fanal/image/oci_test.go b/pkg/fanal/image/oci_test.go index 4256a56ae9f8..a527e34f256f 100644 --- a/pkg/fanal/image/oci_test.go +++ b/pkg/fanal/image/oci_test.go @@ -4,7 +4,6 @@ import ( "path/filepath" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -62,8 +61,7 @@ func TestTryOCI(t *testing.T) { t.Run(test.name, func(t *testing.T) { _, err := tryOCI(test.ociImagePath) if test.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), test.wantErr, err) + require.ErrorContains(t, err, test.wantErr, err) } else { require.NoError(t, err) } diff --git a/pkg/fanal/test/integration/registry_test.go b/pkg/fanal/test/integration/registry_test.go index 35a32536600e..e6fc7445cc87 100644 --- a/pkg/fanal/test/integration/registry_test.go +++ b/pkg/fanal/test/integration/registry_test.go @@ -256,6 +256,7 @@ func analyze(ctx context.Context, imageRef string, opt types.ImageOptions) (*typ if err != nil { return nil, err } + defer ar.Clean(imageInfo) imageDetail, err := ap.ApplyLayers(imageInfo.ID, imageInfo.BlobIDs) if err != nil { diff --git a/pkg/fanal/types/artifact.go b/pkg/fanal/types/artifact.go index b25aaa954188..a3f861d4e910 100644 --- a/pkg/fanal/types/artifact.go +++ b/pkg/fanal/types/artifact.go @@ -15,10 +15,25 @@ type OS struct { Extended bool `json:"extended,omitempty"` } +func (o *OS) String() string { + s := string(o.Family) + if o.Name != "" { + s += "/" + o.Name + } + return s +} + func (o *OS) Detected() bool { return o.Family != "" } +// Normalize normalizes OS family names for backward compatibility +func (o *OS) Normalize() { + if alias, ok := OSTypeAliases[o.Family]; ok { + o.Family = alias + } +} + // Merge merges OS version and enhanced security maintenance programs func (o *OS) Merge(newOS OS) { if lo.IsEmpty(newOS) { @@ -45,6 +60,11 @@ func (o *OS) Merge(newOS OS) { o.Extended = true } } + // When merging layers, there are cases when a layer contains an OS with an old name: + // - Cache contains a layer derived from an old version of Trivy. + // - `client` uses an old version of Trivy, but `server` is a new version of Trivy (for `client/server` mode). + // So we need to normalize the OS name for backward compatibility. + o.Normalize() } type Repository struct { diff --git a/pkg/fanal/types/artifact_test.go b/pkg/fanal/types/artifact_test.go new file mode 100644 index 000000000000..7da117699c4c --- /dev/null +++ b/pkg/fanal/types/artifact_test.go @@ -0,0 +1,53 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestOS_String(t *testing.T) { + type fields struct { + Family OSType + Name string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "family and name", + fields: fields{ + Family: OSType("ubuntu"), + Name: "22.04", + }, + want: "ubuntu/22.04", + }, + { + name: "empty name", + fields: fields{ + Family: OSType("ubuntu"), + Name: "", + }, + want: "ubuntu", + }, + { + name: "empty", + fields: fields{ + Family: "", + Name: "", + }, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OS{ + Family: tt.fields.Family, + Name: tt.fields.Name, + } + assert.Equal(t, tt.want, o.String()) + }) + } +} diff --git a/pkg/fanal/types/const.go b/pkg/fanal/types/const.go index 2e746f065782..d7e0a4ec0a68 100644 --- a/pkg/fanal/types/const.go +++ b/pkg/fanal/types/const.go @@ -43,6 +43,15 @@ const ( Wolfi OSType = "wolfi" ) +// OSTypeAliases is a map of aliases for operating systems. +// This is used to map the old family names to the new ones for backward compatibility. +var OSTypeAliases = map[OSType]OSType{ + "opensuse.leap": OpenSUSELeap, + "opensuse.tumbleweed": OpenSUSETumbleweed, + "suse linux enterprise micro": SLEMicro, + "suse linux enterprise server": SLES, +} + // Programming language dependencies const ( Bundler LangType = "bundler" @@ -57,6 +66,7 @@ const ( Pip LangType = "pip" Pipenv LangType = "pipenv" Poetry LangType = "poetry" + Uv LangType = "uv" CondaPkg LangType = "conda-pkg" CondaEnv LangType = "conda-environment" PythonPkg LangType = "python-pkg" @@ -87,13 +97,37 @@ const ( OCP LangType = "ocp" // Red Hat OpenShift Container Platform ) -var AggregatingTypes = []LangType{ - PythonPkg, - CondaPkg, - GemSpec, - NodePkg, - Jar, -} +var ( + OSTypes = []OSType{ + Alma, + Alpine, + Amazon, + Azure, + CBLMariner, + CentOS, + Chainguard, + Debian, + Fedora, + OpenSUSE, + OpenSUSELeap, + OpenSUSETumbleweed, + Oracle, + Photon, + RedHat, + Rocky, + SLEMicro, + SLES, + Ubuntu, + Wolfi, + } + AggregatingTypes = []LangType{ + PythonPkg, + CondaPkg, + GemSpec, + NodePkg, + Jar, + } +) // Config files const ( @@ -134,6 +168,7 @@ const ( PipRequirements = "requirements.txt" PipfileLock = "Pipfile.lock" PoetryLock = "poetry.lock" + UvLock = "uv.lock" GemfileLock = "Gemfile.lock" diff --git a/pkg/fanal/types/image.go b/pkg/fanal/types/image.go index 91cdfb44b60c..12c45de3abd4 100644 --- a/pkg/fanal/types/image.go +++ b/pkg/fanal/types/image.go @@ -53,6 +53,7 @@ type ImageOptions struct { PodmanOptions PodmanOptions ContainerdOptions ContainerdOptions ImageSources ImageSources + MaxImageSize int64 } type DockerOptions struct { @@ -81,6 +82,9 @@ type RegistryOptions struct { // RegistryToken is a bearer token to be sent to a registry RegistryToken string + // RegistryMirrors is a map of hosts with mirrors for them + RegistryMirrors map[string][]string + // SSL/TLS Insecure bool diff --git a/pkg/fanal/utils/utils.go b/pkg/fanal/utils/utils.go index 463c8dd1f255..5f96990cd703 100644 --- a/pkg/fanal/utils/utils.go +++ b/pkg/fanal/utils/utils.go @@ -32,15 +32,6 @@ func CacheDir() string { return cacheDir } -func StringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - func IsCommandAvailable(name string) bool { if _, err := exec.LookPath(name); err != nil { return false @@ -56,14 +47,6 @@ func IsGzip(f *bufio.Reader) bool { return buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x8 } -func Keys(m map[string]struct{}) []string { - var keys []string - for k := range m { - keys = append(keys, k) - } - return keys -} - func IsExecutable(fileInfo os.FileInfo) bool { // For Windows if filepath.Ext(fileInfo.Name()) == ".exe" { diff --git a/pkg/fanal/walker/tar_test.go b/pkg/fanal/walker/tar_test.go index 4cbdb782fb48..f00ca1e7e3bc 100644 --- a/pkg/fanal/walker/tar_test.go +++ b/pkg/fanal/walker/tar_test.go @@ -80,8 +80,7 @@ func TestLayerTar_Walk(t *testing.T) { w := walker.NewLayerTar(tt.option) gotOpqDirs, gotWhFiles, err := w.Walk(f, tt.analyzeFn) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/flag/db_flags.go b/pkg/flag/db_flags.go index cea4b82eaec6..c6887c98292e 100644 --- a/pkg/flag/db_flags.go +++ b/pkg/flag/db_flags.go @@ -1,7 +1,7 @@ package flag import ( - "fmt" + "strconv" "github.com/google/go-containerregistry/pkg/name" "golang.org/x/xerrors" @@ -188,7 +188,7 @@ func parseRepository(repo string, dbSchemaVersion int) (name.Reference, error) { return dbRepository, nil } - dbRepository = t.Tag(fmt.Sprint(dbSchemaVersion)) + dbRepository = t.Tag(strconv.Itoa(dbSchemaVersion)) log.Info("Adding schema version to the DB repository for backward compatibility", log.String("repository", dbRepository.String())) diff --git a/pkg/flag/image_flags.go b/pkg/flag/image_flags.go index aaa3fc65b930..587448f8d0d9 100644 --- a/pkg/flag/image_flags.go +++ b/pkg/flag/image_flags.go @@ -1,6 +1,7 @@ package flag import ( + "github.com/docker/go-units" v1 "github.com/google/go-containerregistry/pkg/v1" "golang.org/x/xerrors" @@ -58,6 +59,12 @@ var ( Values: xstrings.ToStringSlice(ftypes.AllImageSources), Usage: "image source(s) to use, in priority order", } + MaxImageSize = Flag[string]{ + Name: "max-image-size", + ConfigName: "image.max-size", + Default: "", + Usage: "[EXPERIMENTAL] maximum image size to process, specified in a human-readable format (e.g., '44kB', '17MB'); an error will be returned if the image exceeds this size", + } ) type ImageFlagGroup struct { @@ -68,6 +75,7 @@ type ImageFlagGroup struct { DockerHost *Flag[string] PodmanHost *Flag[string] ImageSources *Flag[[]string] + MaxImageSize *Flag[string] } type ImageOptions struct { @@ -78,6 +86,7 @@ type ImageOptions struct { DockerHost string PodmanHost string ImageSources ftypes.ImageSources + MaxImageSize int64 } func NewImageFlagGroup() *ImageFlagGroup { @@ -89,6 +98,7 @@ func NewImageFlagGroup() *ImageFlagGroup { DockerHost: DockerHostFlag.Clone(), PodmanHost: PodmanHostFlag.Clone(), ImageSources: SourceFlag.Clone(), + MaxImageSize: MaxImageSize.Clone(), } } @@ -105,6 +115,7 @@ func (f *ImageFlagGroup) Flags() []Flagger { f.DockerHost, f.PodmanHost, f.ImageSources, + f.MaxImageSize, } } @@ -124,6 +135,14 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) { } platform = ftypes.Platform{Platform: pl} } + var maxSize int64 + if value := f.MaxImageSize.Value(); value != "" { + parsedSize, err := units.FromHumanSize(value) + if err != nil { + return ImageOptions{}, xerrors.Errorf("invalid max image size %q: %w", value, err) + } + maxSize = parsedSize + } return ImageOptions{ Input: f.Input.Value(), @@ -133,5 +152,6 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) { DockerHost: f.DockerHost.Value(), PodmanHost: f.PodmanHost.Value(), ImageSources: xstrings.ToTSlice[ftypes.ImageSource](f.ImageSources.Value()), + MaxImageSize: maxSize, }, nil } diff --git a/pkg/flag/image_flags_test.go b/pkg/flag/image_flags_test.go new file mode 100644 index 000000000000..97105f6b8449 --- /dev/null +++ b/pkg/flag/image_flags_test.go @@ -0,0 +1,91 @@ +package flag_test + +import ( + "testing" + + "github.com/docker/go-units" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/flag" +) + +func TestImageFlagGroup_ToOptions(t *testing.T) { + type fields struct { + maxImgSize string + platform string + } + tests := []struct { + name string + fields fields + want flag.ImageOptions + wantErr string + }{ + { + name: "happy default (without flags)", + fields: fields{}, + want: flag.ImageOptions{}, + }, + { + name: "happy path with max image size", + fields: fields{ + maxImgSize: "10mb", + }, + want: flag.ImageOptions{ + MaxImageSize: units.MB * 10, + }, + }, + { + name: "invalid max image size", + fields: fields{ + maxImgSize: "10foo", + }, + wantErr: "invalid max image size", + }, + { + name: "happy path with platform", + fields: fields{ + platform: "linux/amd64", + }, + want: flag.ImageOptions{ + Platform: types.Platform{ + Platform: &v1.Platform{ + OS: "linux", + Architecture: "amd64", + }, + }, + }, + }, + { + name: "invalid platform", + fields: fields{ + platform: "unknown/unknown/unknown/unknown", + }, + wantErr: "unable to parse platform", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Cleanup(viper.Reset) + + setValue(flag.MaxImageSize.ConfigName, tt.fields.maxImgSize) + setValue(flag.PlatformFlag.ConfigName, tt.fields.platform) + + f := &flag.ImageFlagGroup{ + MaxImageSize: flag.MaxImageSize.Clone(), + Platform: flag.PlatformFlag.Clone(), + } + + got, err := f.ToOptions() + if tt.wantErr != "" { + assert.ErrorContains(t, err, tt.wantErr) + return + } + require.NoError(t, err) + assert.EqualExportedValues(t, tt.want, got) + }) + } +} diff --git a/pkg/flag/kubernetes_flags.go b/pkg/flag/kubernetes_flags.go index 6d0d64f4dc56..b8ec034d7169 100644 --- a/pkg/flag/kubernetes_flags.go +++ b/pkg/flag/kubernetes_flags.go @@ -1,6 +1,7 @@ package flag import ( + "errors" "fmt" "strconv" "strings" @@ -192,10 +193,10 @@ func (f *K8sFlagGroup) ToOptions() (K8sOptions, error) { exludeNodeLabels[excludeNodeParts[0]] = excludeNodeParts[1] } if len(f.ExcludeNamespaces.Value()) > 0 && len(f.IncludeNamespaces.Value()) > 0 { - return K8sOptions{}, fmt.Errorf("include-namespaces and exclude-namespaces flags cannot be used together") + return K8sOptions{}, errors.New("include-namespaces and exclude-namespaces flags cannot be used together") } if len(f.ExcludeKinds.Value()) > 0 && len(f.IncludeKinds.Value()) > 0 { - return K8sOptions{}, fmt.Errorf("include-kinds and exclude-kinds flags cannot be used together") + return K8sOptions{}, errors.New("include-kinds and exclude-kinds flags cannot be used together") } return K8sOptions{ @@ -222,12 +223,12 @@ func optionToTolerations(tolerationsOptions []string) ([]corev1.Toleration, erro for _, toleration := range tolerationsOptions { tolerationParts := strings.Split(toleration, ":") if len(tolerationParts) < 2 { - return []corev1.Toleration{}, fmt.Errorf("toleration must include key and effect") + return []corev1.Toleration{}, errors.New("toleration must include key and effect") } if corev1.TaintEffect(tolerationParts[1]) != corev1.TaintEffectNoSchedule && corev1.TaintEffect(tolerationParts[1]) != corev1.TaintEffectPreferNoSchedule && corev1.TaintEffect(tolerationParts[1]) != corev1.TaintEffectNoExecute { - return []corev1.Toleration{}, fmt.Errorf("toleration effect must be a valid value") + return []corev1.Toleration{}, errors.New("toleration effect must be a valid value") } keyValue := strings.Split(tolerationParts[0], "=") operator := corev1.TolerationOpEqual @@ -245,7 +246,7 @@ func optionToTolerations(tolerationsOptions []string) ([]corev1.Toleration, erro if len(tolerationParts) == 3 { tolerationSec, err = strconv.Atoi(tolerationParts[2]) if err != nil { - return nil, fmt.Errorf("TolerationSeconds must must be a number") + return nil, errors.New("TolerationSeconds must must be a number") } toleration.TolerationSeconds = lo.ToPtr(int64(tolerationSec)) } diff --git a/pkg/flag/options.go b/pkg/flag/options.go index e00aa4cfa922..775eec1366cd 100644 --- a/pkg/flag/options.go +++ b/pkg/flag/options.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "reflect" "slices" "strings" "sync" @@ -29,7 +30,7 @@ import ( ) type FlagType interface { - int | string | []string | bool | time.Duration | float64 + int | string | []string | bool | time.Duration | float64 | map[string][]string } type Flag[T FlagType] struct { @@ -160,6 +161,8 @@ func (f *Flag[T]) cast(val any) any { return cast.ToFloat64(val) case time.Duration: return cast.ToDuration(val) + case map[string][]string: + return cast.ToStringMapStringSlice(val) case []string: if s, ok := val.(string); ok && strings.Contains(s, ",") { // Split environmental variables by comma as it is not done by viper. @@ -448,14 +451,30 @@ func (o *Options) enableSBOM() { } } +// ScanOpts returns options for scanning +func (o *Options) ScanOpts() types.ScanOptions { + return types.ScanOptions{ + PkgTypes: o.PkgTypes, + PkgRelationships: o.PkgRelationships, + Scanners: o.Scanners, + ImageConfigScanners: o.ImageConfigScanners, // this is valid only for 'image' subcommand + ScanRemovedPackages: o.ScanRemovedPkgs, // this is valid only for 'image' subcommand + LicenseCategories: o.LicenseCategories, + FilePatterns: o.FilePatterns, + IncludeDevDeps: o.IncludeDevDeps, + Distro: o.Distro, + } +} + // RegistryOpts returns options for OCI registries func (o *Options) RegistryOpts() ftypes.RegistryOptions { return ftypes.RegistryOptions{ - Credentials: o.Credentials, - RegistryToken: o.RegistryToken, - Insecure: o.Insecure, - Platform: o.Platform, - AWSRegion: o.AWSOptions.Region, + Credentials: o.Credentials, + RegistryToken: o.RegistryToken, + Insecure: o.Insecure, + Platform: o.Platform, + AWSRegion: o.AWSOptions.Region, + RegistryMirrors: o.RegistryMirrors, } } @@ -856,3 +875,37 @@ func (a flagAliases) NormalizeFunc() func(*pflag.FlagSet, string) pflag.Normaliz return pflag.NormalizedName(name) } } + +func HiddenFlags() []string { + var allFlagGroups = []FlagGroup{ + NewGlobalFlagGroup(), + NewCacheFlagGroup(), + NewCleanFlagGroup(), + NewClientFlags(), + NewDBFlagGroup(), + NewImageFlagGroup(), + NewK8sFlagGroup(), + NewLicenseFlagGroup(), + NewMisconfFlagGroup(), + NewModuleFlagGroup(), + NewPackageFlagGroup(), + NewRegistryFlagGroup(), + NewRegoFlagGroup(), + NewReportFlagGroup(), + NewRepoFlagGroup(), + NewScanFlagGroup(), + NewSecretFlagGroup(), + NewServerFlags(), + NewVulnerabilityFlagGroup(), + } + + var hiddenFlags []string + for _, flagGroup := range allFlagGroups { + for _, flag := range flagGroup.Flags() { + if !reflect.ValueOf(flag).IsNil() && flag.Hidden() { + hiddenFlags = append(hiddenFlags, flag.GetConfigName()) + } + } + } + return hiddenFlags +} diff --git a/pkg/flag/registry_flags.go b/pkg/flag/registry_flags.go index 9c03a07b8872..50de707ea602 100644 --- a/pkg/flag/registry_flags.go +++ b/pkg/flag/registry_flags.go @@ -31,26 +31,33 @@ var ( ConfigName: "registry.token", Usage: "registry token", } + RegistryMirrorsFlag = Flag[map[string][]string]{ + ConfigName: "registry.mirrors", + Usage: "map of hosts and registries for them.", + } ) type RegistryFlagGroup struct { - Username *Flag[[]string] - Password *Flag[[]string] - PasswordStdin *Flag[bool] - RegistryToken *Flag[string] + Username *Flag[[]string] + Password *Flag[[]string] + PasswordStdin *Flag[bool] + RegistryToken *Flag[string] + RegistryMirrors *Flag[map[string][]string] } type RegistryOptions struct { - Credentials []types.Credential - RegistryToken string + Credentials []types.Credential + RegistryToken string + RegistryMirrors map[string][]string } func NewRegistryFlagGroup() *RegistryFlagGroup { return &RegistryFlagGroup{ - Username: UsernameFlag.Clone(), - Password: PasswordFlag.Clone(), - PasswordStdin: PasswordStdinFlag.Clone(), - RegistryToken: RegistryTokenFlag.Clone(), + Username: UsernameFlag.Clone(), + Password: PasswordFlag.Clone(), + PasswordStdin: PasswordStdinFlag.Clone(), + RegistryToken: RegistryTokenFlag.Clone(), + RegistryMirrors: RegistryMirrorsFlag.Clone(), } } @@ -64,6 +71,7 @@ func (f *RegistryFlagGroup) Flags() []Flagger { f.Password, f.PasswordStdin, f.RegistryToken, + f.RegistryMirrors, } } @@ -97,7 +105,8 @@ func (f *RegistryFlagGroup) ToOptions() (RegistryOptions, error) { } return RegistryOptions{ - Credentials: credentials, - RegistryToken: f.RegistryToken.Value(), + Credentials: credentials, + RegistryToken: f.RegistryToken.Value(), + RegistryMirrors: f.RegistryMirrors.Value(), }, nil } diff --git a/pkg/flag/scan_flags.go b/pkg/flag/scan_flags.go index 544d56691883..15a1e04ce139 100644 --- a/pkg/flag/scan_flags.go +++ b/pkg/flag/scan_flags.go @@ -2,8 +2,11 @@ package flag import ( "runtime" + "slices" + "strings" "github.com/samber/lo" + "golang.org/x/xerrors" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" @@ -110,6 +113,11 @@ var ( - "comprehensive": Aims to detect more security findings at the cost of potential false positives. `, } + DistroFlag = Flag[string]{ + Name: "distro", + ConfigName: "scan.distro", + Usage: "[EXPERIMENTAL] specify a distribution, /", + } ) type ScanFlagGroup struct { @@ -123,6 +131,7 @@ type ScanFlagGroup struct { SBOMSources *Flag[[]string] RekorURL *Flag[string] DetectionPriority *Flag[string] + DistroFlag *Flag[string] } type ScanOptions struct { @@ -136,6 +145,7 @@ type ScanOptions struct { SBOMSources []string RekorURL string DetectionPriority ftypes.DetectionPriority + Distro ftypes.OS } func NewScanFlagGroup() *ScanFlagGroup { @@ -150,6 +160,7 @@ func NewScanFlagGroup() *ScanFlagGroup { RekorURL: RekorURLFlag.Clone(), Slow: SlowFlag.Clone(), DetectionPriority: DetectionPriority.Clone(), + DistroFlag: DistroFlag.Clone(), } } @@ -169,6 +180,7 @@ func (f *ScanFlagGroup) Flags() []Flagger { f.SBOMSources, f.RekorURL, f.DetectionPriority, + f.DistroFlag, } } @@ -188,6 +200,18 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) { parallel = runtime.NumCPU() } + var distro ftypes.OS + if f.DistroFlag != nil && f.DistroFlag.Value() != "" { + family, version, _ := strings.Cut(f.DistroFlag.Value(), "/") + if !slices.Contains(ftypes.OSTypes, ftypes.OSType(family)) { + return ScanOptions{}, xerrors.Errorf("unknown OS family: %s, must be %q", family, ftypes.OSTypes) + } + distro = ftypes.OS{ + Family: ftypes.OSType(family), + Name: version, + } + } + return ScanOptions{ Target: target, SkipDirs: f.SkipDirs.Value(), @@ -199,5 +223,6 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) { SBOMSources: f.SBOMSources.Value(), RekorURL: f.RekorURL.Value(), DetectionPriority: ftypes.DetectionPriority(f.DetectionPriority.Value()), + Distro: distro, }, nil } diff --git a/pkg/flag/scan_flags_test.go b/pkg/flag/scan_flags_test.go index d3ad792ae948..e0f8ffb9deb6 100644 --- a/pkg/flag/scan_flags_test.go +++ b/pkg/flag/scan_flags_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/flag" "github.com/aquasecurity/trivy/pkg/types" ) @@ -17,6 +18,7 @@ func TestScanFlagGroup_ToOptions(t *testing.T) { skipFiles []string offlineScan bool scanners string + distro string } tests := []struct { name string @@ -105,6 +107,26 @@ func TestScanFlagGroup_ToOptions(t *testing.T) { }, assertion: require.NoError, }, + { + name: "happy path `distro` flag", + fields: fields{ + distro: "alpine/3.20", + }, + want: flag.ScanOptions{ + Distro: ftypes.OS{ + Family: "alpine", + Name: "3.20", + }, + }, + assertion: require.NoError, + }, + { + name: "sad distro flag", + fields: fields{ + distro: "sad", + }, + assertion: require.Error, + }, } for _, tt := range tests { @@ -114,6 +136,7 @@ func TestScanFlagGroup_ToOptions(t *testing.T) { setSliceValue(flag.SkipFilesFlag.ConfigName, tt.fields.skipFiles) setValue(flag.OfflineScanFlag.ConfigName, tt.fields.offlineScan) setValue(flag.ScannersFlag.ConfigName, tt.fields.scanners) + setValue(flag.DistroFlag.ConfigName, tt.fields.distro) // Assert options f := &flag.ScanFlagGroup{ @@ -121,6 +144,7 @@ func TestScanFlagGroup_ToOptions(t *testing.T) { SkipFiles: flag.SkipFilesFlag.Clone(), OfflineScan: flag.OfflineScanFlag.Clone(), Scanners: flag.ScannersFlag.Clone(), + DistroFlag: flag.DistroFlag.Clone(), } got, err := f.ToOptions(tt.args) diff --git a/pkg/iac/adapters/cloudformation/aws/ecr/ecr_test.go b/pkg/iac/adapters/cloudformation/aws/ecr/ecr_test.go index 6bcd0a4952dd..bf411dddbf8a 100644 --- a/pkg/iac/adapters/cloudformation/aws/ecr/ecr_test.go +++ b/pkg/iac/adapters/cloudformation/aws/ecr/ecr_test.go @@ -3,8 +3,7 @@ package ecr import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/adapters/cloudformation/testutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/adapters/cloudformation/aws/ecr/repository.go b/pkg/iac/adapters/cloudformation/aws/ecr/repository.go index 2c08d57a29c6..e0491c121b4d 100644 --- a/pkg/iac/adapters/cloudformation/aws/ecr/repository.go +++ b/pkg/iac/adapters/cloudformation/aws/ecr/repository.go @@ -1,10 +1,9 @@ package ecr import ( - "fmt" - - "github.com/liamg/iamgo" + "errors" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" @@ -60,7 +59,7 @@ func getRepositories(ctx parser.FileContext) (repositories []ecr.Repository) { func getPolicy(r *parser.Resource) (*iam.Policy, error) { policyProp := r.GetProperty("RepositoryPolicyText") if policyProp.IsNil() { - return nil, fmt.Errorf("missing policy") + return nil, errors.New("missing policy") } parsed, err := iamgo.Parse(policyProp.GetJsonBytes()) diff --git a/pkg/iac/adapters/cloudformation/aws/iam/iam_test.go b/pkg/iac/adapters/cloudformation/aws/iam/iam_test.go index 1ea6a099a698..7f68e2c6aef0 100644 --- a/pkg/iac/adapters/cloudformation/aws/iam/iam_test.go +++ b/pkg/iac/adapters/cloudformation/aws/iam/iam_test.go @@ -3,8 +3,7 @@ package iam import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/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/types" diff --git a/pkg/iac/adapters/cloudformation/aws/iam/policy.go b/pkg/iac/adapters/cloudformation/aws/iam/policy.go index f83771f882d2..d787dac2539b 100644 --- a/pkg/iac/adapters/cloudformation/aws/iam/policy.go +++ b/pkg/iac/adapters/cloudformation/aws/iam/policy.go @@ -1,8 +1,7 @@ package iam import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" diff --git a/pkg/iac/adapters/cloudformation/aws/s3/bucket.go b/pkg/iac/adapters/cloudformation/aws/s3/bucket.go index ec56894dbee4..957278a93a29 100644 --- a/pkg/iac/adapters/cloudformation/aws/s3/bucket.go +++ b/pkg/iac/adapters/cloudformation/aws/s3/bucket.go @@ -7,8 +7,8 @@ import ( "strings" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" - "github.com/liamg/iamgo" + "github.com/aquasecurity/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" diff --git a/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go b/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go index 707aae028f7f..87ca88a97432 100644 --- a/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go +++ b/pkg/iac/adapters/cloudformation/aws/s3/s3_test.go @@ -3,8 +3,7 @@ package s3 import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/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" diff --git a/pkg/iac/adapters/cloudformation/aws/sam/function.go b/pkg/iac/adapters/cloudformation/aws/sam/function.go index 161b078bf681..2bfc488e1a18 100644 --- a/pkg/iac/adapters/cloudformation/aws/sam/function.go +++ b/pkg/iac/adapters/cloudformation/aws/sam/function.go @@ -1,8 +1,7 @@ package sam import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/sam" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" diff --git a/pkg/iac/adapters/cloudformation/aws/sam/sam_test.go b/pkg/iac/adapters/cloudformation/aws/sam/sam_test.go index 1d9586775044..9bd8ab6bd641 100644 --- a/pkg/iac/adapters/cloudformation/aws/sam/sam_test.go +++ b/pkg/iac/adapters/cloudformation/aws/sam/sam_test.go @@ -3,8 +3,7 @@ package sam import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/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/sam" diff --git a/pkg/iac/adapters/cloudformation/aws/sam/state_machines.go b/pkg/iac/adapters/cloudformation/aws/sam/state_machines.go index 2a57afd2bdb6..5b1be5618ec4 100644 --- a/pkg/iac/adapters/cloudformation/aws/sam/state_machines.go +++ b/pkg/iac/adapters/cloudformation/aws/sam/state_machines.go @@ -1,8 +1,7 @@ package sam import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/sam" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" diff --git a/pkg/iac/adapters/cloudformation/aws/sqs/queue.go b/pkg/iac/adapters/cloudformation/aws/sqs/queue.go index 555fd54efd90..a260fa00e08c 100644 --- a/pkg/iac/adapters/cloudformation/aws/sqs/queue.go +++ b/pkg/iac/adapters/cloudformation/aws/sqs/queue.go @@ -1,10 +1,9 @@ package sqs import ( - "fmt" - - "github.com/liamg/iamgo" + "errors" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/sqs" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" @@ -59,5 +58,5 @@ func getPolicy(id string, ctx parser.FileContext) (*iam.Policy, error) { } } } - return nil, fmt.Errorf("no matching policy found") + return nil, errors.New("no matching policy found") } diff --git a/pkg/iac/adapters/cloudformation/aws/sqs/sqs_test.go b/pkg/iac/adapters/cloudformation/aws/sqs/sqs_test.go index 5e7fe278fcad..634eddea9ab4 100644 --- a/pkg/iac/adapters/cloudformation/aws/sqs/sqs_test.go +++ b/pkg/iac/adapters/cloudformation/aws/sqs/sqs_test.go @@ -3,8 +3,7 @@ package sqs import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/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/sqs" diff --git a/pkg/iac/adapters/terraform/aws/ecr/adapt.go b/pkg/iac/adapters/terraform/aws/ecr/adapt.go index 57d5686dc7f7..90a66ba098e1 100644 --- a/pkg/iac/adapters/terraform/aws/ecr/adapt.go +++ b/pkg/iac/adapters/terraform/aws/ecr/adapt.go @@ -1,8 +1,7 @@ package ecr import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr" iamp "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/adapters/terraform/aws/ecr/adapt_test.go b/pkg/iac/adapters/terraform/aws/ecr/adapt_test.go index f2fb4d3dc9c9..71904d8932e4 100644 --- a/pkg/iac/adapters/terraform/aws/ecr/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/ecr/adapt_test.go @@ -3,10 +3,10 @@ package ecr import ( "testing" - "github.com/liamg/iamgo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/tftestutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr" diff --git a/pkg/iac/adapters/terraform/aws/iam/convert.go b/pkg/iac/adapters/terraform/aws/iam/convert.go index 3a61791e5fb9..dcc61cd6bc97 100644 --- a/pkg/iac/adapters/terraform/aws/iam/convert.go +++ b/pkg/iac/adapters/terraform/aws/iam/convert.go @@ -3,8 +3,7 @@ package iam import ( "strings" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/terraform" diff --git a/pkg/iac/adapters/terraform/aws/iam/policies.go b/pkg/iac/adapters/terraform/aws/iam/policies.go index 94b132eddf90..7b662d3e5d30 100644 --- a/pkg/iac/adapters/terraform/aws/iam/policies.go +++ b/pkg/iac/adapters/terraform/aws/iam/policies.go @@ -1,8 +1,7 @@ package iam import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/terraform" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" diff --git a/pkg/iac/adapters/terraform/aws/iam/policies_test.go b/pkg/iac/adapters/terraform/aws/iam/policies_test.go index a1e989c06979..94cc412fc5c5 100644 --- a/pkg/iac/adapters/terraform/aws/iam/policies_test.go +++ b/pkg/iac/adapters/terraform/aws/iam/policies_test.go @@ -3,8 +3,7 @@ package iam import ( "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/tftestutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/adapters/terraform/aws/iam/roles_test.go b/pkg/iac/adapters/terraform/aws/iam/roles_test.go index 93bc5a9e8168..803faf6bfb3a 100644 --- a/pkg/iac/adapters/terraform/aws/iam/roles_test.go +++ b/pkg/iac/adapters/terraform/aws/iam/roles_test.go @@ -4,8 +4,7 @@ import ( "sort" "testing" - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/tftestutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/adapters/terraform/aws/s3/adapt_test.go b/pkg/iac/adapters/terraform/aws/s3/adapt_test.go index ea12206f312b..b64b1e8d43a4 100644 --- a/pkg/iac/adapters/terraform/aws/s3/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/s3/adapt_test.go @@ -3,10 +3,10 @@ package s3 import ( "testing" - "github.com/liamg/iamgo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/tftestutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/adapters/terraform/aws/sqs/adapt.go b/pkg/iac/adapters/terraform/aws/sqs/adapt.go index 432bda06eda2..1e40138b47bc 100644 --- a/pkg/iac/adapters/terraform/aws/sqs/adapt.go +++ b/pkg/iac/adapters/terraform/aws/sqs/adapt.go @@ -2,8 +2,8 @@ package sqs import ( "github.com/google/uuid" - "github.com/liamg/iamgo" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/aws/iam" iamp "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/sqs" diff --git a/pkg/iac/adapters/terraform/aws/sqs/adapt_test.go b/pkg/iac/adapters/terraform/aws/sqs/adapt_test.go index 0a4726140456..c9e08a1df887 100644 --- a/pkg/iac/adapters/terraform/aws/sqs/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/sqs/adapt_test.go @@ -3,10 +3,10 @@ package sqs import ( "testing" - "github.com/liamg/iamgo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/iamgo" "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform/tftestutil" "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam" diff --git a/pkg/iac/providers/aws/iam/actions.go b/pkg/iac/providers/aws/iam/actions.go deleted file mode 100644 index a58ad07f2097..000000000000 --- a/pkg/iac/providers/aws/iam/actions.go +++ /dev/null @@ -1,5180 +0,0 @@ -// Code generated by mage genallowedactions DO NOT EDIT. - -package iam - -var allowedActionsForResourceWildcardsMap = map[string]struct{}{ - "a2c:GetContainerizationJobDetails": {}, - "a2c:GetDeploymentJobDetails": {}, - "a2c:StartContainerizationJob": {}, - "a2c:StartDeploymentJob": {}, - "a4b:ApproveSkill": {}, - "a4b:AssociateSkillWithUsers": {}, - "a4b:CompleteRegistration": {}, - "a4b:CreateAddressBook": {}, - "a4b:CreateBusinessReportSchedule": {}, - "a4b:CreateConferenceProvider": {}, - "a4b:CreateContact": {}, - "a4b:CreateGatewayGroup": {}, - "a4b:CreateNetworkProfile": {}, - "a4b:CreateProfile": {}, - "a4b:CreateSkillGroup": {}, - "a4b:GetConferencePreference": {}, - "a4b:GetInvitationConfiguration": {}, - "a4b:ListBusinessReportSchedules": {}, - "a4b:ListConferenceProviders": {}, - "a4b:ListGatewayGroups": {}, - "a4b:ListSkills": {}, - "a4b:ListSkillsStoreCategories": {}, - "a4b:ListSkillsStoreSkillsByCategory": {}, - "a4b:PutConferencePreference": {}, - "a4b:PutDeviceSetupEvents": {}, - "a4b:PutInvitationConfiguration": {}, - "a4b:RegisterAVSDevice": {}, - "a4b:RegisterDevice": {}, - "a4b:RejectSkill": {}, - "a4b:ResolveRoom": {}, - "a4b:SearchAddressBooks": {}, - "a4b:SearchContacts": {}, - "a4b:SearchDevices": {}, - "a4b:SearchNetworkProfiles": {}, - "a4b:SearchProfiles": {}, - "a4b:SearchRooms": {}, - "a4b:SearchSkillGroups": {}, - "a4b:SearchUsers": {}, - "a4b:SendAnnouncement": {}, - "a4b:StartDeviceSync": {}, - "access-analyzer:CancelPolicyGeneration": {}, - "access-analyzer:CheckAccessNotGranted": {}, - "access-analyzer:CheckNoNewAccess": {}, - "access-analyzer:GetGeneratedPolicy": {}, - "access-analyzer:ListAnalyzers": {}, - "access-analyzer:ListPolicyGenerations": {}, - "access-analyzer:StartPolicyGeneration": {}, - "access-analyzer:ValidatePolicy": {}, - "acm-pca:CreateCertificateAuthority": {}, - "acm-pca:ListCertificateAuthorities": {}, - "acm:GetAccountConfiguration": {}, - "acm:ListCertificates": {}, - "acm:PutAccountConfiguration": {}, - "acm:RequestCertificate": {}, - "activate:CreateForm": {}, - "activate:GetAccountContact": {}, - "activate:GetContentInfo": {}, - "activate:GetCosts": {}, - "activate:GetCredits": {}, - "activate:GetMemberInfo": {}, - "activate:GetProgram": {}, - "activate:PutMemberInfo": {}, - "airflow:ListEnvironments": {}, - "amplify:ListApps": {}, - "amplifybackend:ListS3Buckets": {}, - "amplifyuibuilder:CreateComponent": {}, - "amplifyuibuilder:CreateForm": {}, - "amplifyuibuilder:CreateTheme": {}, - "amplifyuibuilder:ExchangeCodeForToken": {}, - "amplifyuibuilder:ExportComponents": {}, - "amplifyuibuilder:ExportForms": {}, - "amplifyuibuilder:ExportThemes": {}, - "amplifyuibuilder:GetMetadata": {}, - "amplifyuibuilder:ListCodegenJobs": {}, - "amplifyuibuilder:ListComponents": {}, - "amplifyuibuilder:ListForms": {}, - "amplifyuibuilder:ListThemes": {}, - "amplifyuibuilder:PutMetadataFlag": {}, - "amplifyuibuilder:RefreshToken": {}, - "amplifyuibuilder:ResetMetadataFlag": {}, - "amplifyuibuilder:StartCodegenJob": {}, - "aoss:BatchGetCollection": {}, - "aoss:BatchGetEffectiveLifecyclePolicy": {}, - "aoss:BatchGetLifecyclePolicy": {}, - "aoss:BatchGetVpcEndpoint": {}, - "aoss:CreateAccessPolicy": {}, - "aoss:CreateCollection": {}, - "aoss:CreateLifecyclePolicy": {}, - "aoss:CreateSecurityConfig": {}, - "aoss:CreateSecurityPolicy": {}, - "aoss:CreateVpcEndpoint": {}, - "aoss:DeleteAccessPolicy": {}, - "aoss:DeleteLifecyclePolicy": {}, - "aoss:DeleteSecurityConfig": {}, - "aoss:DeleteSecurityPolicy": {}, - "aoss:DeleteVpcEndpoint": {}, - "aoss:GetAccessPolicy": {}, - "aoss:GetAccountSettings": {}, - "aoss:GetPoliciesStats": {}, - "aoss:GetSecurityConfig": {}, - "aoss:GetSecurityPolicy": {}, - "aoss:ListAccessPolicies": {}, - "aoss:ListCollections": {}, - "aoss:ListLifecyclePolicies": {}, - "aoss:ListSecurityConfigs": {}, - "aoss:ListSecurityPolicies": {}, - "aoss:ListTagsForResource": {}, - "aoss:ListVpcEndpoints": {}, - "aoss:TagResource": {}, - "aoss:UntagResource": {}, - "aoss:UpdateAccessPolicy": {}, - "aoss:UpdateAccountSettings": {}, - "aoss:UpdateLifecyclePolicy": {}, - "aoss:UpdateSecurityConfig": {}, - "aoss:UpdateSecurityPolicy": {}, - "aoss:UpdateVpcEndpoint": {}, - "app-integrations:ListApplicationAssociations": {}, - "app-integrations:ListApplications": {}, - "app-integrations:ListDataIntegrationAssociations": {}, - "app-integrations:ListDataIntegrations": {}, - "app-integrations:ListEventIntegrationAssociations": {}, - "app-integrations:ListEventIntegrations": {}, - "appconfig:CreateApplication": {}, - "appconfig:CreateDeploymentStrategy": {}, - "appconfig:CreateExtension": {}, - "appconfig:CreateExtensionAssociation": {}, - "appconfig:ListApplications": {}, - "appconfig:ListDeploymentStrategies": {}, - "appconfig:ListExtensionAssociations": {}, - "appconfig:ListExtensions": {}, - "appfabric:ListAppBundles": {}, - "appflow:CreateConnectorProfile": {}, - "appflow:CreateFlow": {}, - "appflow:DescribeConnectorProfiles": {}, - "appflow:DescribeConnectors": {}, - "appflow:DescribeFlows": {}, - "appflow:RegisterConnector": {}, - "application-autoscaling:DescribeScalableTargets": {}, - "application-autoscaling:DescribeScalingActivities": {}, - "application-autoscaling:DescribeScalingPolicies": {}, - "application-autoscaling:DescribeScheduledActions": {}, - "application-cost-profiler:DeleteReportDefinition": {}, - "application-cost-profiler:GetReportDefinition": {}, - "application-cost-profiler:ImportApplicationUsage": {}, - "application-cost-profiler:ListReportDefinitions": {}, - "application-cost-profiler:PutReportDefinition": {}, - "application-cost-profiler:UpdateReportDefinition": {}, - "application-transformation:GetContainerization": {}, - "application-transformation:GetDeployment": {}, - "application-transformation:GetGroupingAssessment": {}, - "application-transformation:GetPortingCompatibilityAssessment": {}, - "application-transformation:GetPortingRecommendationAssessment": {}, - "application-transformation:GetRuntimeAssessment": {}, - "application-transformation:PutLogData": {}, - "application-transformation:PutMetricData": {}, - "application-transformation:StartContainerization": {}, - "application-transformation:StartDeployment": {}, - "application-transformation:StartGroupingAssessment": {}, - "application-transformation:StartPortingCompatibilityAssessment": {}, - "application-transformation:StartPortingRecommendationAssessment": {}, - "application-transformation:StartRuntimeAssessment": {}, - "applicationinsights:AddWorkload": {}, - "applicationinsights:CreateApplication": {}, - "applicationinsights:CreateComponent": {}, - "applicationinsights:CreateLogPattern": {}, - "applicationinsights:DeleteApplication": {}, - "applicationinsights:DeleteComponent": {}, - "applicationinsights:DeleteLogPattern": {}, - "applicationinsights:DescribeApplication": {}, - "applicationinsights:DescribeComponent": {}, - "applicationinsights:DescribeComponentConfiguration": {}, - "applicationinsights:DescribeComponentConfigurationRecommendation": {}, - "applicationinsights:DescribeLogPattern": {}, - "applicationinsights:DescribeObservation": {}, - "applicationinsights:DescribeProblem": {}, - "applicationinsights:DescribeProblemObservations": {}, - "applicationinsights:DescribeWorkload": {}, - "applicationinsights:Link": {}, - "applicationinsights:ListApplications": {}, - "applicationinsights:ListComponents": {}, - "applicationinsights:ListConfigurationHistory": {}, - "applicationinsights:ListLogPatternSets": {}, - "applicationinsights:ListLogPatterns": {}, - "applicationinsights:ListProblems": {}, - "applicationinsights:ListTagsForResource": {}, - "applicationinsights:ListWorkloads": {}, - "applicationinsights:RemoveWorkload": {}, - "applicationinsights:TagResource": {}, - "applicationinsights:UntagResource": {}, - "applicationinsights:UpdateApplication": {}, - "applicationinsights:UpdateComponent": {}, - "applicationinsights:UpdateComponentConfiguration": {}, - "applicationinsights:UpdateLogPattern": {}, - "applicationinsights:UpdateProblem": {}, - "applicationinsights:UpdateWorkload": {}, - "appmesh-preview:ListMeshes": {}, - "appmesh:ListMeshes": {}, - "apprunner:ListAutoScalingConfigurations": {}, - "apprunner:ListConnections": {}, - "apprunner:ListObservabilityConfigurations": {}, - "apprunner:ListServices": {}, - "apprunner:ListVpcConnectors": {}, - "apprunner:ListVpcIngressConnections": {}, - "appstream:CreateAppBlock": {}, - "appstream:CreateDirectoryConfig": {}, - "appstream:CreateUsageReportSubscription": {}, - "appstream:CreateUser": {}, - "appstream:DeleteDirectoryConfig": {}, - "appstream:DeleteUsageReportSubscription": {}, - "appstream:DeleteUser": {}, - "appstream:DescribeDirectoryConfigs": {}, - "appstream:DescribeUsageReportSubscriptions": {}, - "appstream:DescribeUsers": {}, - "appstream:DisableUser": {}, - "appstream:EnableUser": {}, - "appstream:ExpireSession": {}, - "appstream:ListTagsForResource": {}, - "appstream:UpdateDirectoryConfig": {}, - "appsync:CreateApiCache": {}, - "appsync:CreateApiKey": {}, - "appsync:CreateDataSource": {}, - "appsync:CreateDomainName": {}, - "appsync:CreateFunction": {}, - "appsync:CreateGraphqlApi": {}, - "appsync:CreateResolver": {}, - "appsync:CreateType": {}, - "appsync:DeleteApiCache": {}, - "appsync:DeleteApiKey": {}, - "appsync:DeleteDataSource": {}, - "appsync:DeleteFunction": {}, - "appsync:DeleteResolver": {}, - "appsync:DeleteResourcePolicy": {}, - "appsync:DeleteType": {}, - "appsync:EvaluateCode": {}, - "appsync:EvaluateMappingTemplate": {}, - "appsync:FlushApiCache": {}, - "appsync:GetApiCache": {}, - "appsync:GetDataSource": {}, - "appsync:GetDataSourceIntrospection": {}, - "appsync:GetFunction": {}, - "appsync:GetGraphqlApiEnvironmentVariables": {}, - "appsync:GetIntrospectionSchema": {}, - "appsync:GetResolver": {}, - "appsync:GetResourcePolicy": {}, - "appsync:GetSchemaCreationStatus": {}, - "appsync:GetType": {}, - "appsync:ListApiKeys": {}, - "appsync:ListDataSources": {}, - "appsync:ListDomainNames": {}, - "appsync:ListFunctions": {}, - "appsync:ListGraphqlApis": {}, - "appsync:ListResolvers": {}, - "appsync:ListResolversByFunction": {}, - "appsync:ListSourceApiAssociations": {}, - "appsync:ListTypes": {}, - "appsync:ListTypesByAssociation": {}, - "appsync:PutGraphqlApiEnvironmentVariables": {}, - "appsync:PutResourcePolicy": {}, - "appsync:SetWebACL": {}, - "appsync:StartDataSourceIntrospection": {}, - "appsync:StartSchemaCreation": {}, - "appsync:UpdateApiCache": {}, - "appsync:UpdateApiKey": {}, - "appsync:UpdateDataSource": {}, - "appsync:UpdateFunction": {}, - "appsync:UpdateResolver": {}, - "appsync:UpdateType": {}, - "aps:CreateWorkspace": {}, - "aps:GetDefaultScraperConfiguration": {}, - "aps:ListScrapers": {}, - "aps:ListWorkspaces": {}, - "arc-zonal-shift:ListAutoshifts": {}, - "arc-zonal-shift:ListManagedResources": {}, - "arc-zonal-shift:ListZonalShifts": {}, - "arsenal:RegisterOnPremisesAgent": {}, - "artifact:GetAccountSettings": {}, - "artifact:ListReports": {}, - "artifact:PutAccountSettings": {}, - "athena:GetCatalogs": {}, - "athena:GetExecutionEngine": {}, - "athena:GetExecutionEngines": {}, - "athena:GetNamespace": {}, - "athena:GetNamespaces": {}, - "athena:GetQueryExecutions": {}, - "athena:GetTable": {}, - "athena:GetTables": {}, - "athena:ListApplicationDPUSizes": {}, - "athena:ListCapacityReservations": {}, - "athena:ListDataCatalogs": {}, - "athena:ListEngineVersions": {}, - "athena:ListExecutors": {}, - "athena:ListWorkGroups": {}, - "athena:RunQuery": {}, - "auditmanager:CreateAssessment": {}, - "auditmanager:CreateAssessmentFramework": {}, - "auditmanager:CreateControl": {}, - "auditmanager:DeleteAssessmentFrameworkShare": {}, - "auditmanager:DeregisterAccount": {}, - "auditmanager:DeregisterOrganizationAdminAccount": {}, - "auditmanager:GetAccountStatus": {}, - "auditmanager:GetDelegations": {}, - "auditmanager:GetEvidenceFileUploadUrl": {}, - "auditmanager:GetInsights": {}, - "auditmanager:GetInsightsByAssessment": {}, - "auditmanager:GetOrganizationAdminAccount": {}, - "auditmanager:GetServicesInScope": {}, - "auditmanager:GetSettings": {}, - "auditmanager:ListAssessmentControlInsightsByControlDomain": {}, - "auditmanager:ListAssessmentFrameworkShareRequests": {}, - "auditmanager:ListAssessmentFrameworks": {}, - "auditmanager:ListAssessmentReports": {}, - "auditmanager:ListAssessments": {}, - "auditmanager:ListControlDomainInsights": {}, - "auditmanager:ListControlDomainInsightsByAssessment": {}, - "auditmanager:ListControlInsightsByControlDomain": {}, - "auditmanager:ListControls": {}, - "auditmanager:ListKeywordsForDataSource": {}, - "auditmanager:ListNotifications": {}, - "auditmanager:RegisterAccount": {}, - "auditmanager:RegisterOrganizationAdminAccount": {}, - "auditmanager:UpdateAssessmentFrameworkShare": {}, - "auditmanager:UpdateSettings": {}, - "auditmanager:ValidateAssessmentReportIntegrity": {}, - "autoscaling-plans:CreateScalingPlan": {}, - "autoscaling-plans:DeleteScalingPlan": {}, - "autoscaling-plans:DescribeScalingPlanResources": {}, - "autoscaling-plans:DescribeScalingPlans": {}, - "autoscaling-plans:GetScalingPlanResourceForecastData": {}, - "autoscaling-plans:UpdateScalingPlan": {}, - "autoscaling:DescribeAccountLimits": {}, - "autoscaling:DescribeAdjustmentTypes": {}, - "autoscaling:DescribeAutoScalingGroups": {}, - "autoscaling:DescribeAutoScalingInstances": {}, - "autoscaling:DescribeAutoScalingNotificationTypes": {}, - "autoscaling:DescribeInstanceRefreshes": {}, - "autoscaling:DescribeLaunchConfigurations": {}, - "autoscaling:DescribeLifecycleHookTypes": {}, - "autoscaling:DescribeLifecycleHooks": {}, - "autoscaling:DescribeLoadBalancerTargetGroups": {}, - "autoscaling:DescribeLoadBalancers": {}, - "autoscaling:DescribeMetricCollectionTypes": {}, - "autoscaling:DescribeNotificationConfigurations": {}, - "autoscaling:DescribePolicies": {}, - "autoscaling:DescribeScalingActivities": {}, - "autoscaling:DescribeScalingProcessTypes": {}, - "autoscaling:DescribeScheduledActions": {}, - "autoscaling:DescribeTags": {}, - "autoscaling:DescribeTerminationPolicyTypes": {}, - "autoscaling:DescribeTrafficSources": {}, - "autoscaling:DescribeWarmPool": {}, - "autoscaling:GetPredictiveScalingForecast": {}, - "aws-marketplace-management:GetAdditionalSellerNotificationRecipients": {}, - "aws-marketplace-management:GetBankAccountVerificationDetails": {}, - "aws-marketplace-management:GetSecondaryUserVerificationDetails": {}, - "aws-marketplace-management:GetSellerVerificationDetails": {}, - "aws-marketplace-management:PutAdditionalSellerNotificationRecipients": {}, - "aws-marketplace-management:PutBankAccountVerificationDetails": {}, - "aws-marketplace-management:PutSecondaryUserVerificationDetails": {}, - "aws-marketplace-management:PutSellerVerificationDetails": {}, - "aws-marketplace-management:uploadFiles": {}, - "aws-marketplace-management:viewMarketing": {}, - "aws-marketplace-management:viewReports": {}, - "aws-marketplace-management:viewSettings": {}, - "aws-marketplace-management:viewSupport": {}, - "aws-marketplace:AcceptAgreementApprovalRequest": {}, - "aws-marketplace:AcceptAgreementRequest": {}, - "aws-marketplace:AssociateProductsWithPrivateMarketplace": {}, - "aws-marketplace:BatchMeterUsage": {}, - "aws-marketplace:CancelAgreement": {}, - "aws-marketplace:CancelAgreementRequest": {}, - "aws-marketplace:CompleteTask": {}, - "aws-marketplace:CreateAgreementRequest": {}, - "aws-marketplace:CreatePrivateMarketplaceRequests": {}, - "aws-marketplace:DescribeAgreement": {}, - "aws-marketplace:DescribeBuilds": {}, - "aws-marketplace:DescribePrivateMarketplaceRequests": {}, - "aws-marketplace:DescribeProcurementSystemConfiguration": {}, - "aws-marketplace:DescribeTask": {}, - "aws-marketplace:DisassociateProductsFromPrivateMarketplace": {}, - "aws-marketplace:GetAgreementApprovalRequest": {}, - "aws-marketplace:GetAgreementRequest": {}, - "aws-marketplace:GetAgreementTerms": {}, - "aws-marketplace:ListAgreementApprovalRequests": {}, - "aws-marketplace:ListAgreementRequests": {}, - "aws-marketplace:ListBuilds": {}, - "aws-marketplace:ListChangeSets": {}, - "aws-marketplace:ListEntities": {}, - "aws-marketplace:ListEntitlementDetails": {}, - "aws-marketplace:ListPrivateListings": {}, - "aws-marketplace:ListPrivateMarketplaceRequests": {}, - "aws-marketplace:ListTasks": {}, - "aws-marketplace:MeterUsage": {}, - "aws-marketplace:PutProcurementSystemConfiguration": {}, - "aws-marketplace:RegisterUsage": {}, - "aws-marketplace:RejectAgreementApprovalRequest": {}, - "aws-marketplace:ResolveCustomer": {}, - "aws-marketplace:SearchAgreements": {}, - "aws-marketplace:StartBuild": {}, - "aws-marketplace:Subscribe": {}, - "aws-marketplace:Unsubscribe": {}, - "aws-marketplace:UpdateAgreementApprovalRequest": {}, - "aws-marketplace:UpdateTask": {}, - "aws-marketplace:ViewSubscriptions": {}, - "aws-portal:GetConsoleActionSetEnforced": {}, - "aws-portal:ModifyAccount": {}, - "aws-portal:ModifyBilling": {}, - "aws-portal:ModifyPaymentMethods": {}, - "aws-portal:UpdateConsoleActionSetEnforced": {}, - "aws-portal:ViewAccount": {}, - "aws-portal:ViewBilling": {}, - "aws-portal:ViewPaymentMethods": {}, - "aws-portal:ViewUsage": {}, - "awsconnector:GetConnectorHealth": {}, - "awsconnector:RegisterConnector": {}, - "awsconnector:ValidateConnectorId": {}, - "b2bi:CreateProfile": {}, - "b2bi:CreateTransformer": {}, - "b2bi:ListCapabilities": {}, - "b2bi:ListPartnerships": {}, - "b2bi:ListProfiles": {}, - "b2bi:ListTransformers": {}, - "backup-gateway:CreateGateway": {}, - "backup-gateway:ImportHypervisorConfiguration": {}, - "backup-gateway:ListGateways": {}, - "backup-gateway:ListHypervisors": {}, - "backup-gateway:ListVirtualMachines": {}, - "backup-storage:CommitBackupJob": {}, - "backup-storage:DeleteObjects": {}, - "backup-storage:DescribeBackupJob": {}, - "backup-storage:GetBaseBackup": {}, - "backup-storage:GetChunk": {}, - "backup-storage:GetIncrementalBaseBackup": {}, - "backup-storage:GetObjectMetadata": {}, - "backup-storage:ListChunks": {}, - "backup-storage:ListObjects": {}, - "backup-storage:MountCapsule": {}, - "backup-storage:NotifyObjectComplete": {}, - "backup-storage:PutChunk": {}, - "backup-storage:PutObject": {}, - "backup-storage:StartObject": {}, - "backup-storage:UpdateObjectComplete": {}, - "backup:DescribeBackupJob": {}, - "backup:DescribeCopyJob": {}, - "backup:DescribeGlobalSettings": {}, - "backup:DescribeProtectedResource": {}, - "backup:DescribeRegionSettings": {}, - "backup:DescribeReportJob": {}, - "backup:DescribeRestoreJob": {}, - "backup:ExportBackupPlanTemplate": {}, - "backup:GetBackupPlanFromJSON": {}, - "backup:GetBackupPlanFromTemplate": {}, - "backup:GetRestoreJobMetadata": {}, - "backup:GetRestoreTestingInferredMetadata": {}, - "backup:GetSupportedResourceTypes": {}, - "backup:ListBackupJobSummaries": {}, - "backup:ListBackupJobs": {}, - "backup:ListBackupPlanTemplates": {}, - "backup:ListBackupPlans": {}, - "backup:ListBackupVaults": {}, - "backup:ListCopyJobSummaries": {}, - "backup:ListCopyJobs": {}, - "backup:ListFrameworks": {}, - "backup:ListLegalHolds": {}, - "backup:ListProtectedResources": {}, - "backup:ListRecoveryPointsByResource": {}, - "backup:ListReportJobs": {}, - "backup:ListReportPlans": {}, - "backup:ListRestoreJobSummaries": {}, - "backup:ListRestoreJobs": {}, - "backup:ListRestoreJobsByProtectedResource": {}, - "backup:ListRestoreTestingPlans": {}, - "backup:PutRestoreValidationResult": {}, - "backup:StopBackupJob": {}, - "backup:UpdateGlobalSettings": {}, - "backup:UpdateRegionSettings": {}, - "batch:DescribeComputeEnvironments": {}, - "batch:DescribeJobDefinitions": {}, - "batch:DescribeJobQueues": {}, - "batch:DescribeJobs": {}, - "batch:DescribeSchedulingPolicies": {}, - "batch:ListJobs": {}, - "batch:ListSchedulingPolicies": {}, - "bcm-data-exports:ListExports": {}, - "bcm-data-exports:ListTables": {}, - "bedrock:AssociateThirdPartyKnowledgeBase": {}, - "bedrock:CreateAgent": {}, - "bedrock:CreateFoundationModelAgreement": {}, - "bedrock:CreateGuardrail": {}, - "bedrock:CreateKnowledgeBase": {}, - "bedrock:DeleteFoundationModelAgreement": {}, - "bedrock:DeleteModelInvocationLoggingConfiguration": {}, - "bedrock:GetFoundationModelAvailability": {}, - "bedrock:GetModelInvocationLoggingConfiguration": {}, - "bedrock:GetUseCaseForModelAccess": {}, - "bedrock:ListAgents": {}, - "bedrock:ListCustomModels": {}, - "bedrock:ListFoundationModelAgreementOffers": {}, - "bedrock:ListFoundationModels": {}, - "bedrock:ListKnowledgeBases": {}, - "bedrock:ListModelCustomizationJobs": {}, - "bedrock:ListModelEvaluationJobs": {}, - "bedrock:ListModelInvocationJobs": {}, - "bedrock:ListProvisionedModelThroughputs": {}, - "bedrock:PutFoundationModelEntitlement": {}, - "bedrock:PutModelInvocationLoggingConfiguration": {}, - "bedrock:PutUseCaseForModelAccess": {}, - "bedrock:RetrieveAndGenerate": {}, - "billing:GetBillingData": {}, - "billing:GetBillingDetails": {}, - "billing:GetBillingNotifications": {}, - "billing:GetBillingPreferences": {}, - "billing:GetContractInformation": {}, - "billing:GetCredits": {}, - "billing:GetIAMAccessPreference": {}, - "billing:GetSellerOfRecord": {}, - "billing:ListBillingViews": {}, - "billing:PutContractInformation": {}, - "billing:RedeemCredits": {}, - "billing:UpdateBillingPreferences": {}, - "billing:UpdateIAMAccessPreference": {}, - "billingconductor:CreatePricingRule": {}, - "billingconductor:ListAccountAssociations": {}, - "billingconductor:ListBillingGroupCostReports": {}, - "billingconductor:ListBillingGroups": {}, - "billingconductor:ListCustomLineItems": {}, - "billingconductor:ListPricingPlans": {}, - "billingconductor:ListPricingRules": {}, - "braket:AcceptUserAgreement": {}, - "braket:AccessBraketFeature": {}, - "braket:CreateJob": {}, - "braket:CreateQuantumTask": {}, - "braket:GetDevice": {}, - "braket:GetServiceLinkedRoleStatus": {}, - "braket:GetUserAgreementStatus": {}, - "braket:SearchDevices": {}, - "braket:SearchJobs": {}, - "braket:SearchQuantumTasks": {}, - "budgets:DescribeBudgetActionsForAccount": {}, - "bugbust:CreateEvent": {}, - "bugbust:ListEvents": {}, - "cases:CreateDomain": {}, - "cases:ListDomains": {}, - "cases:ListTagsForResource": {}, - "ce:CreateAnomalyMonitor": {}, - "ce:CreateAnomalySubscription": {}, - "ce:CreateCostCategoryDefinition": {}, - "ce:CreateNotificationSubscription": {}, - "ce:CreateReport": {}, - "ce:DeleteNotificationSubscription": {}, - "ce:DeleteReport": {}, - "ce:DescribeNotificationSubscription": {}, - "ce:DescribeReport": {}, - "ce:GetApproximateUsageRecords": {}, - "ce:GetConsoleActionSetEnforced": {}, - "ce:GetCostAndUsage": {}, - "ce:GetCostAndUsageWithResources": {}, - "ce:GetCostCategories": {}, - "ce:GetCostForecast": {}, - "ce:GetDimensionValues": {}, - "ce:GetPreferences": {}, - "ce:GetReservationCoverage": {}, - "ce:GetReservationPurchaseRecommendation": {}, - "ce:GetReservationUtilization": {}, - "ce:GetRightsizingRecommendation": {}, - "ce:GetSavingsPlanPurchaseRecommendationDetails": {}, - "ce:GetSavingsPlansCoverage": {}, - "ce:GetSavingsPlansPurchaseRecommendation": {}, - "ce:GetSavingsPlansUtilization": {}, - "ce:GetSavingsPlansUtilizationDetails": {}, - "ce:GetTags": {}, - "ce:GetUsageForecast": {}, - "ce:ListCostAllocationTags": {}, - "ce:ListCostCategoryDefinitions": {}, - "ce:ListSavingsPlansPurchaseRecommendationGeneration": {}, - "ce:ProvideAnomalyFeedback": {}, - "ce:StartSavingsPlansPurchaseRecommendationGeneration": {}, - "ce:UpdateConsoleActionSetEnforced": {}, - "ce:UpdateCostAllocationTagsStatus": {}, - "ce:UpdateNotificationSubscription": {}, - "ce:UpdatePreferences": {}, - "ce:UpdateReport": {}, - "chatbot:CreateChimeWebhookConfiguration": {}, - "chatbot:CreateMicrosoftTeamsChannelConfiguration": {}, - "chatbot:CreateSlackChannelConfiguration": {}, - "chatbot:DeleteMicrosoftTeamsChannelConfiguration": {}, - "chatbot:DeleteMicrosoftTeamsConfiguredTeam": {}, - "chatbot:DeleteMicrosoftTeamsUserIdentity": {}, - "chatbot:DeleteSlackUserIdentity": {}, - "chatbot:DeleteSlackWorkspaceAuthorization": {}, - "chatbot:DescribeChimeWebhookConfigurations": {}, - "chatbot:DescribeSlackChannelConfigurations": {}, - "chatbot:DescribeSlackChannels": {}, - "chatbot:DescribeSlackUserIdentities": {}, - "chatbot:DescribeSlackWorkspaces": {}, - "chatbot:GetAccountPreferences": {}, - "chatbot:GetMicrosoftTeamsChannelConfiguration": {}, - "chatbot:GetMicrosoftTeamsOauthParameters": {}, - "chatbot:GetSlackOauthParameters": {}, - "chatbot:ListMicrosoftTeamsChannelConfigurations": {}, - "chatbot:ListMicrosoftTeamsConfiguredTeams": {}, - "chatbot:ListMicrosoftTeamsUserIdentities": {}, - "chatbot:RedeemMicrosoftTeamsOauthCode": {}, - "chatbot:RedeemSlackOauthCode": {}, - "chatbot:UpdateAccountPreferences": {}, - "chatbot:UpdateMicrosoftTeamsChannelConfiguration": {}, - "chime:AcceptDelegate": {}, - "chime:ActivateUsers": {}, - "chime:AddDomain": {}, - "chime:AddOrUpdateGroups": {}, - "chime:AssociatePhoneNumberWithUser": {}, - "chime:AssociatePhoneNumbersWithVoiceConnectorGroup": {}, - "chime:AssociateSigninDelegateGroupsWithAccount": {}, - "chime:AuthorizeDirectory": {}, - "chime:BatchCreateRoomMembership": {}, - "chime:BatchDeletePhoneNumber": {}, - "chime:BatchSuspendUser": {}, - "chime:BatchUnsuspendUser": {}, - "chime:BatchUpdatePhoneNumber": {}, - "chime:BatchUpdateUser": {}, - "chime:ConnectDirectory": {}, - "chime:CreateAccount": {}, - "chime:CreateApiKey": {}, - "chime:CreateAppInstance": {}, - "chime:CreateAppInstanceBot": {}, - "chime:CreateAppInstanceUser": {}, - "chime:CreateBot": {}, - "chime:CreateCDRBucket": {}, - "chime:CreateMediaCapturePipeline": {}, - "chime:CreateMediaConcatenationPipeline": {}, - "chime:CreateMediaInsightsPipelineConfiguration": {}, - "chime:CreateMediaLiveConnectorPipeline": {}, - "chime:CreateMediaPipelineKinesisVideoStreamPool": {}, - "chime:CreateMeeting": {}, - "chime:CreateMeetingWithAttendees": {}, - "chime:CreatePhoneNumberOrder": {}, - "chime:CreateRoom": {}, - "chime:CreateRoomMembership": {}, - "chime:CreateSipMediaApplication": {}, - "chime:CreateUser": {}, - "chime:CreateVoiceConnector": {}, - "chime:CreateVoiceProfile": {}, - "chime:CreateVoiceProfileDomain": {}, - "chime:DeleteAccount": {}, - "chime:DeleteAccountOpenIdConfig": {}, - "chime:DeleteApiKey": {}, - "chime:DeleteCDRBucket": {}, - "chime:DeleteDelegate": {}, - "chime:DeleteDomain": {}, - "chime:DeleteEventsConfiguration": {}, - "chime:DeleteGroups": {}, - "chime:DeletePhoneNumber": {}, - "chime:DeleteRoom": {}, - "chime:DeleteRoomMembership": {}, - "chime:DeleteSipRule": {}, - "chime:DeleteVoiceConnectorGroup": {}, - "chime:DisassociatePhoneNumberFromUser": {}, - "chime:DisassociatePhoneNumbersFromVoiceConnectorGroup": {}, - "chime:DisassociateSigninDelegateGroupsFromAccount": {}, - "chime:DisconnectDirectory": {}, - "chime:GetAccount": {}, - "chime:GetAccountResource": {}, - "chime:GetAccountSettings": {}, - "chime:GetAccountWithOpenIdConfig": {}, - "chime:GetBot": {}, - "chime:GetCDRBucket": {}, - "chime:GetDomain": {}, - "chime:GetEventsConfiguration": {}, - "chime:GetGlobalSettings": {}, - "chime:GetMeetingDetail": {}, - "chime:GetMessagingSessionEndpoint": {}, - "chime:GetPhoneNumber": {}, - "chime:GetPhoneNumberOrder": {}, - "chime:GetPhoneNumberSettings": {}, - "chime:GetRetentionSettings": {}, - "chime:GetRoom": {}, - "chime:GetSipRule": {}, - "chime:GetTelephonyLimits": {}, - "chime:GetUser": {}, - "chime:GetUserActivityReportData": {}, - "chime:GetUserByEmail": {}, - "chime:GetUserSettings": {}, - "chime:GetVoiceConnectorGroup": {}, - "chime:InviteDelegate": {}, - "chime:InviteUsers": {}, - "chime:InviteUsersFromProvider": {}, - "chime:ListAccountUsageReportData": {}, - "chime:ListAccounts": {}, - "chime:ListApiKeys": {}, - "chime:ListAvailableVoiceConnectorRegions": {}, - "chime:ListBots": {}, - "chime:ListCDRBucket": {}, - "chime:ListCallingRegions": {}, - "chime:ListDelegates": {}, - "chime:ListDirectories": {}, - "chime:ListDomains": {}, - "chime:ListGroups": {}, - "chime:ListMediaCapturePipelines": {}, - "chime:ListMediaInsightsPipelineConfigurations": {}, - "chime:ListMediaPipelineKinesisVideoStreamPools": {}, - "chime:ListMediaPipelines": {}, - "chime:ListMeetingEvents": {}, - "chime:ListMeetings": {}, - "chime:ListMeetingsReportData": {}, - "chime:ListPhoneNumberOrders": {}, - "chime:ListPhoneNumbers": {}, - "chime:ListRoomMemberships": {}, - "chime:ListRooms": {}, - "chime:ListSipMediaApplications": {}, - "chime:ListSupportedPhoneNumberCountries": {}, - "chime:ListUsers": {}, - "chime:ListVoiceConnectorGroups": {}, - "chime:ListVoiceConnectors": {}, - "chime:ListVoiceProfileDomains": {}, - "chime:LogoutUser": {}, - "chime:PutEventsConfiguration": {}, - "chime:PutRetentionSettings": {}, - "chime:RedactConversationMessage": {}, - "chime:RedactRoomMessage": {}, - "chime:RegenerateSecurityToken": {}, - "chime:RenameAccount": {}, - "chime:RenewDelegate": {}, - "chime:ResetAccountResource": {}, - "chime:ResetPersonalPIN": {}, - "chime:RestorePhoneNumber": {}, - "chime:RetrieveDataExports": {}, - "chime:SearchAvailablePhoneNumbers": {}, - "chime:StartDataExport": {}, - "chime:StartMeetingTranscription": {}, - "chime:StopMeetingTranscription": {}, - "chime:SubmitSupportRequest": {}, - "chime:SuspendUsers": {}, - "chime:UnauthorizeDirectory": {}, - "chime:UpdateAccount": {}, - "chime:UpdateAccountOpenIdConfig": {}, - "chime:UpdateAccountResource": {}, - "chime:UpdateAccountSettings": {}, - "chime:UpdateBot": {}, - "chime:UpdateCDRSettings": {}, - "chime:UpdateGlobalSettings": {}, - "chime:UpdatePhoneNumber": {}, - "chime:UpdatePhoneNumberSettings": {}, - "chime:UpdateRoom": {}, - "chime:UpdateRoomMembership": {}, - "chime:UpdateSupportedLicenses": {}, - "chime:UpdateUser": {}, - "chime:UpdateUserLicenses": {}, - "chime:UpdateUserSettings": {}, - "chime:ValidateAccountResource": {}, - "chime:ValidateE911Address": {}, - "cleanrooms-ml:CreateTrainingDataset": {}, - "cleanrooms-ml:ListAudienceModels": {}, - "cleanrooms-ml:ListConfiguredAudienceModels": {}, - "cleanrooms-ml:ListTrainingDatasets": {}, - "cleanrooms:ListCollaborations": {}, - "cleanrooms:ListConfiguredTables": {}, - "cleanrooms:ListMemberships": {}, - "cloud9:CreateEnvironmentEC2": {}, - "cloud9:CreateEnvironmentSSH": {}, - "cloud9:GetMigrationExperiences": {}, - "cloud9:GetUserPublicKey": {}, - "cloud9:GetUserSettings": {}, - "cloud9:ListEnvironments": {}, - "cloud9:UpdateUserSettings": {}, - "cloud9:ValidateEnvironmentName": {}, - "clouddirectory:CreateSchema": {}, - "clouddirectory:ListDevelopmentSchemaArns": {}, - "clouddirectory:ListDirectories": {}, - "clouddirectory:ListManagedSchemaArns": {}, - "clouddirectory:ListPublishedSchemaArns": {}, - "clouddirectory:PutSchemaFromJson": {}, - "cloudformation:ActivateOrganizationsAccess": {}, - "cloudformation:ActivateType": {}, - "cloudformation:BatchDescribeTypeConfigurations": {}, - "cloudformation:CancelResourceRequest": {}, - "cloudformation:CreateGeneratedTemplate": {}, - "cloudformation:CreateResource": {}, - "cloudformation:CreateStackSet": {}, - "cloudformation:CreateUploadBucket": {}, - "cloudformation:DeactivateOrganizationsAccess": {}, - "cloudformation:DeactivateType": {}, - "cloudformation:DeleteGeneratedTemplate": {}, - "cloudformation:DeleteResource": {}, - "cloudformation:DeregisterType": {}, - "cloudformation:DescribeAccountLimits": {}, - "cloudformation:DescribeGeneratedTemplate": {}, - "cloudformation:DescribeOrganizationsAccess": {}, - "cloudformation:DescribePublisher": {}, - "cloudformation:DescribeResourceScan": {}, - "cloudformation:DescribeStackDriftDetectionStatus": {}, - "cloudformation:DescribeType": {}, - "cloudformation:DescribeTypeRegistration": {}, - "cloudformation:EstimateTemplateCost": {}, - "cloudformation:GetGeneratedTemplate": {}, - "cloudformation:GetResource": {}, - "cloudformation:GetResourceRequestStatus": {}, - "cloudformation:ListExports": {}, - "cloudformation:ListGeneratedTemplates": {}, - "cloudformation:ListImports": {}, - "cloudformation:ListResourceRequests": {}, - "cloudformation:ListResourceScanRelatedResources": {}, - "cloudformation:ListResourceScanResources": {}, - "cloudformation:ListResourceScans": {}, - "cloudformation:ListResources": {}, - "cloudformation:ListStackSets": {}, - "cloudformation:ListStacks": {}, - "cloudformation:ListTypeRegistrations": {}, - "cloudformation:ListTypeVersions": {}, - "cloudformation:ListTypes": {}, - "cloudformation:PublishType": {}, - "cloudformation:RegisterPublisher": {}, - "cloudformation:RegisterType": {}, - "cloudformation:SetTypeConfiguration": {}, - "cloudformation:SetTypeDefaultVersion": {}, - "cloudformation:StartResourceScan": {}, - "cloudformation:TestType": {}, - "cloudformation:UpdateGeneratedTemplate": {}, - "cloudformation:UpdateResource": {}, - "cloudformation:ValidateTemplate": {}, - "cloudfront:CreateFieldLevelEncryptionConfig": {}, - "cloudfront:CreateFieldLevelEncryptionProfile": {}, - "cloudfront:CreateKeyGroup": {}, - "cloudfront:CreateMonitoringSubscription": {}, - "cloudfront:CreateOriginAccessControl": {}, - "cloudfront:CreatePublicKey": {}, - "cloudfront:CreateSavingsPlan": {}, - "cloudfront:DeleteKeyGroup": {}, - "cloudfront:DeleteMonitoringSubscription": {}, - "cloudfront:DeletePublicKey": {}, - "cloudfront:GetKeyGroup": {}, - "cloudfront:GetKeyGroupConfig": {}, - "cloudfront:GetMonitoringSubscription": {}, - "cloudfront:GetPublicKey": {}, - "cloudfront:GetPublicKeyConfig": {}, - "cloudfront:GetSavingsPlan": {}, - "cloudfront:ListCachePolicies": {}, - "cloudfront:ListCloudFrontOriginAccessIdentities": {}, - "cloudfront:ListContinuousDeploymentPolicies": {}, - "cloudfront:ListDistributions": {}, - "cloudfront:ListDistributionsByCachePolicyId": {}, - "cloudfront:ListDistributionsByKeyGroup": {}, - "cloudfront:ListDistributionsByLambdaFunction": {}, - "cloudfront:ListDistributionsByOriginRequestPolicyId": {}, - "cloudfront:ListDistributionsByRealtimeLogConfig": {}, - "cloudfront:ListDistributionsByResponseHeadersPolicyId": {}, - "cloudfront:ListDistributionsByWebACLId": {}, - "cloudfront:ListFieldLevelEncryptionConfigs": {}, - "cloudfront:ListFieldLevelEncryptionProfiles": {}, - "cloudfront:ListFunctions": {}, - "cloudfront:ListKeyGroups": {}, - "cloudfront:ListKeyValueStores": {}, - "cloudfront:ListOriginAccessControls": {}, - "cloudfront:ListOriginRequestPolicies": {}, - "cloudfront:ListPublicKeys": {}, - "cloudfront:ListRateCards": {}, - "cloudfront:ListRealtimeLogConfigs": {}, - "cloudfront:ListResponseHeadersPolicies": {}, - "cloudfront:ListSavingsPlans": {}, - "cloudfront:ListStreamingDistributions": {}, - "cloudfront:ListUsages": {}, - "cloudfront:UpdateFieldLevelEncryptionConfig": {}, - "cloudfront:UpdateKeyGroup": {}, - "cloudfront:UpdatePublicKey": {}, - "cloudfront:UpdateSavingsPlan": {}, - "cloudhsm:AddTagsToResource": {}, - "cloudhsm:CreateHapg": {}, - "cloudhsm:CreateLunaClient": {}, - "cloudhsm:DeleteHapg": {}, - "cloudhsm:DeleteHsm": {}, - "cloudhsm:DeleteLunaClient": {}, - "cloudhsm:DescribeBackups": {}, - "cloudhsm:DescribeClusters": {}, - "cloudhsm:DescribeHapg": {}, - "cloudhsm:DescribeHsm": {}, - "cloudhsm:DescribeLunaClient": {}, - "cloudhsm:GetConfig": {}, - "cloudhsm:ListAvailableZones": {}, - "cloudhsm:ListHapgs": {}, - "cloudhsm:ListHsms": {}, - "cloudhsm:ListLunaClients": {}, - "cloudhsm:ListTagsForResource": {}, - "cloudhsm:ModifyHapg": {}, - "cloudhsm:ModifyHsm": {}, - "cloudhsm:ModifyLunaClient": {}, - "cloudhsm:RemoveTagsFromResource": {}, - "cloudshell:CreateEnvironment": {}, - "cloudtrail:DeregisterOrganizationDelegatedAdmin": {}, - "cloudtrail:DescribeTrails": {}, - "cloudtrail:GetImport": {}, - "cloudtrail:ListChannels": {}, - "cloudtrail:ListEventDataStores": {}, - "cloudtrail:ListImportFailures": {}, - "cloudtrail:ListImports": {}, - "cloudtrail:ListPublicKeys": {}, - "cloudtrail:ListServiceLinkedChannels": {}, - "cloudtrail:ListTrails": {}, - "cloudtrail:LookupEvents": {}, - "cloudtrail:RegisterOrganizationDelegatedAdmin": {}, - "cloudtrail:StartImport": {}, - "cloudtrail:StopImport": {}, - "cloudwatch:BatchGetServiceLevelIndicatorReport": {}, - "cloudwatch:CreateServiceLevelObjective": {}, - "cloudwatch:DeleteAnomalyDetector": {}, - "cloudwatch:DescribeAlarmsForMetric": {}, - "cloudwatch:DescribeAnomalyDetectors": {}, - "cloudwatch:DescribeInsightRules": {}, - "cloudwatch:EnableTopologyDiscovery": {}, - "cloudwatch:GenerateQuery": {}, - "cloudwatch:GetMetricData": {}, - "cloudwatch:GetMetricStatistics": {}, - "cloudwatch:GetMetricWidgetImage": {}, - "cloudwatch:GetTopologyDiscoveryStatus": {}, - "cloudwatch:GetTopologyMap": {}, - "cloudwatch:Link": {}, - "cloudwatch:ListDashboards": {}, - "cloudwatch:ListManagedInsightRules": {}, - "cloudwatch:ListMetricStreams": {}, - "cloudwatch:ListMetrics": {}, - "cloudwatch:ListServiceLevelObjectives": {}, - "cloudwatch:ListServices": {}, - "cloudwatch:PutAnomalyDetector": {}, - "cloudwatch:PutManagedInsightRules": {}, - "cloudwatch:PutMetricData": {}, - "codeartifact:CreateDomain": {}, - "codeartifact:CreateRepository": {}, - "codeartifact:ListDomains": {}, - "codeartifact:ListRepositories": {}, - "codebuild:DeleteOAuthToken": {}, - "codebuild:DeleteSourceCredentials": {}, - "codebuild:ImportSourceCredentials": {}, - "codebuild:ListBuildBatches": {}, - "codebuild:ListBuilds": {}, - "codebuild:ListConnectedOAuthAccounts": {}, - "codebuild:ListCuratedEnvironmentImages": {}, - "codebuild:ListFleets": {}, - "codebuild:ListProjects": {}, - "codebuild:ListReportGroups": {}, - "codebuild:ListReports": {}, - "codebuild:ListRepositories": {}, - "codebuild:ListSharedProjects": {}, - "codebuild:ListSharedReportGroups": {}, - "codebuild:ListSourceCredentials": {}, - "codebuild:PersistOAuthToken": {}, - "codecatalyst:AcceptConnection": {}, - "codecatalyst:CreateIdentityCenterApplication": {}, - "codecatalyst:CreateSpace": {}, - "codecatalyst:GetPendingConnection": {}, - "codecatalyst:ListConnections": {}, - "codecatalyst:ListIdentityCenterApplications": {}, - "codecatalyst:ListIdentityCenterApplicationsForSpace": {}, - "codecatalyst:RejectConnection": {}, - "codecommit:CreateApprovalRuleTemplate": {}, - "codecommit:DeleteApprovalRuleTemplate": {}, - "codecommit:GetApprovalRuleTemplate": {}, - "codecommit:ListApprovalRuleTemplates": {}, - "codecommit:ListRepositories": {}, - "codecommit:ListRepositoriesForApprovalRuleTemplate": {}, - "codecommit:UpdateApprovalRuleTemplateContent": {}, - "codecommit:UpdateApprovalRuleTemplateDescription": {}, - "codecommit:UpdateApprovalRuleTemplateName": {}, - "codedeploy-commands-secure:GetDeploymentSpecification": {}, - "codedeploy-commands-secure:PollHostCommand": {}, - "codedeploy-commands-secure:PutHostCommandAcknowledgement": {}, - "codedeploy-commands-secure:PutHostCommandComplete": {}, - "codedeploy:BatchGetDeploymentTargets": {}, - "codedeploy:ContinueDeployment": {}, - "codedeploy:DeleteGitHubAccountToken": {}, - "codedeploy:DeleteResourcesByExternalId": {}, - "codedeploy:GetDeploymentTarget": {}, - "codedeploy:ListApplications": {}, - "codedeploy:ListDeploymentConfigs": {}, - "codedeploy:ListDeploymentTargets": {}, - "codedeploy:ListGitHubAccountTokenNames": {}, - "codedeploy:ListOnPremisesInstances": {}, - "codedeploy:PutLifecycleEventHookExecutionStatus": {}, - "codedeploy:SkipWaitTimeForInstanceTermination": {}, - "codedeploy:StopDeployment": {}, - "codeguru-profiler:CreateProfilingGroup": {}, - "codeguru-profiler:GetFindingsReportAccountSummary": {}, - "codeguru-profiler:ListProfilingGroups": {}, - "codeguru-reviewer:AssociateRepository": {}, - "codeguru-reviewer:CreateConnectionToken": {}, - "codeguru-reviewer:GetMetricsData": {}, - "codeguru-reviewer:ListCodeReviews": {}, - "codeguru-reviewer:ListRepositoryAssociations": {}, - "codeguru-reviewer:ListThirdPartyRepositories": {}, - "codeguru-security:DeleteScansByCategory": {}, - "codeguru-security:GetAccountConfiguration": {}, - "codeguru-security:GetMetricsSummary": {}, - "codeguru-security:ListFindings": {}, - "codeguru-security:ListFindingsMetrics": {}, - "codeguru-security:ListScans": {}, - "codeguru-security:UpdateAccountConfiguration": {}, - "codeguru:GetCodeGuruFreeTrialSummary": {}, - "codepipeline:AcknowledgeJob": {}, - "codepipeline:AcknowledgeThirdPartyJob": {}, - "codepipeline:GetActionType": {}, - "codepipeline:GetJobDetails": {}, - "codepipeline:GetThirdPartyJobDetails": {}, - "codepipeline:ListActionTypes": {}, - "codepipeline:ListPipelines": {}, - "codepipeline:PollForThirdPartyJobs": {}, - "codepipeline:PutJobFailureResult": {}, - "codepipeline:PutJobSuccessResult": {}, - "codepipeline:PutThirdPartyJobFailureResult": {}, - "codepipeline:PutThirdPartyJobSuccessResult": {}, - "codestar-connections:CreateConnection": {}, - "codestar-connections:CreateHost": {}, - "codestar-connections:DeleteSyncConfiguration": {}, - "codestar-connections:GetIndividualAccessToken": {}, - "codestar-connections:GetInstallationUrl": {}, - "codestar-connections:GetResourceSyncStatus": {}, - "codestar-connections:GetSyncBlockerSummary": {}, - "codestar-connections:GetSyncConfiguration": {}, - "codestar-connections:ListHosts": {}, - "codestar-connections:ListInstallationTargets": {}, - "codestar-connections:ListRepositoryLinks": {}, - "codestar-connections:ListRepositorySyncDefinitions": {}, - "codestar-connections:ListSyncConfigurations": {}, - "codestar-connections:RegisterAppCode": {}, - "codestar-connections:StartAppRegistrationHandshake": {}, - "codestar-connections:StartOAuthHandshake": {}, - "codestar-connections:UpdateSyncBlocker": {}, - "codestar-connections:UpdateSyncConfiguration": {}, - "codestar-notifications:DeleteTarget": {}, - "codestar-notifications:ListEventTypes": {}, - "codestar-notifications:ListNotificationRules": {}, - "codestar-notifications:ListTargets": {}, - "codestar:CreateProject": {}, - "codestar:DescribeUserProfile": {}, - "codestar:ListProjects": {}, - "codestar:ListUserProfiles": {}, - "codewhisperer:GenerateRecommendations": {}, - "codewhisperer:ListProfiles": {}, - "cognito-identity:CreateIdentityPool": {}, - "cognito-identity:DeleteIdentities": {}, - "cognito-identity:DescribeIdentity": {}, - "cognito-identity:GetCredentialsForIdentity": {}, - "cognito-identity:GetId": {}, - "cognito-identity:GetOpenIdToken": {}, - "cognito-identity:ListIdentityPools": {}, - "cognito-identity:SetIdentityPoolRoles": {}, - "cognito-identity:SetPrincipalTagAttributeMap": {}, - "cognito-identity:UnlinkIdentity": {}, - "cognito-idp:AssociateSoftwareToken": {}, - "cognito-idp:ChangePassword": {}, - "cognito-idp:ConfirmDevice": {}, - "cognito-idp:ConfirmForgotPassword": {}, - "cognito-idp:ConfirmSignUp": {}, - "cognito-idp:CreateUserPool": {}, - "cognito-idp:DeleteUser": {}, - "cognito-idp:DeleteUserAttributes": {}, - "cognito-idp:DescribeUserPoolDomain": {}, - "cognito-idp:ForgetDevice": {}, - "cognito-idp:ForgotPassword": {}, - "cognito-idp:GetDevice": {}, - "cognito-idp:GetUser": {}, - "cognito-idp:GetUserAttributeVerificationCode": {}, - "cognito-idp:GlobalSignOut": {}, - "cognito-idp:InitiateAuth": {}, - "cognito-idp:ListDevices": {}, - "cognito-idp:ListUserPools": {}, - "cognito-idp:ResendConfirmationCode": {}, - "cognito-idp:RespondToAuthChallenge": {}, - "cognito-idp:RevokeToken": {}, - "cognito-idp:SetUserMFAPreference": {}, - "cognito-idp:SetUserSettings": {}, - "cognito-idp:SignUp": {}, - "cognito-idp:UpdateDeviceStatus": {}, - "cognito-idp:UpdateUserAttributes": {}, - "cognito-idp:VerifySoftwareToken": {}, - "cognito-idp:VerifyUserAttribute": {}, - "comprehend:BatchDetectDominantLanguage": {}, - "comprehend:BatchDetectEntities": {}, - "comprehend:BatchDetectKeyPhrases": {}, - "comprehend:BatchDetectSentiment": {}, - "comprehend:BatchDetectSyntax": {}, - "comprehend:BatchDetectTargetedSentiment": {}, - "comprehend:ContainsPiiEntities": {}, - "comprehend:DetectDominantLanguage": {}, - "comprehend:DetectKeyPhrases": {}, - "comprehend:DetectPiiEntities": {}, - "comprehend:DetectSentiment": {}, - "comprehend:DetectSyntax": {}, - "comprehend:DetectTargetedSentiment": {}, - "comprehend:DetectToxicContent": {}, - "comprehend:ListDocumentClassificationJobs": {}, - "comprehend:ListDocumentClassifierSummaries": {}, - "comprehend:ListDocumentClassifiers": {}, - "comprehend:ListDominantLanguageDetectionJobs": {}, - "comprehend:ListEndpoints": {}, - "comprehend:ListEntitiesDetectionJobs": {}, - "comprehend:ListEntityRecognizerSummaries": {}, - "comprehend:ListEntityRecognizers": {}, - "comprehend:ListEventsDetectionJobs": {}, - "comprehend:ListFlywheels": {}, - "comprehend:ListKeyPhrasesDetectionJobs": {}, - "comprehend:ListPiiEntitiesDetectionJobs": {}, - "comprehend:ListSentimentDetectionJobs": {}, - "comprehend:ListTargetedSentimentDetectionJobs": {}, - "comprehend:ListTopicsDetectionJobs": {}, - "comprehendmedical:DescribeEntitiesDetectionV2Job": {}, - "comprehendmedical:DescribeICD10CMInferenceJob": {}, - "comprehendmedical:DescribePHIDetectionJob": {}, - "comprehendmedical:DescribeRxNormInferenceJob": {}, - "comprehendmedical:DescribeSNOMEDCTInferenceJob": {}, - "comprehendmedical:DetectEntitiesV2": {}, - "comprehendmedical:DetectPHI": {}, - "comprehendmedical:InferICD10CM": {}, - "comprehendmedical:InferRxNorm": {}, - "comprehendmedical:InferSNOMEDCT": {}, - "comprehendmedical:ListEntitiesDetectionV2Jobs": {}, - "comprehendmedical:ListICD10CMInferenceJobs": {}, - "comprehendmedical:ListPHIDetectionJobs": {}, - "comprehendmedical:ListRxNormInferenceJobs": {}, - "comprehendmedical:ListSNOMEDCTInferenceJobs": {}, - "comprehendmedical:StartEntitiesDetectionV2Job": {}, - "comprehendmedical:StartICD10CMInferenceJob": {}, - "comprehendmedical:StartPHIDetectionJob": {}, - "comprehendmedical:StartRxNormInferenceJob": {}, - "comprehendmedical:StartSNOMEDCTInferenceJob": {}, - "comprehendmedical:StopEntitiesDetectionV2Job": {}, - "comprehendmedical:StopICD10CMInferenceJob": {}, - "comprehendmedical:StopPHIDetectionJob": {}, - "comprehendmedical:StopRxNormInferenceJob": {}, - "comprehendmedical:StopSNOMEDCTInferenceJob": {}, - "compute-optimizer:DeleteRecommendationPreferences": {}, - "compute-optimizer:DescribeRecommendationExportJobs": {}, - "compute-optimizer:ExportAutoScalingGroupRecommendations": {}, - "compute-optimizer:ExportEBSVolumeRecommendations": {}, - "compute-optimizer:ExportEC2InstanceRecommendations": {}, - "compute-optimizer:ExportECSServiceRecommendations": {}, - "compute-optimizer:ExportLambdaFunctionRecommendations": {}, - "compute-optimizer:ExportLicenseRecommendations": {}, - "compute-optimizer:GetAutoScalingGroupRecommendations": {}, - "compute-optimizer:GetEBSVolumeRecommendations": {}, - "compute-optimizer:GetEC2InstanceRecommendations": {}, - "compute-optimizer:GetEC2RecommendationProjectedMetrics": {}, - "compute-optimizer:GetECSServiceRecommendationProjectedMetrics": {}, - "compute-optimizer:GetECSServiceRecommendations": {}, - "compute-optimizer:GetEffectiveRecommendationPreferences": {}, - "compute-optimizer:GetEnrollmentStatus": {}, - "compute-optimizer:GetEnrollmentStatusesForOrganization": {}, - "compute-optimizer:GetLambdaFunctionRecommendations": {}, - "compute-optimizer:GetLicenseRecommendations": {}, - "compute-optimizer:GetRecommendationPreferences": {}, - "compute-optimizer:GetRecommendationSummaries": {}, - "compute-optimizer:PutRecommendationPreferences": {}, - "compute-optimizer:UpdateEnrollmentStatus": {}, - "config:BatchGetResourceConfig": {}, - "config:DeleteConfigurationRecorder": {}, - "config:DeleteDeliveryChannel": {}, - "config:DeletePendingAggregationRequest": {}, - "config:DeleteRemediationExceptions": {}, - "config:DeleteResourceConfig": {}, - "config:DeleteRetentionConfiguration": {}, - "config:DeliverConfigSnapshot": {}, - "config:DescribeAggregationAuthorizations": {}, - "config:DescribeComplianceByConfigRule": {}, - "config:DescribeComplianceByResource": {}, - "config:DescribeConfigRuleEvaluationStatus": {}, - "config:DescribeConfigRules": {}, - "config:DescribeConfigurationAggregators": {}, - "config:DescribeConfigurationRecorderStatus": {}, - "config:DescribeConfigurationRecorders": {}, - "config:DescribeConformancePackStatus": {}, - "config:DescribeConformancePacks": {}, - "config:DescribeDeliveryChannelStatus": {}, - "config:DescribeDeliveryChannels": {}, - "config:DescribeOrganizationConfigRuleStatuses": {}, - "config:DescribeOrganizationConfigRules": {}, - "config:DescribeOrganizationConformancePackStatuses": {}, - "config:DescribeOrganizationConformancePacks": {}, - "config:DescribePendingAggregationRequests": {}, - "config:DescribeRemediationExceptions": {}, - "config:DescribeRetentionConfigurations": {}, - "config:GetComplianceDetailsByResource": {}, - "config:GetComplianceSummaryByConfigRule": {}, - "config:GetComplianceSummaryByResourceType": {}, - "config:GetDiscoveredResourceCounts": {}, - "config:GetResourceConfigHistory": {}, - "config:GetResourceEvaluationSummary": {}, - "config:ListConformancePackComplianceScores": {}, - "config:ListDiscoveredResources": {}, - "config:ListResourceEvaluations": {}, - "config:ListStoredQueries": {}, - "config:PutConfigurationRecorder": {}, - "config:PutDeliveryChannel": {}, - "config:PutEvaluations": {}, - "config:PutRemediationExceptions": {}, - "config:PutResourceConfig": {}, - "config:PutRetentionConfiguration": {}, - "config:SelectResourceConfig": {}, - "config:StartConfigurationRecorder": {}, - "config:StartRemediationExecution": {}, - "config:StartResourceEvaluation": {}, - "config:StopConfigurationRecorder": {}, - "connect-campaigns:DeleteConnectInstanceConfig": {}, - "connect-campaigns:DeleteInstanceOnboardingJob": {}, - "connect-campaigns:GetConnectInstanceConfig": {}, - "connect-campaigns:GetInstanceOnboardingJobStatus": {}, - "connect-campaigns:ListCampaigns": {}, - "connect-campaigns:StartInstanceOnboardingJob": {}, - "connect:CreateInstance": {}, - "connect:ListInstances": {}, - "connect:SendChatIntegrationEvent": {}, - "consoleapp:ListDeviceIdentities": {}, - "consolidatedbilling:GetAccountBillingRole": {}, - "consolidatedbilling:ListLinkedAccounts": {}, - "controltower:CreateLandingZone": {}, - "controltower:CreateManagedAccount": {}, - "controltower:DeregisterManagedAccount": {}, - "controltower:DeregisterOrganizationalUnit": {}, - "controltower:DescribeAccountFactoryConfig": {}, - "controltower:DescribeCoreService": {}, - "controltower:DescribeGuardrail": {}, - "controltower:DescribeGuardrailForTarget": {}, - "controltower:DescribeLandingZoneConfiguration": {}, - "controltower:DescribeManagedAccount": {}, - "controltower:DescribeManagedOrganizationalUnit": {}, - "controltower:DescribeRegisterOrganizationalUnitOperation": {}, - "controltower:DescribeSingleSignOn": {}, - "controltower:DisableGuardrail": {}, - "controltower:EnableGuardrail": {}, - "controltower:GetAccountInfo": {}, - "controltower:GetAvailableUpdates": {}, - "controltower:GetControlOperation": {}, - "controltower:GetGuardrailComplianceStatus": {}, - "controltower:GetHomeRegion": {}, - "controltower:GetLandingZoneDriftStatus": {}, - "controltower:GetLandingZoneOperation": {}, - "controltower:GetLandingZoneStatus": {}, - "controltower:ListDirectoryGroups": {}, - "controltower:ListDriftDetails": {}, - "controltower:ListEnabledControls": {}, - "controltower:ListEnabledGuardrails": {}, - "controltower:ListExtendGovernancePrecheckDetails": {}, - "controltower:ListExternalConfigRuleCompliance": {}, - "controltower:ListGuardrailViolations": {}, - "controltower:ListGuardrails": {}, - "controltower:ListGuardrailsForTarget": {}, - "controltower:ListLandingZones": {}, - "controltower:ListManagedAccounts": {}, - "controltower:ListManagedAccountsForGuardrail": {}, - "controltower:ListManagedAccountsForParent": {}, - "controltower:ListManagedOrganizationalUnits": {}, - "controltower:ListManagedOrganizationalUnitsForGuardrail": {}, - "controltower:ManageOrganizationalUnit": {}, - "controltower:PerformPreLaunchChecks": {}, - "controltower:SetupLandingZone": {}, - "controltower:UpdateAccountFactoryConfig": {}, - "cost-optimization-hub:GetPreferences": {}, - "cost-optimization-hub:GetRecommendation": {}, - "cost-optimization-hub:ListEnrollmentStatuses": {}, - "cost-optimization-hub:ListRecommendationSummaries": {}, - "cost-optimization-hub:ListRecommendations": {}, - "cost-optimization-hub:UpdateEnrollmentStatus": {}, - "cost-optimization-hub:UpdatePreferences": {}, - "cur:DescribeReportDefinitions": {}, - "cur:GetClassicReport": {}, - "cur:GetClassicReportPreferences": {}, - "cur:GetUsageReport": {}, - "cur:PutClassicReportPreferences": {}, - "cur:ValidateReportDestination": {}, - "customer-verification:CreateCustomerVerificationDetails": {}, - "customer-verification:GetCustomerVerificationDetails": {}, - "customer-verification:GetCustomerVerificationEligibility": {}, - "customer-verification:UpdateCustomerVerificationDetails": {}, - "databrew:CreateDataset": {}, - "databrew:CreateProfileJob": {}, - "databrew:CreateProject": {}, - "databrew:CreateRecipe": {}, - "databrew:CreateRecipeJob": {}, - "databrew:CreateRuleset": {}, - "databrew:CreateSchedule": {}, - "databrew:ListDatasets": {}, - "databrew:ListJobs": {}, - "databrew:ListProjects": {}, - "databrew:ListRecipes": {}, - "databrew:ListRulesets": {}, - "databrew:ListSchedules": {}, - "dataexchange:CreateDataSet": {}, - "dataexchange:CreateEventAction": {}, - "dataexchange:CreateJob": {}, - "dataexchange:ListDataSets": {}, - "dataexchange:ListEventActions": {}, - "dataexchange:ListJobs": {}, - "datapipeline:CreatePipeline": {}, - "datapipeline:GetAccountLimits": {}, - "datapipeline:ListPipelines": {}, - "datapipeline:PollForTask": {}, - "datapipeline:PutAccountLimits": {}, - "datapipeline:ReportTaskRunnerHeartbeat": {}, - "datasync:CreateAgent": {}, - "datasync:CreateLocationAzureBlob": {}, - "datasync:CreateLocationEfs": {}, - "datasync:CreateLocationFsxLustre": {}, - "datasync:CreateLocationFsxOntap": {}, - "datasync:CreateLocationFsxOpenZfs": {}, - "datasync:CreateLocationFsxWindows": {}, - "datasync:CreateLocationHdfs": {}, - "datasync:CreateLocationNfs": {}, - "datasync:CreateLocationObjectStorage": {}, - "datasync:CreateLocationS3": {}, - "datasync:CreateLocationSmb": {}, - "datasync:ListAgents": {}, - "datasync:ListDiscoveryJobs": {}, - "datasync:ListLocations": {}, - "datasync:ListStorageSystems": {}, - "datasync:ListTaskExecutions": {}, - "datasync:ListTasks": {}, - "datazone:AcceptPredictions": {}, - "datazone:AcceptSubscriptionRequest": {}, - "datazone:CancelSubscription": {}, - "datazone:CreateAsset": {}, - "datazone:CreateAssetRevision": {}, - "datazone:CreateAssetType": {}, - "datazone:CreateDataSource": {}, - "datazone:CreateDomain": {}, - "datazone:CreateEnvironment": {}, - "datazone:CreateEnvironmentBlueprint": {}, - "datazone:CreateEnvironmentProfile": {}, - "datazone:CreateFormType": {}, - "datazone:CreateGlossary": {}, - "datazone:CreateGlossaryTerm": {}, - "datazone:CreateGroupProfile": {}, - "datazone:CreateListingChangeSet": {}, - "datazone:CreateProject": {}, - "datazone:CreateProjectMembership": {}, - "datazone:CreateSubscriptionGrant": {}, - "datazone:CreateSubscriptionRequest": {}, - "datazone:CreateSubscriptionTarget": {}, - "datazone:CreateUserProfile": {}, - "datazone:DeleteAsset": {}, - "datazone:DeleteAssetType": {}, - "datazone:DeleteDataSource": {}, - "datazone:DeleteDomainSharingPolicy": {}, - "datazone:DeleteEnvironment": {}, - "datazone:DeleteEnvironmentBlueprint": {}, - "datazone:DeleteEnvironmentBlueprintConfiguration": {}, - "datazone:DeleteEnvironmentProfile": {}, - "datazone:DeleteFormType": {}, - "datazone:DeleteGlossary": {}, - "datazone:DeleteGlossaryTerm": {}, - "datazone:DeleteListing": {}, - "datazone:DeleteProject": {}, - "datazone:DeleteProjectMembership": {}, - "datazone:DeleteSubscriptionGrant": {}, - "datazone:DeleteSubscriptionRequest": {}, - "datazone:DeleteSubscriptionTarget": {}, - "datazone:GetAsset": {}, - "datazone:GetAssetType": {}, - "datazone:GetDataSource": {}, - "datazone:GetDataSourceRun": {}, - "datazone:GetDomainSharingPolicy": {}, - "datazone:GetEnvironment": {}, - "datazone:GetEnvironmentActionLink": {}, - "datazone:GetEnvironmentBlueprint": {}, - "datazone:GetEnvironmentBlueprintConfiguration": {}, - "datazone:GetEnvironmentCredentials": {}, - "datazone:GetEnvironmentProfile": {}, - "datazone:GetFormType": {}, - "datazone:GetGlossary": {}, - "datazone:GetGlossaryTerm": {}, - "datazone:GetGroupProfile": {}, - "datazone:GetIamPortalLoginUrl": {}, - "datazone:GetListing": {}, - "datazone:GetMetadataGenerationRun": {}, - "datazone:GetProject": {}, - "datazone:GetSubscription": {}, - "datazone:GetSubscriptionEligibility": {}, - "datazone:GetSubscriptionGrant": {}, - "datazone:GetSubscriptionRequestDetails": {}, - "datazone:GetSubscriptionTarget": {}, - "datazone:GetUserProfile": {}, - "datazone:ListAccountEnvironments": {}, - "datazone:ListAssetRevisions": {}, - "datazone:ListDataSourceRunActivities": {}, - "datazone:ListDataSourceRuns": {}, - "datazone:ListDataSources": {}, - "datazone:ListDomains": {}, - "datazone:ListEnvironmentBlueprintConfigurationSummaries": {}, - "datazone:ListEnvironmentBlueprintConfigurations": {}, - "datazone:ListEnvironmentBlueprints": {}, - "datazone:ListEnvironmentProfiles": {}, - "datazone:ListEnvironments": {}, - "datazone:ListGroupsForUser": {}, - "datazone:ListMetadataGenerationRuns": {}, - "datazone:ListNotifications": {}, - "datazone:ListProjectMemberships": {}, - "datazone:ListProjects": {}, - "datazone:ListSubscriptionGrants": {}, - "datazone:ListSubscriptionRequests": {}, - "datazone:ListSubscriptionTargets": {}, - "datazone:ListSubscriptions": {}, - "datazone:ListWarehouseMetadata": {}, - "datazone:ProvisionDomain": {}, - "datazone:PutDomainSharingPolicy": {}, - "datazone:PutEnvironmentBlueprintConfiguration": {}, - "datazone:RefreshToken": {}, - "datazone:RejectPredictions": {}, - "datazone:RejectSubscriptionRequest": {}, - "datazone:RevokeSubscription": {}, - "datazone:Search": {}, - "datazone:SearchGroupProfiles": {}, - "datazone:SearchListings": {}, - "datazone:SearchTypes": {}, - "datazone:SearchUserProfiles": {}, - "datazone:SsoLogin": {}, - "datazone:SsoLogout": {}, - "datazone:StartDataSourceRun": {}, - "datazone:StartMetadataGenerationRun": {}, - "datazone:StopMetadataGenerationRun": {}, - "datazone:UpdateDataSource": {}, - "datazone:UpdateEnvironment": {}, - "datazone:UpdateEnvironmentBlueprint": {}, - "datazone:UpdateEnvironmentConfiguration": {}, - "datazone:UpdateEnvironmentDeploymentStatus": {}, - "datazone:UpdateEnvironmentProfile": {}, - "datazone:UpdateGlossary": {}, - "datazone:UpdateGlossaryTerm": {}, - "datazone:UpdateGroupProfile": {}, - "datazone:UpdateProject": {}, - "datazone:UpdateSubscriptionGrantStatus": {}, - "datazone:UpdateSubscriptionRequest": {}, - "datazone:UpdateSubscriptionTarget": {}, - "datazone:UpdateUserProfile": {}, - "datazone:ValidatePassRole": {}, - "dax:CreateParameterGroup": {}, - "dax:CreateSubnetGroup": {}, - "dax:DeleteParameterGroup": {}, - "dax:DeleteSubnetGroup": {}, - "dax:DescribeDefaultParameters": {}, - "dax:DescribeEvents": {}, - "dax:DescribeParameterGroups": {}, - "dax:DescribeParameters": {}, - "dax:DescribeSubnetGroups": {}, - "dax:UpdateParameterGroup": {}, - "dax:UpdateSubnetGroup": {}, - "dbqms:CreateFavoriteQuery": {}, - "dbqms:CreateTab": {}, - "dbqms:DeleteFavoriteQueries": {}, - "dbqms:DeleteQueryHistory": {}, - "dbqms:DeleteTab": {}, - "dbqms:DescribeFavoriteQueries": {}, - "dbqms:DescribeQueryHistory": {}, - "dbqms:DescribeTabs": {}, - "dbqms:GetQueryString": {}, - "dbqms:UpdateFavoriteQuery": {}, - "dbqms:UpdateQueryHistory": {}, - "dbqms:UpdateTab": {}, - "deepcomposer:AssociateCoupon": {}, - "deepracer:AdminGetAccountConfig": {}, - "deepracer:AdminListAssociatedResources": {}, - "deepracer:AdminListAssociatedUsers": {}, - "deepracer:AdminManageUser": {}, - "deepracer:AdminSetAccountConfig": {}, - "deepracer:CreateCar": {}, - "deepracer:CreateLeaderboard": {}, - "deepracer:GetAccountConfig": {}, - "deepracer:GetAlias": {}, - "deepracer:GetCars": {}, - "deepracer:ImportModel": {}, - "deepracer:ListLeaderboards": {}, - "deepracer:ListModels": {}, - "deepracer:ListPrivateLeaderboards": {}, - "deepracer:ListSubscribedPrivateLeaderboards": {}, - "deepracer:ListTracks": {}, - "deepracer:MigrateModels": {}, - "deepracer:SetAlias": {}, - "deepracer:TestRewardFunction": {}, - "detective:AcceptInvitation": {}, - "detective:BatchGetMembershipDatasources": {}, - "detective:CreateGraph": {}, - "detective:DisableOrganizationAdminAccount": {}, - "detective:DisassociateMembership": {}, - "detective:EnableOrganizationAdminAccount": {}, - "detective:GetPricingInformation": {}, - "detective:ListGraphs": {}, - "detective:ListInvitations": {}, - "detective:ListOrganizationAdminAccount": {}, - "detective:RejectInvitation": {}, - "devicefarm:CreateInstanceProfile": {}, - "devicefarm:CreateProject": {}, - "devicefarm:CreateTestGridProject": {}, - "devicefarm:CreateVPCEConfiguration": {}, - "devicefarm:GetAccountSettings": {}, - "devicefarm:GetOfferingStatus": {}, - "devicefarm:ListDeviceInstances": {}, - "devicefarm:ListDevices": {}, - "devicefarm:ListInstanceProfiles": {}, - "devicefarm:ListOfferingPromotions": {}, - "devicefarm:ListOfferingTransactions": {}, - "devicefarm:ListOfferings": {}, - "devicefarm:ListProjects": {}, - "devicefarm:ListTestGridProjects": {}, - "devicefarm:ListVPCEConfigurations": {}, - "devicefarm:PurchaseOffering": {}, - "devicefarm:RenewOffering": {}, - "devops-guru:DeleteInsight": {}, - "devops-guru:DescribeAccountHealth": {}, - "devops-guru:DescribeAccountOverview": {}, - "devops-guru:DescribeAnomaly": {}, - "devops-guru:DescribeEventSourcesConfig": {}, - "devops-guru:DescribeFeedback": {}, - "devops-guru:DescribeInsight": {}, - "devops-guru:DescribeOrganizationHealth": {}, - "devops-guru:DescribeOrganizationOverview": {}, - "devops-guru:DescribeOrganizationResourceCollectionHealth": {}, - "devops-guru:DescribeResourceCollectionHealth": {}, - "devops-guru:DescribeServiceIntegration": {}, - "devops-guru:GetCostEstimation": {}, - "devops-guru:GetResourceCollection": {}, - "devops-guru:ListAnomaliesForInsight": {}, - "devops-guru:ListAnomalousLogGroups": {}, - "devops-guru:ListEvents": {}, - "devops-guru:ListInsights": {}, - "devops-guru:ListMonitoredResources": {}, - "devops-guru:ListNotificationChannels": {}, - "devops-guru:ListOrganizationInsights": {}, - "devops-guru:ListRecommendations": {}, - "devops-guru:PutFeedback": {}, - "devops-guru:SearchInsights": {}, - "devops-guru:SearchOrganizationInsights": {}, - "devops-guru:StartCostEstimation": {}, - "devops-guru:UpdateEventSourcesConfig": {}, - "devops-guru:UpdateResourceCollection": {}, - "devops-guru:UpdateServiceIntegration": {}, - "directconnect:ConfirmCustomerAgreement": {}, - "directconnect:CreateDirectConnectGateway": {}, - "directconnect:DeleteDirectConnectGatewayAssociationProposal": {}, - "directconnect:DescribeCustomerMetadata": {}, - "directconnect:DescribeLocations": {}, - "directconnect:DescribeVirtualGateways": {}, - "directconnect:UpdateDirectConnectGatewayAssociation": {}, - "discovery:AssociateConfigurationItemsToApplication": {}, - "discovery:BatchDeleteAgents": {}, - "discovery:BatchDeleteImportData": {}, - "discovery:CreateApplication": {}, - "discovery:CreateTags": {}, - "discovery:DeleteApplications": {}, - "discovery:DeleteTags": {}, - "discovery:DescribeAgents": {}, - "discovery:DescribeBatchDeleteConfigurationTask": {}, - "discovery:DescribeConfigurations": {}, - "discovery:DescribeContinuousExports": {}, - "discovery:DescribeExportConfigurations": {}, - "discovery:DescribeExportTasks": {}, - "discovery:DescribeImportTasks": {}, - "discovery:DescribeTags": {}, - "discovery:DisassociateConfigurationItemsFromApplication": {}, - "discovery:ExportConfigurations": {}, - "discovery:GetDiscoverySummary": {}, - "discovery:GetNetworkConnectionGraph": {}, - "discovery:ListConfigurations": {}, - "discovery:ListServerNeighbors": {}, - "discovery:StartBatchDeleteConfigurationTask": {}, - "discovery:StartContinuousExport": {}, - "discovery:StartDataCollectionByAgentIds": {}, - "discovery:StartExportTask": {}, - "discovery:StartImportTask": {}, - "discovery:StopContinuousExport": {}, - "discovery:StopDataCollectionByAgentIds": {}, - "discovery:UpdateApplication": {}, - "dlm:CreateLifecyclePolicy": {}, - "dlm:GetLifecyclePolicies": {}, - "dms:BatchStartRecommendations": {}, - "dms:CreateDataProvider": {}, - "dms:CreateEndpoint": {}, - "dms:CreateEventSubscription": {}, - "dms:CreateFleetAdvisorCollector": {}, - "dms:CreateInstanceProfile": {}, - "dms:CreateReplicationInstance": {}, - "dms:CreateReplicationSubnetGroup": {}, - "dms:DeleteFleetAdvisorCollector": {}, - "dms:DeleteFleetAdvisorDatabases": {}, - "dms:DescribeAccountAttributes": {}, - "dms:DescribeCertificates": {}, - "dms:DescribeConnections": {}, - "dms:DescribeDataMigrations": {}, - "dms:DescribeEndpointSettings": {}, - "dms:DescribeEndpointTypes": {}, - "dms:DescribeEndpoints": {}, - "dms:DescribeEngineVersions": {}, - "dms:DescribeEventCategories": {}, - "dms:DescribeEventSubscriptions": {}, - "dms:DescribeEvents": {}, - "dms:DescribeFleetAdvisorCollectors": {}, - "dms:DescribeFleetAdvisorDatabases": {}, - "dms:DescribeFleetAdvisorLsaAnalysis": {}, - "dms:DescribeFleetAdvisorSchemaObjectSummary": {}, - "dms:DescribeFleetAdvisorSchemas": {}, - "dms:DescribeOrderableReplicationInstances": {}, - "dms:DescribePendingMaintenanceActions": {}, - "dms:DescribeRecommendationLimitations": {}, - "dms:DescribeRecommendations": {}, - "dms:DescribeReplicationConfigs": {}, - "dms:DescribeReplicationInstances": {}, - "dms:DescribeReplicationSubnetGroups": {}, - "dms:DescribeReplicationTasks": {}, - "dms:DescribeReplications": {}, - "dms:ImportCertificate": {}, - "dms:ModifyEventSubscription": {}, - "dms:ModifyFleetAdvisorCollector": {}, - "dms:ModifyFleetAdvisorCollectorStatuses": {}, - "dms:ModifyReplicationSubnetGroup": {}, - "dms:RunFleetAdvisorLsaAnalysis": {}, - "dms:StartRecommendations": {}, - "dms:UpdateSubscriptionsToEventBridge": {}, - "dms:UploadFileMetadataList": {}, - "docdb-elastic:CreateCluster": {}, - "docdb-elastic:ListClusterSnapshots": {}, - "docdb-elastic:ListClusters": {}, - "drs:BatchDeleteSnapshotRequestForDrs": {}, - "drs:CreateExtendedSourceServer": {}, - "drs:CreateLaunchConfigurationTemplate": {}, - "drs:CreateReplicationConfigurationTemplate": {}, - "drs:CreateSourceNetwork": {}, - "drs:CreateSourceServerForDrs": {}, - "drs:DescribeJobs": {}, - "drs:DescribeLaunchConfigurationTemplates": {}, - "drs:DescribeRecoveryInstances": {}, - "drs:DescribeReplicationConfigurationTemplates": {}, - "drs:DescribeReplicationServerAssociationsForDrs": {}, - "drs:DescribeSnapshotRequestsForDrs": {}, - "drs:DescribeSourceNetworks": {}, - "drs:DescribeSourceServers": {}, - "drs:GetAgentInstallationAssetsForDrs": {}, - "drs:GetChannelCommandsForDrs": {}, - "drs:InitializeService": {}, - "drs:ListExtensibleSourceServers": {}, - "drs:ListStagingAccounts": {}, - "drs:ListTagsForResource": {}, - "drs:SendChannelCommandResultForDrs": {}, - "drs:SendClientLogsForDrs": {}, - "drs:SendClientMetricsForDrs": {}, - "ds:CheckAlias": {}, - "ds:ConnectDirectory": {}, - "ds:CreateDirectory": {}, - "ds:CreateIdentityPoolDirectory": {}, - "ds:CreateMicrosoftAD": {}, - "ds:DescribeDirectories": {}, - "ds:DescribeSnapshots": {}, - "ds:DescribeTrusts": {}, - "ds:GetDirectoryLimits": {}, - "ds:ListLogSubscriptions": {}, - "dynamodb:DescribeEndpoints": {}, - "dynamodb:DescribeLimits": {}, - "dynamodb:DescribeReservedCapacity": {}, - "dynamodb:DescribeReservedCapacityOfferings": {}, - "dynamodb:ListBackups": {}, - "dynamodb:ListContributorInsights": {}, - "dynamodb:ListExports": {}, - "dynamodb:ListGlobalTables": {}, - "dynamodb:ListImports": {}, - "dynamodb:ListStreams": {}, - "dynamodb:ListTables": {}, - "dynamodb:PurchaseReservedCapacityOfferings": {}, - "ec2:AcceptReservedInstancesExchangeQuote": {}, - "ec2:AdvertiseByoipCidr": {}, - "ec2:AssociateIpamByoasn": {}, - "ec2:AssociateTrunkInterface": {}, - "ec2:BundleInstance": {}, - "ec2:CancelBundleTask": {}, - "ec2:CancelConversionTask": {}, - "ec2:CancelReservedInstancesListing": {}, - "ec2:ConfirmProductInstance": {}, - "ec2:CreateDefaultSubnet": {}, - "ec2:CreateDefaultVpc": {}, - "ec2:CreateReservedInstancesListing": {}, - "ec2:CreateSpotDatafeedSubscription": {}, - "ec2:CreateSubnetCidrReservation": {}, - "ec2:DeleteQueuedReservedInstances": {}, - "ec2:DeleteSpotDatafeedSubscription": {}, - "ec2:DeleteSubnetCidrReservation": {}, - "ec2:DeprovisionByoipCidr": {}, - "ec2:DeregisterInstanceEventNotificationAttributes": {}, - "ec2:DescribeAccountAttributes": {}, - "ec2:DescribeAddressTransfers": {}, - "ec2:DescribeAddresses": {}, - "ec2:DescribeAggregateIdFormat": {}, - "ec2:DescribeAvailabilityZones": {}, - "ec2:DescribeAwsNetworkPerformanceMetricSubscriptions": {}, - "ec2:DescribeBundleTasks": {}, - "ec2:DescribeByoipCidrs": {}, - "ec2:DescribeCapacityBlockOfferings": {}, - "ec2:DescribeCapacityReservationFleets": {}, - "ec2:DescribeCapacityReservations": {}, - "ec2:DescribeCarrierGateways": {}, - "ec2:DescribeClassicLinkInstances": {}, - "ec2:DescribeCoipPools": {}, - "ec2:DescribeConversionTasks": {}, - "ec2:DescribeCustomerGateways": {}, - "ec2:DescribeDhcpOptions": {}, - "ec2:DescribeEgressOnlyInternetGateways": {}, - "ec2:DescribeElasticGpus": {}, - "ec2:DescribeExportImageTasks": {}, - "ec2:DescribeExportTasks": {}, - "ec2:DescribeFastLaunchImages": {}, - "ec2:DescribeFastSnapshotRestores": {}, - "ec2:DescribeFleets": {}, - "ec2:DescribeFlowLogs": {}, - "ec2:DescribeFpgaImages": {}, - "ec2:DescribeHostReservationOfferings": {}, - "ec2:DescribeHostReservations": {}, - "ec2:DescribeHosts": {}, - "ec2:DescribeIamInstanceProfileAssociations": {}, - "ec2:DescribeIdFormat": {}, - "ec2:DescribeIdentityIdFormat": {}, - "ec2:DescribeImages": {}, - "ec2:DescribeImportImageTasks": {}, - "ec2:DescribeImportSnapshotTasks": {}, - "ec2:DescribeInstanceConnectEndpoints": {}, - "ec2:DescribeInstanceCreditSpecifications": {}, - "ec2:DescribeInstanceEventNotificationAttributes": {}, - "ec2:DescribeInstanceEventWindows": {}, - "ec2:DescribeInstanceStatus": {}, - "ec2:DescribeInstanceTopology": {}, - "ec2:DescribeInstanceTypeOfferings": {}, - "ec2:DescribeInstanceTypes": {}, - "ec2:DescribeInstances": {}, - "ec2:DescribeInternetGateways": {}, - "ec2:DescribeIpamByoasn": {}, - "ec2:DescribeIpamPools": {}, - "ec2:DescribeIpamResourceDiscoveries": {}, - "ec2:DescribeIpamResourceDiscoveryAssociations": {}, - "ec2:DescribeIpamScopes": {}, - "ec2:DescribeIpams": {}, - "ec2:DescribeIpv6Pools": {}, - "ec2:DescribeKeyPairs": {}, - "ec2:DescribeLaunchTemplateVersions": {}, - "ec2:DescribeLaunchTemplates": {}, - "ec2:DescribeLocalGatewayRouteTablePermissions": {}, - "ec2:DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociations": {}, - "ec2:DescribeLocalGatewayRouteTableVpcAssociations": {}, - "ec2:DescribeLocalGatewayRouteTables": {}, - "ec2:DescribeLocalGatewayVirtualInterfaceGroups": {}, - "ec2:DescribeLocalGatewayVirtualInterfaces": {}, - "ec2:DescribeLocalGateways": {}, - "ec2:DescribeLockedSnapshots": {}, - "ec2:DescribeManagedPrefixLists": {}, - "ec2:DescribeMovingAddresses": {}, - "ec2:DescribeNatGateways": {}, - "ec2:DescribeNetworkAcls": {}, - "ec2:DescribeNetworkInsightsAccessScopeAnalyses": {}, - "ec2:DescribeNetworkInsightsAccessScopes": {}, - "ec2:DescribeNetworkInsightsAnalyses": {}, - "ec2:DescribeNetworkInsightsPaths": {}, - "ec2:DescribeNetworkInterfaceAttribute": {}, - "ec2:DescribeNetworkInterfacePermissions": {}, - "ec2:DescribeNetworkInterfaces": {}, - "ec2:DescribePlacementGroups": {}, - "ec2:DescribePrefixLists": {}, - "ec2:DescribePrincipalIdFormat": {}, - "ec2:DescribePublicIpv4Pools": {}, - "ec2:DescribeRegions": {}, - "ec2:DescribeReplaceRootVolumeTasks": {}, - "ec2:DescribeReservedInstances": {}, - "ec2:DescribeReservedInstancesListings": {}, - "ec2:DescribeReservedInstancesModifications": {}, - "ec2:DescribeReservedInstancesOfferings": {}, - "ec2:DescribeRouteTables": {}, - "ec2:DescribeScheduledInstanceAvailability": {}, - "ec2:DescribeScheduledInstances": {}, - "ec2:DescribeSecurityGroupReferences": {}, - "ec2:DescribeSecurityGroupRules": {}, - "ec2:DescribeSecurityGroups": {}, - "ec2:DescribeSnapshotTierStatus": {}, - "ec2:DescribeSnapshots": {}, - "ec2:DescribeSpotDatafeedSubscription": {}, - "ec2:DescribeSpotFleetRequests": {}, - "ec2:DescribeSpotInstanceRequests": {}, - "ec2:DescribeSpotPriceHistory": {}, - "ec2:DescribeStaleSecurityGroups": {}, - "ec2:DescribeStoreImageTasks": {}, - "ec2:DescribeSubnets": {}, - "ec2:DescribeTags": {}, - "ec2:DescribeTrafficMirrorFilters": {}, - "ec2:DescribeTrafficMirrorSessions": {}, - "ec2:DescribeTrafficMirrorTargets": {}, - "ec2:DescribeTransitGatewayAttachments": {}, - "ec2:DescribeTransitGatewayConnectPeers": {}, - "ec2:DescribeTransitGatewayConnects": {}, - "ec2:DescribeTransitGatewayMulticastDomains": {}, - "ec2:DescribeTransitGatewayPeeringAttachments": {}, - "ec2:DescribeTransitGatewayPolicyTables": {}, - "ec2:DescribeTransitGatewayRouteTableAnnouncements": {}, - "ec2:DescribeTransitGatewayRouteTables": {}, - "ec2:DescribeTransitGatewayVpcAttachments": {}, - "ec2:DescribeTransitGateways": {}, - "ec2:DescribeTrunkInterfaceAssociations": {}, - "ec2:DescribeVerifiedAccessEndpoints": {}, - "ec2:DescribeVerifiedAccessGroups": {}, - "ec2:DescribeVerifiedAccessInstanceLoggingConfigurations": {}, - "ec2:DescribeVerifiedAccessInstanceWebAclAssociations": {}, - "ec2:DescribeVerifiedAccessInstances": {}, - "ec2:DescribeVerifiedAccessTrustProviders": {}, - "ec2:DescribeVolumeStatus": {}, - "ec2:DescribeVolumes": {}, - "ec2:DescribeVolumesModifications": {}, - "ec2:DescribeVpcClassicLink": {}, - "ec2:DescribeVpcClassicLinkDnsSupport": {}, - "ec2:DescribeVpcEndpointConnectionNotifications": {}, - "ec2:DescribeVpcEndpointConnections": {}, - "ec2:DescribeVpcEndpointServiceConfigurations": {}, - "ec2:DescribeVpcEndpointServices": {}, - "ec2:DescribeVpcEndpoints": {}, - "ec2:DescribeVpcPeeringConnections": {}, - "ec2:DescribeVpcs": {}, - "ec2:DescribeVpnConnections": {}, - "ec2:DescribeVpnGateways": {}, - "ec2:DisableAwsNetworkPerformanceMetricSubscription": {}, - "ec2:DisableEbsEncryptionByDefault": {}, - "ec2:DisableImageBlockPublicAccess": {}, - "ec2:DisableIpamOrganizationAdminAccount": {}, - "ec2:DisableSerialConsoleAccess": {}, - "ec2:DisableSnapshotBlockPublicAccess": {}, - "ec2:DisassociateIpamByoasn": {}, - "ec2:DisassociateTrunkInterface": {}, - "ec2:EnableAwsNetworkPerformanceMetricSubscription": {}, - "ec2:EnableEbsEncryptionByDefault": {}, - "ec2:EnableImageBlockPublicAccess": {}, - "ec2:EnableIpamOrganizationAdminAccount": {}, - "ec2:EnableReachabilityAnalyzerOrganizationSharing": {}, - "ec2:EnableSerialConsoleAccess": {}, - "ec2:EnableSnapshotBlockPublicAccess": {}, - "ec2:ExportTransitGatewayRoutes": {}, - "ec2:GetAssociatedIpv6PoolCidrs": {}, - "ec2:GetAwsNetworkPerformanceData": {}, - "ec2:GetDefaultCreditSpecification": {}, - "ec2:GetEbsDefaultKmsKeyId": {}, - "ec2:GetEbsEncryptionByDefault": {}, - "ec2:GetHostReservationPurchasePreview": {}, - "ec2:GetImageBlockPublicAccessState": {}, - "ec2:GetInstanceTypesFromInstanceRequirements": {}, - "ec2:GetReservedInstancesExchangeQuote": {}, - "ec2:GetSerialConsoleAccessStatus": {}, - "ec2:GetSnapshotBlockPublicAccessState": {}, - "ec2:GetSpotPlacementScores": {}, - "ec2:GetSubnetCidrReservations": {}, - "ec2:GetTransitGatewayAttachmentPropagations": {}, - "ec2:GetTransitGatewayPrefixListReferences": {}, - "ec2:GetTransitGatewayRouteTableAssociations": {}, - "ec2:GetTransitGatewayRouteTablePropagations": {}, - "ec2:GetVpnConnectionDeviceTypes": {}, - "ec2:InjectApiError": {}, - "ec2:ListImagesInRecycleBin": {}, - "ec2:ListSnapshotsInRecycleBin": {}, - "ec2:ModifyAvailabilityZoneGroup": {}, - "ec2:ModifyDefaultCreditSpecification": {}, - "ec2:ModifyEbsDefaultKmsKeyId": {}, - "ec2:ModifyIdFormat": {}, - "ec2:ModifyIdentityIdFormat": {}, - "ec2:MoveAddressToVpc": {}, - "ec2:ProvisionByoipCidr": {}, - "ec2:PurchaseReservedInstancesOffering": {}, - "ec2:PurchaseScheduledInstances": {}, - "ec2:RegisterInstanceEventNotificationAttributes": {}, - "ec2:ReportInstanceStatus": {}, - "ec2:ResetEbsDefaultKmsKeyId": {}, - "ec2:RestoreAddressToClassic": {}, - "ec2:RunScheduledInstances": {}, - "ec2:WithdrawByoipCidr": {}, - "ec2messages:AcknowledgeMessage": {}, - "ec2messages:DeleteMessage": {}, - "ec2messages:FailMessage": {}, - "ec2messages:GetEndpoint": {}, - "ec2messages:GetMessages": {}, - "ec2messages:SendReply": {}, - "ecr-public:GetAuthorizationToken": {}, - "ecr:BatchImportUpstreamImage": {}, - "ecr:CreatePullThroughCacheRule": {}, - "ecr:CreateRepository": {}, - "ecr:CreateRepositoryCreationTemplate": {}, - "ecr:DeletePullThroughCacheRule": {}, - "ecr:DeleteRegistryPolicy": {}, - "ecr:DeleteRepositoryCreationTemplate": {}, - "ecr:DescribePullThroughCacheRules": {}, - "ecr:DescribeRegistry": {}, - "ecr:DescribeRepositoryCreationTemplate": {}, - "ecr:GetAuthorizationToken": {}, - "ecr:GetRegistryPolicy": {}, - "ecr:GetRegistryScanningConfiguration": {}, - "ecr:PutRegistryPolicy": {}, - "ecr:PutRegistryScanningConfiguration": {}, - "ecr:PutReplicationConfiguration": {}, - "ecr:UpdatePullThroughCacheRule": {}, - "ecr:ValidatePullThroughCacheRule": {}, - "ecs:CreateCapacityProvider": {}, - "ecs:CreateCluster": {}, - "ecs:CreateTaskSet": {}, - "ecs:DeleteAccountSetting": {}, - "ecs:DeregisterTaskDefinition": {}, - "ecs:DescribeTaskDefinition": {}, - "ecs:DiscoverPollEndpoint": {}, - "ecs:ListAccountSettings": {}, - "ecs:ListClusters": {}, - "ecs:ListServices": {}, - "ecs:ListServicesByNamespace": {}, - "ecs:ListTaskDefinitionFamilies": {}, - "ecs:ListTaskDefinitions": {}, - "ecs:PutAccountSetting": {}, - "ecs:PutAccountSettingDefault": {}, - "ecs:RegisterTaskDefinition": {}, - "eks:CreateCluster": {}, - "eks:CreateEksAnywhereSubscription": {}, - "eks:DescribeAddonConfiguration": {}, - "eks:DescribeAddonVersions": {}, - "eks:ListAccessPolicies": {}, - "eks:ListClusters": {}, - "eks:ListEksAnywhereSubscriptions": {}, - "eks:RegisterCluster": {}, - "elasticache:DescribeCacheEngineVersions": {}, - "elasticache:DescribeEngineDefaultParameters": {}, - "elasticache:DescribeEvents": {}, - "elasticache:DescribeReservedCacheNodesOfferings": {}, - "elasticache:DescribeServiceUpdates": {}, - "elasticbeanstalk:CheckDNSAvailability": {}, - "elasticbeanstalk:CreateStorageLocation": {}, - "elasticbeanstalk:DescribeAccountAttributes": {}, - "elasticbeanstalk:ListPlatformBranches": {}, - "elasticfilesystem:CreateFileSystem": {}, - "elasticfilesystem:DescribeAccountPreferences": {}, - "elasticfilesystem:PutAccountPreferences": {}, - "elasticloadbalancing:DescribeAccountLimits": {}, - "elasticloadbalancing:DescribeInstanceHealth": {}, - "elasticloadbalancing:DescribeListenerCertificates": {}, - "elasticloadbalancing:DescribeListeners": {}, - "elasticloadbalancing:DescribeLoadBalancerAttributes": {}, - "elasticloadbalancing:DescribeLoadBalancerPolicies": {}, - "elasticloadbalancing:DescribeLoadBalancerPolicyTypes": {}, - "elasticloadbalancing:DescribeLoadBalancers": {}, - "elasticloadbalancing:DescribeRules": {}, - "elasticloadbalancing:DescribeSSLPolicies": {}, - "elasticloadbalancing:DescribeTags": {}, - "elasticloadbalancing:DescribeTargetGroupAttributes": {}, - "elasticloadbalancing:DescribeTargetGroups": {}, - "elasticloadbalancing:DescribeTargetHealth": {}, - "elasticloadbalancing:DescribeTrustStoreAssociations": {}, - "elasticloadbalancing:DescribeTrustStoreRevocations": {}, - "elasticloadbalancing:DescribeTrustStores": {}, - "elasticloadbalancing:SetWebAcl": {}, - "elasticmapreduce:CreateRepository": {}, - "elasticmapreduce:CreateSecurityConfiguration": {}, - "elasticmapreduce:CreateStudio": {}, - "elasticmapreduce:DeleteRepository": {}, - "elasticmapreduce:DeleteSecurityConfiguration": {}, - "elasticmapreduce:DescribeReleaseLabel": {}, - "elasticmapreduce:DescribeRepository": {}, - "elasticmapreduce:DescribeSecurityConfiguration": {}, - "elasticmapreduce:GetBlockPublicAccessConfiguration": {}, - "elasticmapreduce:LinkRepository": {}, - "elasticmapreduce:ListClusters": {}, - "elasticmapreduce:ListEditors": {}, - "elasticmapreduce:ListNotebookExecutions": {}, - "elasticmapreduce:ListReleaseLabels": {}, - "elasticmapreduce:ListRepositories": {}, - "elasticmapreduce:ListSecurityConfigurations": {}, - "elasticmapreduce:ListStudioSessionMappings": {}, - "elasticmapreduce:ListStudios": {}, - "elasticmapreduce:ListSupportedInstanceTypes": {}, - "elasticmapreduce:PutBlockPublicAccessConfiguration": {}, - "elasticmapreduce:RunJobFlow": {}, - "elasticmapreduce:UnlinkRepository": {}, - "elasticmapreduce:UpdateRepository": {}, - "elasticmapreduce:ViewEventsFromAllClustersInConsole": {}, - "elastictranscoder:CreatePipeline": {}, - "elastictranscoder:CreatePreset": {}, - "elastictranscoder:ListJobsByStatus": {}, - "elastictranscoder:ListPipelines": {}, - "elastictranscoder:ListPresets": {}, - "elastictranscoder:TestRole": {}, - "elemental-activations:CompleteAccountRegistration": {}, - "elemental-activations:CompleteFileUpload": {}, - "elemental-activations:DownloadSoftware": {}, - "elemental-activations:GenerateLicenses": {}, - "elemental-activations:StartAccountRegistration": {}, - "elemental-activations:StartFileUpload": {}, - "elemental-appliances-software:CompleteUpload": {}, - "elemental-appliances-software:CreateOrderV1": {}, - "elemental-appliances-software:GetAvsCorrectAddress": {}, - "elemental-appliances-software:GetBillingAddresses": {}, - "elemental-appliances-software:GetDeliveryAddressesV2": {}, - "elemental-appliances-software:GetOrder": {}, - "elemental-appliances-software:GetOrdersV2": {}, - "elemental-appliances-software:GetTaxes": {}, - "elemental-appliances-software:ListQuotes": {}, - "elemental-appliances-software:StartUpload": {}, - "elemental-appliances-software:SubmitOrderV1": {}, - "elemental-support-cases:CheckCasePermission": {}, - "elemental-support-cases:CreateCase": {}, - "elemental-support-cases:GetCase": {}, - "elemental-support-cases:GetCases": {}, - "elemental-support-cases:UpdateCase": {}, - "elemental-support-content:Query": {}, - "emr-containers:CreateJobTemplate": {}, - "emr-containers:CreateVirtualCluster": {}, - "emr-containers:ListJobTemplates": {}, - "emr-containers:ListVirtualClusters": {}, - "emr-serverless:CreateApplication": {}, - "emr-serverless:ListApplications": {}, - "entityresolution:CreateIdMappingWorkflow": {}, - "entityresolution:CreateMatchingWorkflow": {}, - "entityresolution:CreateSchemaMapping": {}, - "entityresolution:ListIdMappingWorkflows": {}, - "entityresolution:ListMatchingWorkflows": {}, - "entityresolution:ListSchemaMappings": {}, - "entityresolution:ListTagsForResource": {}, - "entityresolution:TagResource": {}, - "entityresolution:UntagResource": {}, - "es:AcceptInboundConnection": {}, - "es:AcceptInboundCrossClusterSearchConnection": {}, - "es:AuthorizeVpcEndpointAccess": {}, - "es:CreateElasticsearchServiceRole": {}, - "es:CreatePackage": {}, - "es:CreateServiceRole": {}, - "es:CreateVpcEndpoint": {}, - "es:DeleteElasticsearchServiceRole": {}, - "es:DeleteInboundConnection": {}, - "es:DeleteInboundCrossClusterSearchConnection": {}, - "es:DeleteOutboundConnection": {}, - "es:DeleteOutboundCrossClusterSearchConnection": {}, - "es:DeletePackage": {}, - "es:DeleteVpcEndpoint": {}, - "es:DescribeElasticsearchInstanceTypeLimits": {}, - "es:DescribeInboundConnections": {}, - "es:DescribeInboundCrossClusterSearchConnections": {}, - "es:DescribeInstanceTypeLimits": {}, - "es:DescribeOutboundConnections": {}, - "es:DescribeOutboundCrossClusterSearchConnections": {}, - "es:DescribePackages": {}, - "es:DescribeReservedElasticsearchInstanceOfferings": {}, - "es:DescribeReservedElasticsearchInstances": {}, - "es:DescribeReservedInstanceOfferings": {}, - "es:DescribeReservedInstances": {}, - "es:DescribeVpcEndpoints": {}, - "es:GetPackageVersionHistory": {}, - "es:ListDomainNames": {}, - "es:ListDomainsForPackage": {}, - "es:ListElasticsearchInstanceTypeDetails": {}, - "es:ListElasticsearchInstanceTypes": {}, - "es:ListElasticsearchVersions": {}, - "es:ListInstanceTypeDetails": {}, - "es:ListVersions": {}, - "es:ListVpcEndpointAccess": {}, - "es:ListVpcEndpoints": {}, - "es:ListVpcEndpointsForDomain": {}, - "es:PurchaseReservedElasticsearchInstanceOffering": {}, - "es:PurchaseReservedInstanceOffering": {}, - "es:RejectInboundConnection": {}, - "es:RejectInboundCrossClusterSearchConnection": {}, - "es:RevokeVpcEndpointAccess": {}, - "es:UpdatePackage": {}, - "es:UpdateVpcEndpoint": {}, - "events:ListApiDestinations": {}, - "events:ListArchives": {}, - "events:ListConnections": {}, - "events:ListEndpoints": {}, - "events:ListEventBuses": {}, - "events:ListEventSources": {}, - "events:ListPartnerEventSources": {}, - "events:ListReplays": {}, - "events:ListRuleNamesByTarget": {}, - "events:ListRules": {}, - "events:PutPartnerEvents": {}, - "events:PutPermission": {}, - "events:RemovePermission": {}, - "events:TestEventPattern": {}, - "evidently:CreateExperiment": {}, - "evidently:CreateFeature": {}, - "evidently:CreateLaunch": {}, - "evidently:CreateProject": {}, - "evidently:CreateSegment": {}, - "evidently:ListExperiments": {}, - "evidently:ListFeatures": {}, - "evidently:ListLaunches": {}, - "evidently:ListProjects": {}, - "evidently:ListSegmentReferences": {}, - "evidently:ListSegments": {}, - "evidently:ListTagsForResource": {}, - "evidently:TestSegmentPattern": {}, - "finspace:CreateKxEnvironment": {}, - "finspace:ListKxEnvironments": {}, - "firehose:ListDeliveryStreams": {}, - "fis:GetTargetResourceType": {}, - "fis:ListActions": {}, - "fis:ListExperimentTemplates": {}, - "fis:ListExperiments": {}, - "fis:ListTargetResourceTypes": {}, - "fms:AssociateAdminAccount": {}, - "fms:AssociateThirdPartyFirewall": {}, - "fms:DeleteNotificationChannel": {}, - "fms:DisassociateAdminAccount": {}, - "fms:DisassociateThirdPartyFirewall": {}, - "fms:GetAdminAccount": {}, - "fms:GetAdminScope": {}, - "fms:GetNotificationChannel": {}, - "fms:GetThirdPartyFirewallAssociationStatus": {}, - "fms:ListAdminAccountsForOrganization": {}, - "fms:ListAdminsManagingAccount": {}, - "fms:ListAppsLists": {}, - "fms:ListDiscoveredResources": {}, - "fms:ListMemberAccounts": {}, - "fms:ListPolicies": {}, - "fms:ListProtocolsLists": {}, - "fms:ListResourceSets": {}, - "fms:ListThirdPartyFirewallFirewallPolicies": {}, - "fms:PutAdminAccount": {}, - "fms:PutNotificationChannel": {}, - "forecast:CreateAutoPredictor": {}, - "forecast:ListDatasetGroups": {}, - "forecast:ListDatasetImportJobs": {}, - "forecast:ListDatasets": {}, - "forecast:ListExplainabilities": {}, - "forecast:ListExplainabilityExports": {}, - "forecast:ListForecastExportJobs": {}, - "forecast:ListForecasts": {}, - "forecast:ListMonitors": {}, - "forecast:ListPredictorBacktestExportJobs": {}, - "forecast:ListPredictors": {}, - "forecast:ListWhatIfAnalyses": {}, - "forecast:ListWhatIfForecastExports": {}, - "forecast:ListWhatIfForecasts": {}, - "frauddetector:BatchCreateVariable": {}, - "frauddetector:CreateList": {}, - "frauddetector:CreateVariable": {}, - "frauddetector:GetKMSEncryptionKey": {}, - "frauddetector:PutKMSEncryptionKey": {}, - "freertos:CreateSubscription": {}, - "freertos:DescribeHardwarePlatform": {}, - "freertos:GetEmpPatchUrl": {}, - "freertos:GetSoftwareURL": {}, - "freertos:GetSoftwareURLForConfiguration": {}, - "freertos:GetSubscriptionBillingAmount": {}, - "freertos:ListFreeRTOSVersions": {}, - "freertos:ListHardwarePlatforms": {}, - "freertos:ListHardwareVendors": {}, - "freertos:ListSoftwareConfigurations": {}, - "freertos:ListSoftwarePatches": {}, - "freertos:ListSubscriptionEmails": {}, - "freertos:ListSubscriptions": {}, - "freertos:UpdateEmailRecipients": {}, - "freertos:VerifyEmail": {}, - "freetier:GetFreeTierAlertPreference": {}, - "freetier:GetFreeTierUsage": {}, - "freetier:PutFreeTierAlertPreference": {}, - "fsx:DescribeBackups": {}, - "fsx:DescribeDataRepositoryAssociations": {}, - "fsx:DescribeDataRepositoryTasks": {}, - "fsx:DescribeFileCaches": {}, - "fsx:DescribeFileSystems": {}, - "fsx:DescribeSharedVpcConfiguration": {}, - "fsx:DescribeSnapshots": {}, - "fsx:DescribeStorageVirtualMachines": {}, - "fsx:DescribeVolumes": {}, - "fsx:UpdateSharedVpcConfiguration": {}, - "gamelift:AcceptMatch": {}, - "gamelift:CreateAlias": {}, - "gamelift:CreateBuild": {}, - "gamelift:CreateFleet": {}, - "gamelift:CreateGameServerGroup": {}, - "gamelift:CreateGameSession": {}, - "gamelift:CreateGameSessionQueue": {}, - "gamelift:CreateLocation": {}, - "gamelift:CreateMatchmakingConfiguration": {}, - "gamelift:CreateMatchmakingRuleSet": {}, - "gamelift:CreatePlayerSession": {}, - "gamelift:CreatePlayerSessions": {}, - "gamelift:CreateScript": {}, - "gamelift:CreateVpcPeeringAuthorization": {}, - "gamelift:CreateVpcPeeringConnection": {}, - "gamelift:DeleteVpcPeeringAuthorization": {}, - "gamelift:DeleteVpcPeeringConnection": {}, - "gamelift:DescribeEC2InstanceLimits": {}, - "gamelift:DescribeFleetAttributes": {}, - "gamelift:DescribeFleetCapacity": {}, - "gamelift:DescribeFleetUtilization": {}, - "gamelift:DescribeGameSessionDetails": {}, - "gamelift:DescribeGameSessionPlacement": {}, - "gamelift:DescribeGameSessionQueues": {}, - "gamelift:DescribeGameSessions": {}, - "gamelift:DescribeMatchmaking": {}, - "gamelift:DescribeMatchmakingConfigurations": {}, - "gamelift:DescribeMatchmakingRuleSets": {}, - "gamelift:DescribePlayerSessions": {}, - "gamelift:DescribeVpcPeeringAuthorizations": {}, - "gamelift:DescribeVpcPeeringConnections": {}, - "gamelift:GetGameSessionLogUrl": {}, - "gamelift:ListAliases": {}, - "gamelift:ListBuilds": {}, - "gamelift:ListFleets": {}, - "gamelift:ListGameServerGroups": {}, - "gamelift:ListLocations": {}, - "gamelift:ListScripts": {}, - "gamelift:SearchGameSessions": {}, - "gamelift:StartMatchBackfill": {}, - "gamelift:StartMatchmaking": {}, - "gamelift:StopGameSessionPlacement": {}, - "gamelift:StopMatchmaking": {}, - "gamelift:UpdateGameSession": {}, - "gamelift:ValidateMatchmakingRuleSet": {}, - "glacier:GetDataRetrievalPolicy": {}, - "glacier:ListProvisionedCapacity": {}, - "glacier:ListVaults": {}, - "glacier:PurchaseProvisionedCapacity": {}, - "glacier:SetDataRetrievalPolicy": {}, - "globalaccelerator:AdvertiseByoipCidr": {}, - "globalaccelerator:CreateAccelerator": {}, - "globalaccelerator:CreateCrossAccountAttachment": {}, - "globalaccelerator:CreateCustomRoutingAccelerator": {}, - "globalaccelerator:DeprovisionByoipCidr": {}, - "globalaccelerator:ListAccelerators": {}, - "globalaccelerator:ListByoipCidrs": {}, - "globalaccelerator:ListCrossAccountAttachments": {}, - "globalaccelerator:ListCrossAccountResourceAccounts": {}, - "globalaccelerator:ListCrossAccountResources": {}, - "globalaccelerator:ListCustomRoutingAccelerators": {}, - "globalaccelerator:ListCustomRoutingPortMappingsByDestination": {}, - "globalaccelerator:ProvisionByoipCidr": {}, - "globalaccelerator:WithdrawByoipCidr": {}, - "glue:CheckSchemaVersionValidity": {}, - "glue:CreateClassifier": {}, - "glue:CreateCrawler": {}, - "glue:CreateCustomEntityType": {}, - "glue:CreateDataQualityRuleset": {}, - "glue:CreateDevEndpoint": {}, - "glue:CreateMLTransform": {}, - "glue:CreateScript": {}, - "glue:CreateSecurityConfiguration": {}, - "glue:CreateSession": {}, - "glue:DeleteClassifier": {}, - "glue:DeleteSecurityConfiguration": {}, - "glue:DeregisterDataPreview": {}, - "glue:GetClassifier": {}, - "glue:GetClassifiers": {}, - "glue:GetColumnStatisticsTaskRun": {}, - "glue:GetColumnStatisticsTaskRuns": {}, - "glue:GetCrawlerMetrics": {}, - "glue:GetCrawlers": {}, - "glue:GetDataPreviewStatement": {}, - "glue:GetDataflowGraph": {}, - "glue:GetDevEndpoints": {}, - "glue:GetJobBookmark": {}, - "glue:GetJobs": {}, - "glue:GetMapping": {}, - "glue:GetNotebookInstanceStatus": {}, - "glue:GetPlan": {}, - "glue:GetSecurityConfiguration": {}, - "glue:GetSecurityConfigurations": {}, - "glue:GetTriggers": {}, - "glue:GlueNotebookAuthorize": {}, - "glue:GlueNotebookRefreshCredentials": {}, - "glue:ListBlueprints": {}, - "glue:ListColumnStatisticsTaskRuns": {}, - "glue:ListCrawlers": {}, - "glue:ListCrawls": {}, - "glue:ListCustomEntityTypes": {}, - "glue:ListDevEndpoints": {}, - "glue:ListJobs": {}, - "glue:ListRegistries": {}, - "glue:ListSessions": {}, - "glue:ListTriggers": {}, - "glue:ListWorkflows": {}, - "glue:ResetJobBookmark": {}, - "glue:RunDataPreviewStatement": {}, - "glue:SendFeedback": {}, - "glue:StartCompletion": {}, - "glue:StartCrawlerSchedule": {}, - "glue:StartNotebook": {}, - "glue:StopCrawlerSchedule": {}, - "glue:TerminateNotebook": {}, - "glue:TestConnection": {}, - "glue:UpdateClassifier": {}, - "glue:UpdateCrawlerSchedule": {}, - "glue:UseGlueStudio": {}, - "grafana:CreateWorkspace": {}, - "grafana:ListWorkspaces": {}, - "greengrass:AssociateServiceRoleToAccount": {}, - "greengrass:CreateConnectorDefinition": {}, - "greengrass:CreateCoreDefinition": {}, - "greengrass:CreateDeployment": {}, - "greengrass:CreateDeviceDefinition": {}, - "greengrass:CreateFunctionDefinition": {}, - "greengrass:CreateGroup": {}, - "greengrass:CreateLoggerDefinition": {}, - "greengrass:CreateResourceDefinition": {}, - "greengrass:CreateSoftwareUpdateJob": {}, - "greengrass:CreateSubscriptionDefinition": {}, - "greengrass:DisassociateServiceRoleFromAccount": {}, - "greengrass:GetServiceRoleForAccount": {}, - "greengrass:ListBulkDeployments": {}, - "greengrass:ListComponents": {}, - "greengrass:ListConnectorDefinitions": {}, - "greengrass:ListCoreDefinitions": {}, - "greengrass:ListCoreDevices": {}, - "greengrass:ListDeployments": {}, - "greengrass:ListDeviceDefinitions": {}, - "greengrass:ListFunctionDefinitions": {}, - "greengrass:ListGroups": {}, - "greengrass:ListLoggerDefinitions": {}, - "greengrass:ListResourceDefinitions": {}, - "greengrass:ListSubscriptionDefinitions": {}, - "greengrass:StartBulkDeployment": {}, - "groundstation:CreateConfig": {}, - "groundstation:CreateDataflowEndpointGroup": {}, - "groundstation:CreateEphemeris": {}, - "groundstation:CreateMissionProfile": {}, - "groundstation:GetMinuteUsage": {}, - "groundstation:ListConfigs": {}, - "groundstation:ListContacts": {}, - "groundstation:ListDataflowEndpointGroups": {}, - "groundstation:ListEphemerides": {}, - "groundstation:ListGroundStations": {}, - "groundstation:ListMissionProfiles": {}, - "groundstation:ListSatellites": {}, - "groundstation:RegisterAgent": {}, - "groundstation:ReserveContact": {}, - "groundtruthlabeling:AssociatePatchToManifestJob": {}, - "groundtruthlabeling:DescribeConsoleJob": {}, - "groundtruthlabeling:ListDatasetObjects": {}, - "groundtruthlabeling:RunFilterOrSampleDatasetJob": {}, - "groundtruthlabeling:RunGenerateManifestByCrawlingJob": {}, - "guardduty:AcceptAdministratorInvitation": {}, - "guardduty:AcceptInvitation": {}, - "guardduty:ArchiveFindings": {}, - "guardduty:CreateDetector": {}, - "guardduty:CreateIPSet": {}, - "guardduty:CreateMembers": {}, - "guardduty:CreatePublishingDestination": {}, - "guardduty:CreateSampleFindings": {}, - "guardduty:CreateThreatIntelSet": {}, - "guardduty:DeclineInvitations": {}, - "guardduty:DeleteInvitations": {}, - "guardduty:DeleteMembers": {}, - "guardduty:DescribeMalwareScans": {}, - "guardduty:DescribeOrganizationConfiguration": {}, - "guardduty:DisableOrganizationAdminAccount": {}, - "guardduty:DisassociateFromAdministratorAccount": {}, - "guardduty:DisassociateFromMasterAccount": {}, - "guardduty:DisassociateMembers": {}, - "guardduty:EnableOrganizationAdminAccount": {}, - "guardduty:GetAdministratorAccount": {}, - "guardduty:GetFindings": {}, - "guardduty:GetFindingsStatistics": {}, - "guardduty:GetInvitationsCount": {}, - "guardduty:GetMalwareScanSettings": {}, - "guardduty:GetMasterAccount": {}, - "guardduty:GetMemberDetectors": {}, - "guardduty:GetMembers": {}, - "guardduty:GetOrganizationStatistics": {}, - "guardduty:GetRemainingFreeTrialDays": {}, - "guardduty:GetUsageStatistics": {}, - "guardduty:InviteMembers": {}, - "guardduty:ListDetectors": {}, - "guardduty:ListFilters": {}, - "guardduty:ListFindings": {}, - "guardduty:ListIPSets": {}, - "guardduty:ListInvitations": {}, - "guardduty:ListMembers": {}, - "guardduty:ListOrganizationAdminAccounts": {}, - "guardduty:ListPublishingDestinations": {}, - "guardduty:ListThreatIntelSets": {}, - "guardduty:SendSecurityTelemetry": {}, - "guardduty:StartMalwareScan": {}, - "guardduty:StartMonitoringMembers": {}, - "guardduty:StopMonitoringMembers": {}, - "guardduty:UnarchiveFindings": {}, - "guardduty:UpdateFindingsFeedback": {}, - "guardduty:UpdateMalwareScanSettings": {}, - "guardduty:UpdateMemberDetectors": {}, - "guardduty:UpdateOrganizationConfiguration": {}, - "health:DescribeAffectedAccountsForOrganization": {}, - "health:DescribeAffectedEntitiesForOrganization": {}, - "health:DescribeEntityAggregates": {}, - "health:DescribeEntityAggregatesForOrganization": {}, - "health:DescribeEventAggregates": {}, - "health:DescribeEventDetailsForOrganization": {}, - "health:DescribeEventTypes": {}, - "health:DescribeEvents": {}, - "health:DescribeEventsForOrganization": {}, - "health:DescribeHealthServiceStatusForOrganization": {}, - "health:DisableHealthServiceAccessForOrganization": {}, - "health:EnableHealthServiceAccessForOrganization": {}, - "healthlake:CreateFHIRDatastore": {}, - "healthlake:ListFHIRDatastores": {}, - "honeycode:ApproveTeamAssociation": {}, - "honeycode:CreateTeam": {}, - "honeycode:CreateTenant": {}, - "honeycode:DeleteDomains": {}, - "honeycode:DeregisterGroups": {}, - "honeycode:DescribeTeam": {}, - "honeycode:ListDomains": {}, - "honeycode:ListGroups": {}, - "honeycode:ListTagsForResource": {}, - "honeycode:ListTeamAssociations": {}, - "honeycode:ListTenants": {}, - "honeycode:RegisterDomainForVerification": {}, - "honeycode:RegisterGroups": {}, - "honeycode:RejectTeamAssociation": {}, - "honeycode:RestartDomainVerification": {}, - "honeycode:TagResource": {}, - "honeycode:UntagResource": {}, - "honeycode:UpdateTeam": {}, - "iam:CreateAccountAlias": {}, - "iam:DeleteAccountAlias": {}, - "iam:DeleteAccountPasswordPolicy": {}, - "iam:DeleteCloudFrontPublicKey": {}, - "iam:GenerateCredentialReport": {}, - "iam:GetAccountAuthorizationDetails": {}, - "iam:GetAccountEmailAddress": {}, - "iam:GetAccountName": {}, - "iam:GetAccountPasswordPolicy": {}, - "iam:GetAccountSummary": {}, - "iam:GetCloudFrontPublicKey": {}, - "iam:GetContextKeysForCustomPolicy": {}, - "iam:GetCredentialReport": {}, - "iam:GetOrganizationsAccessReport": {}, - "iam:GetServiceLastAccessedDetails": {}, - "iam:GetServiceLastAccessedDetailsWithEntities": {}, - "iam:ListAccountAliases": {}, - "iam:ListCloudFrontPublicKeys": {}, - "iam:ListGroups": {}, - "iam:ListInstanceProfiles": {}, - "iam:ListOpenIDConnectProviders": {}, - "iam:ListPolicies": {}, - "iam:ListRoles": {}, - "iam:ListSAMLProviders": {}, - "iam:ListSTSRegionalEndpointsStatus": {}, - "iam:ListServerCertificates": {}, - "iam:ListUsers": {}, - "iam:ListVirtualMFADevices": {}, - "iam:SetSTSRegionalEndpointStatus": {}, - "iam:SetSecurityTokenServicePreferences": {}, - "iam:SimulateCustomPolicy": {}, - "iam:UpdateAccountEmailAddress": {}, - "iam:UpdateAccountName": {}, - "iam:UpdateAccountPasswordPolicy": {}, - "iam:UpdateCloudFrontPublicKey": {}, - "iam:UploadCloudFrontPublicKey": {}, - "identity-sync:CreateSyncProfile": {}, - "identitystore-auth:BatchDeleteSession": {}, - "identitystore-auth:BatchGetSession": {}, - "identitystore-auth:ListSessions": {}, - "imagebuilder:ListComponents": {}, - "imagebuilder:ListContainerRecipes": {}, - "imagebuilder:ListDistributionConfigurations": {}, - "imagebuilder:ListImagePipelines": {}, - "imagebuilder:ListImageRecipes": {}, - "imagebuilder:ListImages": {}, - "imagebuilder:ListInfrastructureConfigurations": {}, - "imagebuilder:ListLifecyclePolicies": {}, - "imagebuilder:ListWaitingWorkflowSteps": {}, - "imagebuilder:ListWorkflows": {}, - "importexport:CancelJob": {}, - "importexport:CreateJob": {}, - "importexport:GetShippingLabel": {}, - "importexport:GetStatus": {}, - "importexport:ListJobs": {}, - "importexport:UpdateJob": {}, - "inspector-scan:ScanSbom": {}, - "inspector2:AssociateMember": {}, - "inspector2:BatchGetAccountStatus": {}, - "inspector2:BatchGetCodeSnippet": {}, - "inspector2:BatchGetFindingDetails": {}, - "inspector2:BatchGetFreeTrialInfo": {}, - "inspector2:BatchGetMemberEc2DeepInspectionStatus": {}, - "inspector2:BatchUpdateMemberEc2DeepInspectionStatus": {}, - "inspector2:CancelFindingsReport": {}, - "inspector2:CancelSbomExport": {}, - "inspector2:CreateFindingsReport": {}, - "inspector2:CreateSbomExport": {}, - "inspector2:DescribeOrganizationConfiguration": {}, - "inspector2:Disable": {}, - "inspector2:DisableDelegatedAdminAccount": {}, - "inspector2:DisassociateMember": {}, - "inspector2:Enable": {}, - "inspector2:EnableDelegatedAdminAccount": {}, - "inspector2:GetCisScanReport": {}, - "inspector2:GetCisScanResultDetails": {}, - "inspector2:GetConfiguration": {}, - "inspector2:GetDelegatedAdminAccount": {}, - "inspector2:GetEc2DeepInspectionConfiguration": {}, - "inspector2:GetEncryptionKey": {}, - "inspector2:GetFindingsReportStatus": {}, - "inspector2:GetMember": {}, - "inspector2:GetSbomExport": {}, - "inspector2:ListAccountPermissions": {}, - "inspector2:ListCisScanConfigurations": {}, - "inspector2:ListCisScanResultsAggregatedByChecks": {}, - "inspector2:ListCisScanResultsAggregatedByTargetResource": {}, - "inspector2:ListCisScans": {}, - "inspector2:ListCoverage": {}, - "inspector2:ListCoverageStatistics": {}, - "inspector2:ListDelegatedAdminAccounts": {}, - "inspector2:ListFilters": {}, - "inspector2:ListFindingAggregations": {}, - "inspector2:ListFindings": {}, - "inspector2:ListMembers": {}, - "inspector2:ListTagsForResource": {}, - "inspector2:ListUsageTotals": {}, - "inspector2:ResetEncryptionKey": {}, - "inspector2:SearchVulnerabilities": {}, - "inspector2:SendCisSessionHealth": {}, - "inspector2:SendCisSessionTelemetry": {}, - "inspector2:StartCisSession": {}, - "inspector2:StopCisSession": {}, - "inspector2:UpdateConfiguration": {}, - "inspector2:UpdateEc2DeepInspectionConfiguration": {}, - "inspector2:UpdateEncryptionKey": {}, - "inspector2:UpdateOrgEc2DeepInspectionConfiguration": {}, - "inspector2:UpdateOrganizationConfiguration": {}, - "inspector:AddAttributesToFindings": {}, - "inspector:CreateAssessmentTarget": {}, - "inspector:CreateAssessmentTemplate": {}, - "inspector:CreateExclusionsPreview": {}, - "inspector:CreateResourceGroup": {}, - "inspector:DeleteAssessmentRun": {}, - "inspector:DeleteAssessmentTarget": {}, - "inspector:DeleteAssessmentTemplate": {}, - "inspector:DescribeAssessmentRuns": {}, - "inspector:DescribeAssessmentTargets": {}, - "inspector:DescribeAssessmentTemplates": {}, - "inspector:DescribeCrossAccountAccessRole": {}, - "inspector:DescribeExclusions": {}, - "inspector:DescribeFindings": {}, - "inspector:DescribeResourceGroups": {}, - "inspector:DescribeRulesPackages": {}, - "inspector:GetAssessmentReport": {}, - "inspector:GetExclusionsPreview": {}, - "inspector:GetTelemetryMetadata": {}, - "inspector:ListAssessmentRunAgents": {}, - "inspector:ListAssessmentRuns": {}, - "inspector:ListAssessmentTargets": {}, - "inspector:ListAssessmentTemplates": {}, - "inspector:ListEventSubscriptions": {}, - "inspector:ListExclusions": {}, - "inspector:ListFindings": {}, - "inspector:ListRulesPackages": {}, - "inspector:ListTagsForResource": {}, - "inspector:PreviewAgents": {}, - "inspector:RegisterCrossAccountAccessRole": {}, - "inspector:RemoveAttributesFromFindings": {}, - "inspector:SetTagsForResource": {}, - "inspector:StartAssessmentRun": {}, - "inspector:StopAssessmentRun": {}, - "inspector:SubscribeToEvent": {}, - "inspector:UnsubscribeFromEvent": {}, - "inspector:UpdateAssessmentTarget": {}, - "internetmonitor:ListMonitors": {}, - "invoicing:GetInvoiceEmailDeliveryPreferences": {}, - "invoicing:GetInvoicePDF": {}, - "invoicing:ListInvoiceSummaries": {}, - "invoicing:PutInvoiceEmailDeliveryPreferences": {}, - "iot-device-tester:CheckVersion": {}, - "iot-device-tester:DownloadTestSuite": {}, - "iot-device-tester:LatestIdt": {}, - "iot-device-tester:SendMetrics": {}, - "iot-device-tester:SupportedVersion": {}, - "iot1click:ClaimDevicesByClaimCode": {}, - "iot1click:ListDevices": {}, - "iot1click:ListProjects": {}, - "iot:AttachThingPrincipal": {}, - "iot:CancelAuditMitigationActionsTask": {}, - "iot:CancelAuditTask": {}, - "iot:CancelDetectMitigationActionsTask": {}, - "iot:ClearDefaultAuthorizer": {}, - "iot:CreateAuditSuppression": {}, - "iot:CreateCertificateFromCsr": {}, - "iot:CreateKeysAndCertificate": {}, - "iot:DeleteAccountAuditConfiguration": {}, - "iot:DeleteAuditSuppression": {}, - "iot:DeleteRegistrationCode": {}, - "iot:DeleteV2LoggingLevel": {}, - "iot:DescribeAccountAuditConfiguration": {}, - "iot:DescribeAuditFinding": {}, - "iot:DescribeAuditMitigationActionsTask": {}, - "iot:DescribeAuditSuppression": {}, - "iot:DescribeAuditTask": {}, - "iot:DescribeDefaultAuthorizer": {}, - "iot:DescribeDetectMitigationActionsTask": {}, - "iot:DescribeEndpoint": {}, - "iot:DescribeEventConfigurations": {}, - "iot:DescribeThingRegistrationTask": {}, - "iot:DetachThingPrincipal": {}, - "iot:GetIndexingConfiguration": {}, - "iot:GetLoggingOptions": {}, - "iot:GetPackageConfiguration": {}, - "iot:GetRegistrationCode": {}, - "iot:GetV2LoggingOptions": {}, - "iot:ListAttachedPolicies": {}, - "iot:ListAuditFindings": {}, - "iot:ListAuditMitigationActionsExecutions": {}, - "iot:ListAuditMitigationActionsTasks": {}, - "iot:ListAuditSuppressions": {}, - "iot:ListAuditTasks": {}, - "iot:ListAuthorizers": {}, - "iot:ListBillingGroups": {}, - "iot:ListCACertificates": {}, - "iot:ListCertificateProviders": {}, - "iot:ListCertificates": {}, - "iot:ListCertificatesByCA": {}, - "iot:ListCustomMetrics": {}, - "iot:ListDetectMitigationActionsTasks": {}, - "iot:ListDimensions": {}, - "iot:ListDomainConfigurations": {}, - "iot:ListFleetMetrics": {}, - "iot:ListIndices": {}, - "iot:ListJobTemplates": {}, - "iot:ListJobs": {}, - "iot:ListManagedJobTemplates": {}, - "iot:ListMitigationActions": {}, - "iot:ListOTAUpdates": {}, - "iot:ListOutgoingCertificates": {}, - "iot:ListPackageVersions": {}, - "iot:ListPackages": {}, - "iot:ListPolicies": {}, - "iot:ListPolicyPrincipals": {}, - "iot:ListPrincipalPolicies": {}, - "iot:ListPrincipalThings": {}, - "iot:ListProvisioningTemplates": {}, - "iot:ListRelatedResourcesForAuditFinding": {}, - "iot:ListRetainedMessages": {}, - "iot:ListRoleAliases": {}, - "iot:ListScheduledAudits": {}, - "iot:ListStreams": {}, - "iot:ListThingGroups": {}, - "iot:ListThingPrincipals": {}, - "iot:ListThingRegistrationTaskReports": {}, - "iot:ListThingRegistrationTasks": {}, - "iot:ListThingTypes": {}, - "iot:ListThings": {}, - "iot:ListTopicRuleDestinations": {}, - "iot:ListTopicRules": {}, - "iot:ListTunnels": {}, - "iot:ListV2LoggingLevels": {}, - "iot:OpenTunnel": {}, - "iot:PutVerificationStateOnViolation": {}, - "iot:RegisterCACertificate": {}, - "iot:RegisterCertificate": {}, - "iot:RegisterCertificateWithoutCA": {}, - "iot:RegisterThing": {}, - "iot:SetLoggingOptions": {}, - "iot:SetV2LoggingLevel": {}, - "iot:SetV2LoggingOptions": {}, - "iot:StartAuditMitigationActionsTask": {}, - "iot:StartOnDemandAuditTask": {}, - "iot:StartThingRegistrationTask": {}, - "iot:StopThingRegistrationTask": {}, - "iot:UpdateAccountAuditConfiguration": {}, - "iot:UpdateAuditSuppression": {}, - "iot:UpdateEventConfigurations": {}, - "iot:UpdateIndexingConfiguration": {}, - "iot:UpdatePackageConfiguration": {}, - "iot:ValidateSecurityProfileBehaviors": {}, - "iotanalytics:DescribeLoggingOptions": {}, - "iotanalytics:ListChannels": {}, - "iotanalytics:ListDatasets": {}, - "iotanalytics:ListDatastores": {}, - "iotanalytics:ListPipelines": {}, - "iotanalytics:PutLoggingOptions": {}, - "iotanalytics:RunPipelineActivity": {}, - "iotdeviceadvisor:CreateSuiteDefinition": {}, - "iotdeviceadvisor:GetEndpoint": {}, - "iotdeviceadvisor:ListSuiteDefinitions": {}, - "iotdeviceadvisor:StartSuiteRun": {}, - "iotevents:DescribeDetectorModelAnalysis": {}, - "iotevents:DescribeLoggingOptions": {}, - "iotevents:GetDetectorModelAnalysisResults": {}, - "iotevents:ListAlarmModels": {}, - "iotevents:ListDetectorModels": {}, - "iotevents:ListInputRoutings": {}, - "iotevents:ListInputs": {}, - "iotevents:PutLoggingOptions": {}, - "iotevents:StartDetectorModelAnalysis": {}, - "iotfleethub:CreateApplication": {}, - "iotfleethub:ListApplications": {}, - "iotfleetwise:GetEncryptionConfiguration": {}, - "iotfleetwise:GetLoggingOptions": {}, - "iotfleetwise:GetRegisterAccountStatus": {}, - "iotfleetwise:ListCampaigns": {}, - "iotfleetwise:ListDecoderManifests": {}, - "iotfleetwise:ListFleets": {}, - "iotfleetwise:ListModelManifests": {}, - "iotfleetwise:ListSignalCatalogs": {}, - "iotfleetwise:ListVehicles": {}, - "iotfleetwise:PutEncryptionConfiguration": {}, - "iotfleetwise:PutLoggingOptions": {}, - "iotfleetwise:RegisterAccount": {}, - "iotroborunner:CreateSite": {}, - "iotroborunner:ListSites": {}, - "iotsitewise:CreateAssetModel": {}, - "iotsitewise:CreateBulkImportJob": {}, - "iotsitewise:CreateGateway": {}, - "iotsitewise:CreatePortal": {}, - "iotsitewise:DescribeBulkImportJob": {}, - "iotsitewise:DescribeDefaultEncryptionConfiguration": {}, - "iotsitewise:DescribeLoggingOptions": {}, - "iotsitewise:DescribeStorageConfiguration": {}, - "iotsitewise:EnableSiteWiseIntegration": {}, - "iotsitewise:ExecuteQuery": {}, - "iotsitewise:ListAssetModels": {}, - "iotsitewise:ListBulkImportJobs": {}, - "iotsitewise:ListGateways": {}, - "iotsitewise:ListPortals": {}, - "iotsitewise:PutDefaultEncryptionConfiguration": {}, - "iotsitewise:PutLoggingOptions": {}, - "iotsitewise:PutStorageConfiguration": {}, - "iottwinmaker:CreateMetadataTransferJob": {}, - "iottwinmaker:CreateWorkspace": {}, - "iottwinmaker:GetPricingPlan": {}, - "iottwinmaker:ListMetadataTransferJobs": {}, - "iottwinmaker:ListWorkspaces": {}, - "iottwinmaker:UpdatePricingPlan": {}, - "iotwireless:AssociateAwsAccountWithPartnerAccount": {}, - "iotwireless:CreateDestination": {}, - "iotwireless:CreateDeviceProfile": {}, - "iotwireless:CreateFuotaTask": {}, - "iotwireless:CreateMulticastGroup": {}, - "iotwireless:CreateServiceProfile": {}, - "iotwireless:CreateWirelessDevice": {}, - "iotwireless:CreateWirelessGateway": {}, - "iotwireless:CreateWirelessGatewayTaskDefinition": {}, - "iotwireless:DeleteQueuedMessages": {}, - "iotwireless:GetEventConfigurationByResourceTypes": {}, - "iotwireless:GetLogLevelsByResourceTypes": {}, - "iotwireless:GetPositionEstimate": {}, - "iotwireless:GetServiceEndpoint": {}, - "iotwireless:ListDestinations": {}, - "iotwireless:ListDeviceProfiles": {}, - "iotwireless:ListEventConfigurations": {}, - "iotwireless:ListFuotaTasks": {}, - "iotwireless:ListMulticastGroups": {}, - "iotwireless:ListNetworkAnalyzerConfigurations": {}, - "iotwireless:ListPartnerAccounts": {}, - "iotwireless:ListPositionConfigurations": {}, - "iotwireless:ListQueuedMessages": {}, - "iotwireless:ListServiceProfiles": {}, - "iotwireless:ListWirelessDeviceImportTasks": {}, - "iotwireless:ListWirelessDevices": {}, - "iotwireless:ListWirelessGatewayTaskDefinitions": {}, - "iotwireless:ListWirelessGateways": {}, - "iotwireless:ResetAllResourceLogLevels": {}, - "iotwireless:StartSingleWirelessDeviceImportTask": {}, - "iotwireless:UpdateEventConfigurationByResourceTypes": {}, - "iotwireless:UpdateLogLevelsByResourceTypes": {}, - "iq:span": {}, - "ivs:ListEncoderConfigurations": {}, - "ivs:ListPlaybackRestrictionPolicies": {}, - "ivs:ListStorageConfigurations": {}, - "kafka:DescribeClusterOperation": {}, - "kafka:DescribeClusterOperationV2": {}, - "kafka:GetBootstrapBrokers": {}, - "kafka:GetCompatibleKafkaVersions": {}, - "kafka:ListClusters": {}, - "kafka:ListClustersV2": {}, - "kafka:ListConfigurations": {}, - "kafka:ListKafkaVersions": {}, - "kafka:ListReplicators": {}, - "kafka:ListVpcConnections": {}, - "kafkaconnect:CreateConnector": {}, - "kafkaconnect:CreateCustomPlugin": {}, - "kafkaconnect:CreateWorkerConfiguration": {}, - "kafkaconnect:DeleteConnector": {}, - "kafkaconnect:DeleteCustomPlugin": {}, - "kafkaconnect:ListConnectors": {}, - "kafkaconnect:ListCustomPlugins": {}, - "kafkaconnect:ListWorkerConfigurations": {}, - "kafkaconnect:UpdateConnector": {}, - "kendra-ranking:CreateRescoreExecutionPlan": {}, - "kendra-ranking:ListRescoreExecutionPlans": {}, - "kendra:CreateIndex": {}, - "kendra:ListIndices": {}, - "kinesis:DescribeLimits": {}, - "kinesis:DisableEnhancedMonitoring": {}, - "kinesis:EnableEnhancedMonitoring": {}, - "kinesis:ListStreams": {}, - "kinesis:UpdateShardCount": {}, - "kinesis:UpdateStreamMode": {}, - "kinesisanalytics:CreateApplication": {}, - "kinesisanalytics:DiscoverInputSchema": {}, - "kinesisanalytics:ListApplications": {}, - "kinesisvideo:ListEdgeAgentConfigurations": {}, - "kinesisvideo:ListSignalingChannels": {}, - "kinesisvideo:ListStreams": {}, - "kms:ConnectCustomKeyStore": {}, - "kms:CreateCustomKeyStore": {}, - "kms:CreateKey": {}, - "kms:DeleteCustomKeyStore": {}, - "kms:DescribeCustomKeyStores": {}, - "kms:DisconnectCustomKeyStore": {}, - "kms:GenerateRandom": {}, - "kms:ListAliases": {}, - "kms:ListKeys": {}, - "kms:ListRetirableGrants": {}, - "kms:UpdateCustomKeyStore": {}, - "lakeformation:AddLFTagsToResource": {}, - "lakeformation:BatchGrantPermissions": {}, - "lakeformation:BatchRevokePermissions": {}, - "lakeformation:CancelTransaction": {}, - "lakeformation:CommitTransaction": {}, - "lakeformation:CreateDataCellsFilter": {}, - "lakeformation:CreateLFTag": {}, - "lakeformation:CreateLakeFormationIdentityCenterConfiguration": {}, - "lakeformation:CreateLakeFormationOptIn": {}, - "lakeformation:DeleteDataCellsFilter": {}, - "lakeformation:DeleteLFTag": {}, - "lakeformation:DeleteLakeFormationIdentityCenterConfiguration": {}, - "lakeformation:DeleteLakeFormationOptIn": {}, - "lakeformation:DeleteObjectsOnCancel": {}, - "lakeformation:DeregisterResource": {}, - "lakeformation:DescribeLakeFormationIdentityCenterConfiguration": {}, - "lakeformation:DescribeResource": {}, - "lakeformation:DescribeTransaction": {}, - "lakeformation:ExtendTransaction": {}, - "lakeformation:GetDataAccess": {}, - "lakeformation:GetDataCellsFilter": {}, - "lakeformation:GetDataLakeSettings": {}, - "lakeformation:GetEffectivePermissionsForPath": {}, - "lakeformation:GetLFTag": {}, - "lakeformation:GetQueryState": {}, - "lakeformation:GetQueryStatistics": {}, - "lakeformation:GetResourceLFTags": {}, - "lakeformation:GetTableObjects": {}, - "lakeformation:GetWorkUnitResults": {}, - "lakeformation:GetWorkUnits": {}, - "lakeformation:GrantPermissions": {}, - "lakeformation:ListDataCellsFilter": {}, - "lakeformation:ListLFTags": {}, - "lakeformation:ListLakeFormationOptIns": {}, - "lakeformation:ListPermissions": {}, - "lakeformation:ListResources": {}, - "lakeformation:ListTableStorageOptimizers": {}, - "lakeformation:ListTransactions": {}, - "lakeformation:PutDataLakeSettings": {}, - "lakeformation:RegisterResource": {}, - "lakeformation:RemoveLFTagsFromResource": {}, - "lakeformation:RevokePermissions": {}, - "lakeformation:SearchDatabasesByLFTags": {}, - "lakeformation:SearchTablesByLFTags": {}, - "lakeformation:StartQueryPlanning": {}, - "lakeformation:StartTransaction": {}, - "lakeformation:UpdateDataCellsFilter": {}, - "lakeformation:UpdateLFTag": {}, - "lakeformation:UpdateLakeFormationIdentityCenterConfiguration": {}, - "lakeformation:UpdateResource": {}, - "lakeformation:UpdateTableObjects": {}, - "lakeformation:UpdateTableStorageOptimizer": {}, - "lambda:CreateCodeSigningConfig": {}, - "lambda:CreateEventSourceMapping": {}, - "lambda:GetAccountSettings": {}, - "lambda:ListCodeSigningConfigs": {}, - "lambda:ListEventSourceMappings": {}, - "lambda:ListFunctions": {}, - "lambda:ListLayerVersions": {}, - "lambda:ListLayers": {}, - "launchwizard:CreateAdditionalNode": {}, - "launchwizard:CreateDeployment": {}, - "launchwizard:CreateSettingsSet": {}, - "launchwizard:DeleteAdditionalNode": {}, - "launchwizard:DeleteApp": {}, - "launchwizard:DeleteDeployment": {}, - "launchwizard:DeleteSettingsSet": {}, - "launchwizard:DescribeAdditionalNode": {}, - "launchwizard:DescribeProvisionedApp": {}, - "launchwizard:DescribeProvisioningEvents": {}, - "launchwizard:DescribeSettingsSet": {}, - "launchwizard:GetDeployment": {}, - "launchwizard:GetInfrastructureSuggestion": {}, - "launchwizard:GetIpAddress": {}, - "launchwizard:GetResourceCostEstimate": {}, - "launchwizard:GetResourceRecommendation": {}, - "launchwizard:GetSettingsSet": {}, - "launchwizard:GetWorkload": {}, - "launchwizard:GetWorkloadAsset": {}, - "launchwizard:GetWorkloadAssets": {}, - "launchwizard:ListAdditionalNodes": {}, - "launchwizard:ListAllowedResources": {}, - "launchwizard:ListDeploymentEvents": {}, - "launchwizard:ListDeployments": {}, - "launchwizard:ListProvisionedApps": {}, - "launchwizard:ListResourceCostEstimates": {}, - "launchwizard:ListSettingsSets": {}, - "launchwizard:ListWorkloadDeploymentOptions": {}, - "launchwizard:ListWorkloadDeploymentPatterns": {}, - "launchwizard:ListWorkloads": {}, - "launchwizard:PutSettingsSet": {}, - "launchwizard:StartProvisioning": {}, - "launchwizard:UpdateSettingsSet": {}, - "lex:CreateTestSet": {}, - "lex:CreateUploadUrl": {}, - "lex:GetBotAliases": {}, - "lex:GetBots": {}, - "lex:GetBuiltinIntent": {}, - "lex:GetBuiltinIntents": {}, - "lex:GetBuiltinSlotTypes": {}, - "lex:GetImport": {}, - "lex:GetIntents": {}, - "lex:GetMigration": {}, - "lex:GetMigrations": {}, - "lex:GetSlotTypes": {}, - "lex:ListBots": {}, - "lex:ListBuiltInIntents": {}, - "lex:ListBuiltInSlotTypes": {}, - "lex:ListExports": {}, - "lex:ListImports": {}, - "lex:ListTestExecutions": {}, - "lex:ListTestSets": {}, - "lex:StartImport": {}, - "license-manager-linux-subscriptions:GetServiceSettings": {}, - "license-manager-linux-subscriptions:ListLinuxSubscriptionInstances": {}, - "license-manager-linux-subscriptions:ListLinuxSubscriptions": {}, - "license-manager-linux-subscriptions:UpdateServiceSettings": {}, - "license-manager-user-subscriptions:AssociateUser": {}, - "license-manager-user-subscriptions:DeregisterIdentityProvider": {}, - "license-manager-user-subscriptions:DisassociateUser": {}, - "license-manager-user-subscriptions:ListIdentityProviders": {}, - "license-manager-user-subscriptions:ListInstances": {}, - "license-manager-user-subscriptions:ListProductSubscriptions": {}, - "license-manager-user-subscriptions:ListUserAssociations": {}, - "license-manager-user-subscriptions:RegisterIdentityProvider": {}, - "license-manager-user-subscriptions:StartProductSubscription": {}, - "license-manager-user-subscriptions:StopProductSubscription": {}, - "license-manager-user-subscriptions:UpdateIdentityProviderSettings": {}, - "license-manager:CheckInLicense": {}, - "license-manager:CheckoutLicense": {}, - "license-manager:CreateLicense": {}, - "license-manager:CreateLicenseConfiguration": {}, - "license-manager:CreateLicenseConversionTaskForResource": {}, - "license-manager:CreateLicenseManagerReportGenerator": {}, - "license-manager:DeleteToken": {}, - "license-manager:ExtendLicenseConsumption": {}, - "license-manager:GetAccessToken": {}, - "license-manager:GetLicenseConversionTask": {}, - "license-manager:GetServiceSettings": {}, - "license-manager:ListDistributedGrants": {}, - "license-manager:ListLicenseConfigurations": {}, - "license-manager:ListLicenseConversionTasks": {}, - "license-manager:ListLicenseSpecificationsForResource": {}, - "license-manager:ListLicenses": {}, - "license-manager:ListReceivedGrants": {}, - "license-manager:ListReceivedGrantsForOrganization": {}, - "license-manager:ListReceivedLicenses": {}, - "license-manager:ListReceivedLicensesForOrganization": {}, - "license-manager:ListResourceInventory": {}, - "license-manager:ListTokens": {}, - "license-manager:UpdateServiceSettings": {}, - "lightsail:AllocateStaticIp": {}, - "lightsail:CopySnapshot": {}, - "lightsail:CreateBucket": {}, - "lightsail:CreateCertificate": {}, - "lightsail:CreateCloudFormationStack": {}, - "lightsail:CreateContactMethod": {}, - "lightsail:CreateContainerService": {}, - "lightsail:CreateContainerServiceRegistryLogin": {}, - "lightsail:CreateDisk": {}, - "lightsail:CreateDistribution": {}, - "lightsail:CreateDomain": {}, - "lightsail:CreateInstances": {}, - "lightsail:CreateKeyPair": {}, - "lightsail:CreateLoadBalancer": {}, - "lightsail:CreateRelationalDatabase": {}, - "lightsail:CreateRelationalDatabaseSnapshot": {}, - "lightsail:DeleteAutoSnapshot": {}, - "lightsail:DeleteContactMethod": {}, - "lightsail:DisableAddOn": {}, - "lightsail:DownloadDefaultKeyPair": {}, - "lightsail:EnableAddOn": {}, - "lightsail:GetActiveNames": {}, - "lightsail:GetAlarms": {}, - "lightsail:GetAutoSnapshots": {}, - "lightsail:GetBlueprints": {}, - "lightsail:GetBucketAccessKeys": {}, - "lightsail:GetBucketBundles": {}, - "lightsail:GetBucketMetricData": {}, - "lightsail:GetBuckets": {}, - "lightsail:GetBundles": {}, - "lightsail:GetCertificates": {}, - "lightsail:GetCloudFormationStackRecords": {}, - "lightsail:GetContactMethods": {}, - "lightsail:GetContainerAPIMetadata": {}, - "lightsail:GetContainerImages": {}, - "lightsail:GetContainerLog": {}, - "lightsail:GetContainerServiceDeployments": {}, - "lightsail:GetContainerServiceMetricData": {}, - "lightsail:GetContainerServicePowers": {}, - "lightsail:GetContainerServices": {}, - "lightsail:GetDisk": {}, - "lightsail:GetDiskSnapshot": {}, - "lightsail:GetDiskSnapshots": {}, - "lightsail:GetDisks": {}, - "lightsail:GetDistributionBundles": {}, - "lightsail:GetDistributionLatestCacheReset": {}, - "lightsail:GetDistributionMetricData": {}, - "lightsail:GetDistributions": {}, - "lightsail:GetDomain": {}, - "lightsail:GetDomains": {}, - "lightsail:GetExportSnapshotRecords": {}, - "lightsail:GetInstance": {}, - "lightsail:GetInstanceMetricData": {}, - "lightsail:GetInstancePortStates": {}, - "lightsail:GetInstanceSnapshot": {}, - "lightsail:GetInstanceSnapshots": {}, - "lightsail:GetInstanceState": {}, - "lightsail:GetInstances": {}, - "lightsail:GetKeyPair": {}, - "lightsail:GetKeyPairs": {}, - "lightsail:GetLoadBalancer": {}, - "lightsail:GetLoadBalancerMetricData": {}, - "lightsail:GetLoadBalancerTlsCertificates": {}, - "lightsail:GetLoadBalancerTlsPolicies": {}, - "lightsail:GetLoadBalancers": {}, - "lightsail:GetOperation": {}, - "lightsail:GetOperations": {}, - "lightsail:GetOperationsForResource": {}, - "lightsail:GetRegions": {}, - "lightsail:GetRelationalDatabase": {}, - "lightsail:GetRelationalDatabaseBlueprints": {}, - "lightsail:GetRelationalDatabaseBundles": {}, - "lightsail:GetRelationalDatabaseEvents": {}, - "lightsail:GetRelationalDatabaseLogEvents": {}, - "lightsail:GetRelationalDatabaseLogStreams": {}, - "lightsail:GetRelationalDatabaseMetricData": {}, - "lightsail:GetRelationalDatabaseParameters": {}, - "lightsail:GetRelationalDatabaseSnapshot": {}, - "lightsail:GetRelationalDatabaseSnapshots": {}, - "lightsail:GetRelationalDatabases": {}, - "lightsail:GetStaticIp": {}, - "lightsail:GetStaticIps": {}, - "lightsail:ImportKeyPair": {}, - "lightsail:IsVpcPeered": {}, - "lightsail:PeerVpc": {}, - "lightsail:SendContactMethodVerification": {}, - "lightsail:UnpeerVpc": {}, - "logs:CancelExportTask": {}, - "logs:CreateLogDelivery": {}, - "logs:DeleteAccountPolicy": {}, - "logs:DeleteLogDelivery": {}, - "logs:DeleteQueryDefinition": {}, - "logs:DeleteResourcePolicy": {}, - "logs:DescribeAccountPolicies": {}, - "logs:DescribeDeliveries": {}, - "logs:DescribeDeliveryDestinations": {}, - "logs:DescribeDeliverySources": {}, - "logs:DescribeDestinations": {}, - "logs:DescribeExportTasks": {}, - "logs:DescribeLogGroups": {}, - "logs:DescribeQueries": {}, - "logs:DescribeQueryDefinitions": {}, - "logs:DescribeResourcePolicies": {}, - "logs:GetLogDelivery": {}, - "logs:Link": {}, - "logs:ListLogDeliveries": {}, - "logs:PutAccountPolicy": {}, - "logs:PutQueryDefinition": {}, - "logs:PutResourcePolicy": {}, - "logs:StopLiveTail": {}, - "logs:StopQuery": {}, - "logs:TestMetricFilter": {}, - "logs:UpdateLogDelivery": {}, - "lookoutequipment:DescribeDataIngestionJob": {}, - "lookoutequipment:ListDatasets": {}, - "lookoutequipment:ListInferenceSchedulers": {}, - "lookoutequipment:ListModels": {}, - "lookoutequipment:ListRetrainingSchedulers": {}, - "lookoutmetrics:GetSampleData": {}, - "lookoutmetrics:ListAnomalyDetectors": {}, - "lookoutvision:CreateDataset": {}, - "lookoutvision:DeleteDataset": {}, - "lookoutvision:DescribeDataset": {}, - "lookoutvision:DescribeModelPackagingJob": {}, - "lookoutvision:DescribeTrialDetection": {}, - "lookoutvision:ListDatasetEntries": {}, - "lookoutvision:ListModelPackagingJobs": {}, - "lookoutvision:ListModels": {}, - "lookoutvision:ListProjects": {}, - "lookoutvision:ListTrialDetections": {}, - "lookoutvision:StartTrialDetection": {}, - "lookoutvision:UpdateDatasetEntries": {}, - "m2:CreateApplication": {}, - "m2:CreateEnvironment": {}, - "m2:GetSignedBluinsightsUrl": {}, - "m2:ListApplications": {}, - "m2:ListEngineVersions": {}, - "m2:ListEnvironments": {}, - "m2:ListTagsForResource": {}, - "machinelearning:DescribeBatchPredictions": {}, - "machinelearning:DescribeDataSources": {}, - "machinelearning:DescribeEvaluations": {}, - "machinelearning:DescribeMLModels": {}, - "macie2:AcceptInvitation": {}, - "macie2:CreateAllowList": {}, - "macie2:CreateInvitations": {}, - "macie2:CreateSampleFindings": {}, - "macie2:DeclineInvitations": {}, - "macie2:DeleteInvitations": {}, - "macie2:DescribeBuckets": {}, - "macie2:DescribeOrganizationConfiguration": {}, - "macie2:DisableMacie": {}, - "macie2:DisableOrganizationAdminAccount": {}, - "macie2:DisassociateFromAdministratorAccount": {}, - "macie2:DisassociateFromMasterAccount": {}, - "macie2:EnableMacie": {}, - "macie2:EnableOrganizationAdminAccount": {}, - "macie2:GetAdministratorAccount": {}, - "macie2:GetAutomatedDiscoveryConfiguration": {}, - "macie2:GetBucketStatistics": {}, - "macie2:GetClassificationExportConfiguration": {}, - "macie2:GetClassificationScope": {}, - "macie2:GetFindingStatistics": {}, - "macie2:GetFindings": {}, - "macie2:GetFindingsPublicationConfiguration": {}, - "macie2:GetInvitationsCount": {}, - "macie2:GetMacieSession": {}, - "macie2:GetMasterAccount": {}, - "macie2:GetResourceProfile": {}, - "macie2:GetRevealConfiguration": {}, - "macie2:GetSensitiveDataOccurrences": {}, - "macie2:GetSensitiveDataOccurrencesAvailability": {}, - "macie2:GetSensitivityInspectionTemplate": {}, - "macie2:GetUsageStatistics": {}, - "macie2:GetUsageTotals": {}, - "macie2:ListAllowLists": {}, - "macie2:ListClassificationJobs": {}, - "macie2:ListClassificationScopes": {}, - "macie2:ListCustomDataIdentifiers": {}, - "macie2:ListFindings": {}, - "macie2:ListFindingsFilters": {}, - "macie2:ListInvitations": {}, - "macie2:ListManagedDataIdentifiers": {}, - "macie2:ListMembers": {}, - "macie2:ListOrganizationAdminAccounts": {}, - "macie2:ListResourceProfileArtifacts": {}, - "macie2:ListResourceProfileDetections": {}, - "macie2:ListSensitivityInspectionTemplates": {}, - "macie2:PutClassificationExportConfiguration": {}, - "macie2:PutFindingsPublicationConfiguration": {}, - "macie2:SearchResources": {}, - "macie2:TestCustomDataIdentifier": {}, - "macie2:UpdateAutomatedDiscoveryConfiguration": {}, - "macie2:UpdateClassificationScope": {}, - "macie2:UpdateMacieSession": {}, - "macie2:UpdateMemberSession": {}, - "macie2:UpdateOrganizationConfiguration": {}, - "macie2:UpdateResourceProfile": {}, - "macie2:UpdateResourceProfileDetections": {}, - "macie2:UpdateRevealConfiguration": {}, - "macie2:UpdateSensitivityInspectionTemplate": {}, - "managedblockchain-query:BatchGetTokenBalance": {}, - "managedblockchain-query:GetAssetContract": {}, - "managedblockchain-query:GetTokenBalance": {}, - "managedblockchain-query:GetTransaction": {}, - "managedblockchain-query:ListAssetContracts": {}, - "managedblockchain-query:ListTokenBalances": {}, - "managedblockchain-query:ListTransactionEvents": {}, - "managedblockchain-query:ListTransactions": {}, - "managedblockchain:CreateAccessor": {}, - "managedblockchain:CreateNetwork": {}, - "managedblockchain:GET": {}, - "managedblockchain:Invoke": {}, - "managedblockchain:InvokeRpcBitcoinMainnet": {}, - "managedblockchain:InvokeRpcBitcoinTestnet": {}, - "managedblockchain:InvokeRpcPolygonMainnet": {}, - "managedblockchain:InvokeRpcPolygonMumbaiTestnet": {}, - "managedblockchain:ListAccessors": {}, - "managedblockchain:ListInvitations": {}, - "managedblockchain:ListNetworks": {}, - "managedblockchain:POST": {}, - "mechanicalturk:AcceptQualificationRequest": {}, - "mechanicalturk:ApproveAssignment": {}, - "mechanicalturk:AssociateQualificationWithWorker": {}, - "mechanicalturk:CreateAdditionalAssignmentsForHIT": {}, - "mechanicalturk:CreateHIT": {}, - "mechanicalturk:CreateHITType": {}, - "mechanicalturk:CreateHITWithHITType": {}, - "mechanicalturk:CreateQualificationType": {}, - "mechanicalturk:CreateWorkerBlock": {}, - "mechanicalturk:DeleteHIT": {}, - "mechanicalturk:DeleteQualificationType": {}, - "mechanicalturk:DeleteWorkerBlock": {}, - "mechanicalturk:DisassociateQualificationFromWorker": {}, - "mechanicalturk:GetAccountBalance": {}, - "mechanicalturk:GetAssignment": {}, - "mechanicalturk:GetFileUploadURL": {}, - "mechanicalturk:GetHIT": {}, - "mechanicalturk:GetQualificationScore": {}, - "mechanicalturk:GetQualificationType": {}, - "mechanicalturk:ListAssignmentsForHIT": {}, - "mechanicalturk:ListBonusPayments": {}, - "mechanicalturk:ListHITs": {}, - "mechanicalturk:ListHITsForQualificationType": {}, - "mechanicalturk:ListQualificationRequests": {}, - "mechanicalturk:ListQualificationTypes": {}, - "mechanicalturk:ListReviewPolicyResultsForHIT": {}, - "mechanicalturk:ListReviewableHITs": {}, - "mechanicalturk:ListWorkerBlocks": {}, - "mechanicalturk:ListWorkersWithQualificationType": {}, - "mechanicalturk:NotifyWorkers": {}, - "mechanicalturk:RejectAssignment": {}, - "mechanicalturk:RejectQualificationRequest": {}, - "mechanicalturk:SendBonus": {}, - "mechanicalturk:SendTestEventNotification": {}, - "mechanicalturk:UpdateExpirationForHIT": {}, - "mechanicalturk:UpdateHITReviewStatus": {}, - "mechanicalturk:UpdateHITTypeOfHIT": {}, - "mechanicalturk:UpdateNotificationSettings": {}, - "mechanicalturk:UpdateQualificationType": {}, - "mediaconnect:AddFlowMediaStreams": {}, - "mediaconnect:AddFlowOutputs": {}, - "mediaconnect:AddFlowSources": {}, - "mediaconnect:AddFlowVpcInterfaces": {}, - "mediaconnect:CreateFlow": {}, - "mediaconnect:DeleteFlow": {}, - "mediaconnect:DescribeFlow": {}, - "mediaconnect:DescribeFlowSourceMetadata": {}, - "mediaconnect:DescribeOffering": {}, - "mediaconnect:DescribeReservation": {}, - "mediaconnect:DiscoverGatewayPollEndpoint": {}, - "mediaconnect:GrantFlowEntitlements": {}, - "mediaconnect:ListEntitlements": {}, - "mediaconnect:ListFlows": {}, - "mediaconnect:ListGateways": {}, - "mediaconnect:ListOfferings": {}, - "mediaconnect:ListReservations": {}, - "mediaconnect:ListTagsForResource": {}, - "mediaconnect:PollGateway": {}, - "mediaconnect:PurchaseOffering": {}, - "mediaconnect:RemoveFlowMediaStream": {}, - "mediaconnect:RemoveFlowOutput": {}, - "mediaconnect:RemoveFlowSource": {}, - "mediaconnect:RemoveFlowVpcInterface": {}, - "mediaconnect:RevokeFlowEntitlement": {}, - "mediaconnect:StartFlow": {}, - "mediaconnect:StopFlow": {}, - "mediaconnect:SubmitGatewayStateChange": {}, - "mediaconnect:TagResource": {}, - "mediaconnect:UntagResource": {}, - "mediaconnect:UpdateFlow": {}, - "mediaconnect:UpdateFlowEntitlement": {}, - "mediaconnect:UpdateFlowMediaStream": {}, - "mediaconnect:UpdateFlowOutput": {}, - "mediaconnect:UpdateFlowSource": {}, - "mediaconvert:AssociateCertificate": {}, - "mediaconvert:CreatePreset": {}, - "mediaconvert:CreateQueue": {}, - "mediaconvert:DeletePolicy": {}, - "mediaconvert:DescribeEndpoints": {}, - "mediaconvert:DisassociateCertificate": {}, - "mediaconvert:GetPolicy": {}, - "mediaconvert:ListJobTemplates": {}, - "mediaconvert:ListPresets": {}, - "mediaconvert:ListQueues": {}, - "mediaconvert:PutPolicy": {}, - "mediaimport:CreateDatabaseBinarySnapshot": {}, - "medialive:BatchDelete": {}, - "medialive:BatchStart": {}, - "medialive:BatchStop": {}, - "medialive:DescribeAccountConfiguration": {}, - "medialive:ListChannels": {}, - "medialive:ListInputDeviceTransfers": {}, - "medialive:ListInputDevices": {}, - "medialive:ListInputSecurityGroups": {}, - "medialive:ListInputs": {}, - "medialive:ListMultiplexPrograms": {}, - "medialive:ListMultiplexes": {}, - "medialive:ListOfferings": {}, - "medialive:ListReservations": {}, - "medialive:UpdateAccountConfiguration": {}, - "mediapackage-vod:CreateAsset": {}, - "mediapackage-vod:CreatePackagingConfiguration": {}, - "mediapackage-vod:CreatePackagingGroup": {}, - "mediapackage-vod:ListAssets": {}, - "mediapackage-vod:ListPackagingConfigurations": {}, - "mediapackage-vod:ListPackagingGroups": {}, - "mediapackage:CreateChannel": {}, - "mediapackage:CreateHarvestJob": {}, - "mediapackage:CreateOriginEndpoint": {}, - "mediapackage:ListChannels": {}, - "mediapackage:ListHarvestJobs": {}, - "mediapackage:ListOriginEndpoints": {}, - "mediapackagev2:ListChannelGroups": {}, - "mediastore:CreateContainer": {}, - "mediastore:ListContainers": {}, - "mediatailor:CreateChannel": {}, - "mediatailor:CreateLiveSource": {}, - "mediatailor:CreateProgram": {}, - "mediatailor:CreateSourceLocation": {}, - "mediatailor:CreateVodSource": {}, - "mediatailor:ListAlerts": {}, - "mediatailor:ListChannels": {}, - "mediatailor:ListLiveSources": {}, - "mediatailor:ListPlaybackConfigurations": {}, - "mediatailor:ListSourceLocations": {}, - "mediatailor:ListVodSources": {}, - "mediatailor:PutPlaybackConfiguration": {}, - "medical-imaging:CreateDatastore": {}, - "medical-imaging:ListDatastores": {}, - "memorydb:CreateParameterGroup": {}, - "memorydb:CreateSubnetGroup": {}, - "memorydb:CreateUser": {}, - "memorydb:DescribeEngineVersions": {}, - "memorydb:DescribeEvents": {}, - "memorydb:DescribeReservedNodesOfferings": {}, - "memorydb:DescribeServiceUpdates": {}, - "mgh:CreateHomeRegionControl": {}, - "mgh:DeleteHomeRegionControl": {}, - "mgh:DescribeApplicationState": {}, - "mgh:DescribeHomeRegionControls": {}, - "mgh:GetHomeRegion": {}, - "mgh:ListApplicationStates": {}, - "mgh:ListMigrationTasks": {}, - "mgh:ListProgressUpdateStreams": {}, - "mgh:NotifyApplicationState": {}, - "mgn:BatchDeleteSnapshotRequestForMgn": {}, - "mgn:CreateApplication": {}, - "mgn:CreateConnector": {}, - "mgn:CreateLaunchConfigurationTemplate": {}, - "mgn:CreateReplicationConfigurationTemplate": {}, - "mgn:CreateVcenterClientForMgn": {}, - "mgn:CreateWave": {}, - "mgn:DescribeJobs": {}, - "mgn:DescribeLaunchConfigurationTemplates": {}, - "mgn:DescribeReplicationConfigurationTemplates": {}, - "mgn:DescribeReplicationServerAssociationsForMgn": {}, - "mgn:DescribeSnapshotRequestsForMgn": {}, - "mgn:DescribeSourceServers": {}, - "mgn:DescribeVcenterClients": {}, - "mgn:GetAgentInstallationAssetsForMgn": {}, - "mgn:GetChannelCommandsForMgn": {}, - "mgn:InitializeService": {}, - "mgn:ListApplications": {}, - "mgn:ListConnectors": {}, - "mgn:ListExports": {}, - "mgn:ListImports": {}, - "mgn:ListManagedAccounts": {}, - "mgn:ListTagsForResource": {}, - "mgn:ListWaves": {}, - "mgn:RegisterAgentForMgn": {}, - "mgn:SendChannelCommandResultForMgn": {}, - "mgn:SendClientLogsForMgn": {}, - "mgn:SendClientMetricsForMgn": {}, - "mgn:StartExport": {}, - "mgn:StartImport": {}, - "mgn:VerifyClientRoleForMgn": {}, - "migrationhub-orchestrator:CreateWorkflow": {}, - "migrationhub-orchestrator:GetMessage": {}, - "migrationhub-orchestrator:GetTemplate": {}, - "migrationhub-orchestrator:GetTemplateStep": {}, - "migrationhub-orchestrator:GetTemplateStepGroup": {}, - "migrationhub-orchestrator:ListPlugins": {}, - "migrationhub-orchestrator:ListTemplateStepGroups": {}, - "migrationhub-orchestrator:ListTemplateSteps": {}, - "migrationhub-orchestrator:ListTemplates": {}, - "migrationhub-orchestrator:ListWorkflows": {}, - "migrationhub-orchestrator:RegisterPlugin": {}, - "migrationhub-orchestrator:SendMessage": {}, - "migrationhub-strategy:GetAntiPattern": {}, - "migrationhub-strategy:GetApplicationComponentDetails": {}, - "migrationhub-strategy:GetApplicationComponentStrategies": {}, - "migrationhub-strategy:GetAssessment": {}, - "migrationhub-strategy:GetImportFileTask": {}, - "migrationhub-strategy:GetLatestAssessmentId": {}, - "migrationhub-strategy:GetMessage": {}, - "migrationhub-strategy:GetPortfolioPreferences": {}, - "migrationhub-strategy:GetPortfolioSummary": {}, - "migrationhub-strategy:GetRecommendationReportDetails": {}, - "migrationhub-strategy:GetServerDetails": {}, - "migrationhub-strategy:GetServerStrategies": {}, - "migrationhub-strategy:ListAnalyzableServers": {}, - "migrationhub-strategy:ListAntiPatterns": {}, - "migrationhub-strategy:ListApplicationComponents": {}, - "migrationhub-strategy:ListCollectors": {}, - "migrationhub-strategy:ListImportFileTask": {}, - "migrationhub-strategy:ListJarArtifacts": {}, - "migrationhub-strategy:ListServers": {}, - "migrationhub-strategy:PutPortfolioPreferences": {}, - "migrationhub-strategy:RegisterCollector": {}, - "migrationhub-strategy:SendMessage": {}, - "migrationhub-strategy:StartAssessment": {}, - "migrationhub-strategy:StartImportFileTask": {}, - "migrationhub-strategy:StartRecommendationReportGeneration": {}, - "migrationhub-strategy:StopAssessment": {}, - "migrationhub-strategy:UpdateApplicationComponentConfig": {}, - "migrationhub-strategy:UpdateCollectorConfiguration": {}, - "migrationhub-strategy:UpdateServerConfig": {}, - "mobileanalytics:PutEvents": {}, - "monitron:CreateProject": {}, - "monitron:ListProjects": {}, - "mq:CreateBroker": {}, - "mq:CreateConfiguration": {}, - "mq:DescribeBrokerEngineTypes": {}, - "mq:DescribeBrokerInstanceOptions": {}, - "mq:ListBrokers": {}, - "mq:ListConfigurations": {}, - "network-firewall:ListRuleGroups": {}, - "networkmanager-chat:CancelMessageResponse": {}, - "networkmanager-chat:CreateConversation": {}, - "networkmanager-chat:DeleteConversation": {}, - "networkmanager-chat:ListConversationMessages": {}, - "networkmanager-chat:ListConversations": {}, - "networkmanager-chat:NotifyConversationIsActive": {}, - "networkmanager-chat:SendConversationMessage": {}, - "networkmanager:CreateGlobalNetwork": {}, - "networkmanager:ListCoreNetworks": {}, - "networkmanager:ListOrganizationServiceAccessStatus": {}, - "networkmanager:ListPeerings": {}, - "networkmanager:StartOrganizationServiceAccessUpdate": {}, - "networkmonitor:CreateProbe": {}, - "networkmonitor:ListMonitors": {}, - "nimble:GetFeatureMap": {}, - "nimble:ListStudios": {}, - "notifications-contacts:CreateEmailContact": {}, - "notifications-contacts:ListEmailContacts": {}, - "notifications-contacts:ListTagsForResource": {}, - "notifications:CreateEventRule": {}, - "notifications:CreateNotificationConfiguration": {}, - "notifications:DeregisterNotificationHub": {}, - "notifications:ListChannels": {}, - "notifications:ListEventRules": {}, - "notifications:ListNotificationConfigurations": {}, - "notifications:ListNotificationEvents": {}, - "notifications:ListNotificationHubs": {}, - "notifications:ListTagsForResource": {}, - "notifications:RegisterNotificationHub": {}, - "oam:CreateSink": {}, - "oam:ListLinks": {}, - "oam:ListSinks": {}, - "omics:AcceptShare": {}, - "omics:CreateAnnotationStore": {}, - "omics:CreateReferenceStore": {}, - "omics:CreateRunGroup": {}, - "omics:CreateSequenceStore": {}, - "omics:CreateShare": {}, - "omics:CreateVariantStore": {}, - "omics:CreateWorkflow": {}, - "omics:DeleteShare": {}, - "omics:GetShare": {}, - "omics:ListAnnotationImportJobs": {}, - "omics:ListAnnotationStores": {}, - "omics:ListReferenceStores": {}, - "omics:ListRunGroups": {}, - "omics:ListRuns": {}, - "omics:ListSequenceStores": {}, - "omics:ListShares": {}, - "omics:ListTagsForResource": {}, - "omics:ListVariantImportJobs": {}, - "omics:ListVariantStores": {}, - "omics:ListWorkflows": {}, - "omics:StartAnnotationImportJob": {}, - "omics:StartRun": {}, - "omics:StartVariantImportJob": {}, - "one:CreateDeviceConfigurationTemplate": {}, - "one:CreateDeviceInstance": {}, - "one:CreateSite": {}, - "one:ListDeviceConfigurationTemplates": {}, - "one:ListDeviceInstances": {}, - "one:ListSites": {}, - "one:ListUsers": {}, - "opsworks-cm:AssociateNode": {}, - "opsworks-cm:CreateBackup": {}, - "opsworks-cm:CreateServer": {}, - "opsworks-cm:DeleteBackup": {}, - "opsworks-cm:DeleteServer": {}, - "opsworks-cm:DescribeAccountAttributes": {}, - "opsworks-cm:DescribeBackups": {}, - "opsworks-cm:DescribeEvents": {}, - "opsworks-cm:DescribeNodeAssociationStatus": {}, - "opsworks-cm:DescribeServers": {}, - "opsworks-cm:DisassociateNode": {}, - "opsworks-cm:ExportServerEngineAttribute": {}, - "opsworks-cm:ListTagsForResource": {}, - "opsworks-cm:RestoreServer": {}, - "opsworks-cm:StartMaintenance": {}, - "opsworks-cm:TagResource": {}, - "opsworks-cm:UntagResource": {}, - "opsworks-cm:UpdateServer": {}, - "opsworks-cm:UpdateServerEngineAttributes": {}, - "opsworks:CreateStack": {}, - "opsworks:CreateUserProfile": {}, - "opsworks:DeleteUserProfile": {}, - "opsworks:DescribeMyUserProfile": {}, - "opsworks:DescribeOperatingSystems": {}, - "opsworks:DescribeUserProfiles": {}, - "opsworks:UpdateMyUserProfile": {}, - "opsworks:UpdateUserProfile": {}, - "organizations:CreateAccount": {}, - "organizations:CreateGovCloudAccount": {}, - "organizations:CreateOrganization": {}, - "organizations:CreatePolicy": {}, - "organizations:DeleteOrganization": {}, - "organizations:DeleteResourcePolicy": {}, - "organizations:DescribeCreateAccountStatus": {}, - "organizations:DescribeOrganization": {}, - "organizations:DescribeResourcePolicy": {}, - "organizations:DisableAWSServiceAccess": {}, - "organizations:EnableAWSServiceAccess": {}, - "organizations:EnableAllFeatures": {}, - "organizations:LeaveOrganization": {}, - "organizations:ListAWSServiceAccessForOrganization": {}, - "organizations:ListAccounts": {}, - "organizations:ListCreateAccountStatus": {}, - "organizations:ListDelegatedAdministrators": {}, - "organizations:ListHandshakesForAccount": {}, - "organizations:ListHandshakesForOrganization": {}, - "organizations:ListPolicies": {}, - "organizations:ListRoots": {}, - "osis:CreatePipeline": {}, - "osis:ListPipelineBlueprints": {}, - "osis:ListPipelines": {}, - "osis:ValidatePipeline": {}, - "outposts:CancelOrder": {}, - "outposts:CreatePrivateConnectivityConfig": {}, - "outposts:CreateSite": {}, - "outposts:GetCatalogItem": {}, - "outposts:GetConnection": {}, - "outposts:GetOrder": {}, - "outposts:GetPrivateConnectivityConfig": {}, - "outposts:ListAssets": {}, - "outposts:ListCatalogItems": {}, - "outposts:ListOrders": {}, - "outposts:ListOutposts": {}, - "outposts:ListSites": {}, - "outposts:ListTagsForResource": {}, - "outposts:StartConnection": {}, - "panorama:CreateApplicationInstance": {}, - "panorama:CreateJobForDevices": {}, - "panorama:CreateNodeFromTemplateJob": {}, - "panorama:CreatePackage": {}, - "panorama:CreatePackageImportJob": {}, - "panorama:DescribeDeviceJob": {}, - "panorama:DescribeNode": {}, - "panorama:DescribeNodeFromTemplateJob": {}, - "panorama:DescribePackageImportJob": {}, - "panorama:DescribeSoftware": {}, - "panorama:GetWebSocketURL": {}, - "panorama:ListDevices": {}, - "panorama:ListNodeFromTemplateJobs": {}, - "panorama:ListNodes": {}, - "panorama:ListPackageImportJobs": {}, - "panorama:ListPackages": {}, - "panorama:ProvisionDevice": {}, - "partnercentral-account-management:AssociatePartnerAccount": {}, - "partnercentral-account-management:AssociatePartnerUser": {}, - "partnercentral-account-management:DisassociatePartnerUser": {}, - "payment-cryptography:CreateKey": {}, - "payment-cryptography:DecryptData": {}, - "payment-cryptography:EncryptData": {}, - "payment-cryptography:GenerateCardValidationData": {}, - "payment-cryptography:GenerateMac": {}, - "payment-cryptography:GeneratePinData": {}, - "payment-cryptography:GetParametersForExport": {}, - "payment-cryptography:GetParametersForImport": {}, - "payment-cryptography:ImportKey": {}, - "payment-cryptography:ListAliases": {}, - "payment-cryptography:ListKeys": {}, - "payment-cryptography:ReEncryptData": {}, - "payment-cryptography:TranslatePinData": {}, - "payment-cryptography:VerifyAuthRequestCryptogram": {}, - "payment-cryptography:VerifyCardValidationData": {}, - "payment-cryptography:VerifyMac": {}, - "payment-cryptography:VerifyPinData": {}, - "payments:CreatePaymentInstrument": {}, - "payments:DeletePaymentInstrument": {}, - "payments:GetPaymentInstrument": {}, - "payments:GetPaymentStatus": {}, - "payments:ListPaymentPreferences": {}, - "payments:MakePayment": {}, - "payments:UpdatePaymentPreferences": {}, - "pca-connector-ad:CreateConnector": {}, - "pca-connector-ad:CreateDirectoryRegistration": {}, - "pca-connector-ad:ListConnectors": {}, - "pca-connector-ad:ListDirectoryRegistrations": {}, - "pca-connector-ad:ListTagsForResource": {}, - "personalize:ListBatchInferenceJobs": {}, - "personalize:ListBatchSegmentJobs": {}, - "personalize:ListCampaigns": {}, - "personalize:ListDataInsightsJobs": {}, - "personalize:ListDatasetExportJobs": {}, - "personalize:ListDatasetGroups": {}, - "personalize:ListDatasetImportJobs": {}, - "personalize:ListDatasets": {}, - "personalize:ListEventTrackers": {}, - "personalize:ListFilters": {}, - "personalize:ListMetricAttributionMetrics": {}, - "personalize:ListMetricAttributions": {}, - "personalize:ListRecipes": {}, - "personalize:ListRecommenders": {}, - "personalize:ListSchemas": {}, - "personalize:ListSolutionVersions": {}, - "personalize:ListSolutions": {}, - "personalize:ListTagsForResource": {}, - "personalize:PutActionInteractions": {}, - "personalize:PutEvents": {}, - "personalize:TagResource": {}, - "personalize:UntagResource": {}, - "pipes:ListPipes": {}, - "polly:DescribeVoices": {}, - "polly:GetSpeechSynthesisTask": {}, - "polly:ListLexicons": {}, - "polly:ListSpeechSynthesisTasks": {}, - "pricing:DescribeServices": {}, - "pricing:GetAttributeValues": {}, - "pricing:GetPriceListFileUrl": {}, - "pricing:GetProducts": {}, - "pricing:ListPriceLists": {}, - "private-networks:ListNetworks": {}, - "private-networks:ListTagsForResource": {}, - "private-networks:Ping": {}, - "profile:GetProfileObjectTypeTemplate": {}, - "profile:ListAccountIntegrations": {}, - "profile:ListDomains": {}, - "profile:ListProfileObjectTypeTemplates": {}, - "proton:CreateEnvironmentAccountConnection": {}, - "proton:CreateServiceSyncConfig": {}, - "proton:CreateTemplateSyncConfig": {}, - "proton:DeleteAccountRoles": {}, - "proton:DeleteServiceSyncConfig": {}, - "proton:DeleteTemplateSyncConfig": {}, - "proton:GetAccountRoles": {}, - "proton:GetAccountSettings": {}, - "proton:GetRepositorySyncStatus": {}, - "proton:GetResourceTemplateVersionStatusCounts": {}, - "proton:GetResourcesSummary": {}, - "proton:GetServiceInstanceSyncStatus": {}, - "proton:GetServiceSyncBlockerSummary": {}, - "proton:GetServiceSyncConfig": {}, - "proton:GetTemplateSyncConfig": {}, - "proton:GetTemplateSyncStatus": {}, - "proton:ListDeployments": {}, - "proton:ListEnvironmentAccountConnections": {}, - "proton:ListEnvironmentTemplates": {}, - "proton:ListEnvironments": {}, - "proton:ListRepositories": {}, - "proton:ListRepositorySyncDefinitions": {}, - "proton:ListServiceInstances": {}, - "proton:ListServiceTemplates": {}, - "proton:ListServices": {}, - "proton:UpdateAccountRoles": {}, - "proton:UpdateAccountSettings": {}, - "proton:UpdateServiceSyncBlocker": {}, - "proton:UpdateServiceSyncConfig": {}, - "proton:UpdateTemplateSyncConfig": {}, - "purchase-orders:GetConsoleActionSetEnforced": {}, - "purchase-orders:ListPurchaseOrders": {}, - "purchase-orders:UpdateConsoleActionSetEnforced": {}, - "q:GetConversation": {}, - "q:GetTroubleshootingResults": {}, - "q:SendMessage": {}, - "q:StartConversation": {}, - "q:StartTroubleshootingAnalysis": {}, - "q:StartTroubleshootingResolutionExplanation": {}, - "qbusiness:AddUserLicenses": {}, - "qbusiness:CreateApplication": {}, - "qbusiness:CreateLicense": {}, - "qbusiness:ListApplications": {}, - "qbusiness:ListUserLicenses": {}, - "qbusiness:RemoveUserLicenses": {}, - "qldb:ListJournalS3Exports": {}, - "qldb:ListLedgers": {}, - "quicksight:AccountConfigurations": {}, - "quicksight:CreateAccountCustomization": {}, - "quicksight:CreateAccountSubscription": {}, - "quicksight:CreateCustomPermissions": {}, - "quicksight:CreateDataSource": {}, - "quicksight:CreateRoleMembership": {}, - "quicksight:CreateVPCConnection": {}, - "quicksight:DeleteCustomPermissions": {}, - "quicksight:DeleteIdentityPropagationConfig": {}, - "quicksight:DeleteRoleCustomPermission": {}, - "quicksight:DeleteRoleMembership": {}, - "quicksight:DescribeAccountSettings": {}, - "quicksight:DescribeCustomPermissions": {}, - "quicksight:DescribeIpRestriction": {}, - "quicksight:DescribeRoleCustomPermission": {}, - "quicksight:GetAnonymousUserEmbedUrl": {}, - "quicksight:GetGroupMapping": {}, - "quicksight:GetSessionEmbedUrl": {}, - "quicksight:ListCustomPermissions": {}, - "quicksight:ListCustomerManagedKeys": {}, - "quicksight:ListDataSets": {}, - "quicksight:ListDataSources": {}, - "quicksight:ListIdentityPropagationConfigs": {}, - "quicksight:ListIngestions": {}, - "quicksight:ListKMSKeysForUser": {}, - "quicksight:ListNamespaces": {}, - "quicksight:ListRefreshSchedules": {}, - "quicksight:ListRoleMemberships": {}, - "quicksight:ListTopicRefreshSchedules": {}, - "quicksight:ListTopics": {}, - "quicksight:ListVPCConnections": {}, - "quicksight:RegisterCustomerManagedKey": {}, - "quicksight:RemoveCustomerManagedKey": {}, - "quicksight:ScopeDownPolicy": {}, - "quicksight:SearchDirectoryGroups": {}, - "quicksight:SetGroupMapping": {}, - "quicksight:Subscribe": {}, - "quicksight:Unsubscribe": {}, - "quicksight:UpdateAccountSettings": {}, - "quicksight:UpdateCustomPermissions": {}, - "quicksight:UpdateIdentityPropagationConfig": {}, - "quicksight:UpdateIpRestriction": {}, - "quicksight:UpdatePublicSharingSettings": {}, - "quicksight:UpdateResourcePermissions": {}, - "quicksight:UpdateRoleCustomPermission": {}, - "ram:CreatePermission": {}, - "ram:CreateResourceShare": {}, - "ram:EnableSharingWithAwsOrganization": {}, - "ram:GetResourcePolicies": {}, - "ram:GetResourceShareAssociations": {}, - "ram:GetResourceShareInvitations": {}, - "ram:GetResourceShares": {}, - "ram:ListPermissionVersions": {}, - "ram:ListPermissions": {}, - "ram:ListPrincipals": {}, - "ram:ListReplacePermissionAssociationsWork": {}, - "ram:ListResourceTypes": {}, - "ram:ListResources": {}, - "rbin:ListRules": {}, - "rds:CancelExportTask": {}, - "rds:CreateDBProxy": {}, - "rds:CrossRegionCommunication": {}, - "rds:DescribeAccountAttributes": {}, - "rds:DescribeCertificates": {}, - "rds:DescribeDBEngineVersions": {}, - "rds:DescribeDBRecommendations": {}, - "rds:DescribeEngineDefaultClusterParameters": {}, - "rds:DescribeEngineDefaultParameters": {}, - "rds:DescribeEventCategories": {}, - "rds:DescribeEvents": {}, - "rds:DescribeExportTasks": {}, - "rds:DescribeOrderableDBInstanceOptions": {}, - "rds:DescribeRecommendationGroups": {}, - "rds:DescribeRecommendations": {}, - "rds:DescribeReservedDBInstancesOfferings": {}, - "rds:DescribeSourceRegions": {}, - "rds:ModifyCertificates": {}, - "rds:ModifyDBRecommendation": {}, - "rds:ModifyRecommendation": {}, - "rds:StartExportTask": {}, - "redshift-data:CancelStatement": {}, - "redshift-data:DescribeStatement": {}, - "redshift-data:GetStatementResult": {}, - "redshift-data:ListStatements": {}, - "redshift-serverless:CreateUsageLimit": {}, - "redshift-serverless:DeleteResourcePolicy": {}, - "redshift-serverless:DeleteScheduledAction": {}, - "redshift-serverless:DeleteSnapshotCopyConfiguration": {}, - "redshift-serverless:DeleteUsageLimit": {}, - "redshift-serverless:GetResourcePolicy": {}, - "redshift-serverless:GetScheduledAction": {}, - "redshift-serverless:GetTableRestoreStatus": {}, - "redshift-serverless:GetUsageLimit": {}, - "redshift-serverless:ListCustomDomainAssociations": {}, - "redshift-serverless:ListNamespaces": {}, - "redshift-serverless:ListScheduledActions": {}, - "redshift-serverless:ListTableRestoreStatus": {}, - "redshift-serverless:ListUsageLimits": {}, - "redshift-serverless:ListWorkgroups": {}, - "redshift-serverless:PutResourcePolicy": {}, - "redshift-serverless:UpdateScheduledAction": {}, - "redshift-serverless:UpdateSnapshotCopyConfiguration": {}, - "redshift-serverless:UpdateUsageLimit": {}, - "redshift-serverless:span": {}, - "redshift:AcceptReservedNodeExchange": {}, - "redshift:AddPartner": {}, - "redshift:AuthorizeEndpointAccess": {}, - "redshift:CancelQuery": {}, - "redshift:CancelQuerySession": {}, - "redshift:CreateAuthenticationProfile": {}, - "redshift:CreateEndpointAccess": {}, - "redshift:CreateRedshiftIdcApplication": {}, - "redshift:CreateSavedQuery": {}, - "redshift:CreateScheduledAction": {}, - "redshift:DeleteAuthenticationProfile": {}, - "redshift:DeleteEndpointAccess": {}, - "redshift:DeletePartner": {}, - "redshift:DeleteSavedQueries": {}, - "redshift:DeleteScheduledAction": {}, - "redshift:DescribeAccountAttributes": {}, - "redshift:DescribeAuthenticationProfiles": {}, - "redshift:DescribeClusterDbRevisions": {}, - "redshift:DescribeClusterParameterGroups": {}, - "redshift:DescribeClusterSecurityGroups": {}, - "redshift:DescribeClusterSnapshots": {}, - "redshift:DescribeClusterSubnetGroups": {}, - "redshift:DescribeClusterTracks": {}, - "redshift:DescribeClusterVersions": {}, - "redshift:DescribeClusters": {}, - "redshift:DescribeCustomDomainAssociations": {}, - "redshift:DescribeDataShares": {}, - "redshift:DescribeDataSharesForConsumer": {}, - "redshift:DescribeDataSharesForProducer": {}, - "redshift:DescribeDefaultClusterParameters": {}, - "redshift:DescribeEndpointAccess": {}, - "redshift:DescribeEndpointAuthorization": {}, - "redshift:DescribeEventCategories": {}, - "redshift:DescribeEventSubscriptions": {}, - "redshift:DescribeEvents": {}, - "redshift:DescribeHsmClientCertificates": {}, - "redshift:DescribeHsmConfigurations": {}, - "redshift:DescribeInboundIntegrations": {}, - "redshift:DescribeNodeConfigurationOptions": {}, - "redshift:DescribeOrderableClusterOptions": {}, - "redshift:DescribePartners": {}, - "redshift:DescribeQuery": {}, - "redshift:DescribeReservedNodeExchangeStatus": {}, - "redshift:DescribeReservedNodeOfferings": {}, - "redshift:DescribeReservedNodes": {}, - "redshift:DescribeSavedQueries": {}, - "redshift:DescribeScheduledActions": {}, - "redshift:DescribeSnapshotCopyGrants": {}, - "redshift:DescribeStorage": {}, - "redshift:DescribeTable": {}, - "redshift:DescribeTableRestoreStatus": {}, - "redshift:ExecuteQuery": {}, - "redshift:FetchResults": {}, - "redshift:GetReservedNodeExchangeConfigurationOptions": {}, - "redshift:GetReservedNodeExchangeOfferings": {}, - "redshift:ListDatabases": {}, - "redshift:ListRecommendations": {}, - "redshift:ListSavedQueries": {}, - "redshift:ListSchemas": {}, - "redshift:ListTables": {}, - "redshift:ModifyAuthenticationProfile": {}, - "redshift:ModifyClusterMaintenance": {}, - "redshift:ModifyEndpointAccess": {}, - "redshift:ModifySavedQuery": {}, - "redshift:ModifyScheduledAction": {}, - "redshift:PurchaseReservedNodeOffering": {}, - "redshift:RevokeEndpointAccess": {}, - "redshift:UpdatePartnerStatus": {}, - "redshift:ViewQueriesFromConsole": {}, - "redshift:ViewQueriesInConsole": {}, - "refactor-spaces:CreateApplication": {}, - "refactor-spaces:CreateEnvironment": {}, - "refactor-spaces:CreateRoute": {}, - "refactor-spaces:CreateService": {}, - "refactor-spaces:DeleteResourcePolicy": {}, - "refactor-spaces:GetResourcePolicy": {}, - "refactor-spaces:ListEnvironments": {}, - "refactor-spaces:ListTagsForResource": {}, - "refactor-spaces:PutResourcePolicy": {}, - "rekognition:CompareFaces": {}, - "rekognition:CreateFaceLivenessSession": {}, - "rekognition:DescribeProjects": {}, - "rekognition:DetectFaces": {}, - "rekognition:DetectLabels": {}, - "rekognition:DetectProtectiveEquipment": {}, - "rekognition:DetectText": {}, - "rekognition:GetCelebrityInfo": {}, - "rekognition:GetCelebrityRecognition": {}, - "rekognition:GetContentModeration": {}, - "rekognition:GetFaceDetection": {}, - "rekognition:GetFaceLivenessSessionResults": {}, - "rekognition:GetFaceSearch": {}, - "rekognition:GetLabelDetection": {}, - "rekognition:GetMediaAnalysisJob": {}, - "rekognition:GetPersonTracking": {}, - "rekognition:GetSegmentDetection": {}, - "rekognition:GetTextDetection": {}, - "rekognition:ListCollections": {}, - "rekognition:ListMediaAnalysisJobs": {}, - "rekognition:RecognizeCelebrities": {}, - "rekognition:StartCelebrityRecognition": {}, - "rekognition:StartContentModeration": {}, - "rekognition:StartFaceDetection": {}, - "rekognition:StartFaceLivenessSession": {}, - "rekognition:StartLabelDetection": {}, - "rekognition:StartPersonTracking": {}, - "rekognition:StartSegmentDetection": {}, - "rekognition:StartTextDetection": {}, - "repostspace:CreateSpace": {}, - "repostspace:ListSpaces": {}, - "resiliencehub:CreateApp": {}, - "resiliencehub:CreateResiliencyPolicy": {}, - "resiliencehub:ListAppAssessments": {}, - "resiliencehub:ListApps": {}, - "resiliencehub:ListResiliencyPolicies": {}, - "resiliencehub:ListSuggestedResiliencyPolicies": {}, - "resiliencehub:ListTagsForResource": {}, - "resource-explorer-2:BatchGetView": {}, - "resource-explorer-2:CreateIndex": {}, - "resource-explorer-2:CreateView": {}, - "resource-explorer-2:DisassociateDefaultView": {}, - "resource-explorer-2:GetAccountLevelServiceConfiguration": {}, - "resource-explorer-2:GetDefaultView": {}, - "resource-explorer-2:GetIndex": {}, - "resource-explorer-2:ListIndexes": {}, - "resource-explorer-2:ListIndexesForMembers": {}, - "resource-explorer-2:ListSupportedResourceTypes": {}, - "resource-explorer-2:ListViews": {}, - "resource-explorer:ListResourceTypes": {}, - "resource-explorer:ListResources": {}, - "resource-explorer:ListTags": {}, - "resource-groups:CreateGroup": {}, - "resource-groups:GetAccountSettings": {}, - "resource-groups:ListGroups": {}, - "resource-groups:SearchResources": {}, - "resource-groups:UpdateAccountSettings": {}, - "rhelkb:GetRhelURL": {}, - "robomaker:BatchDeleteWorlds": {}, - "robomaker:BatchDescribeSimulationJob": {}, - "robomaker:CreateDeploymentJob": {}, - "robomaker:CreateFleet": {}, - "robomaker:CreateRobot": {}, - "robomaker:CreateRobotApplication": {}, - "robomaker:CreateSimulationApplication": {}, - "robomaker:CreateSimulationJob": {}, - "robomaker:CreateWorldTemplate": {}, - "robomaker:ListDeploymentJobs": {}, - "robomaker:ListFleets": {}, - "robomaker:ListRobotApplications": {}, - "robomaker:ListRobots": {}, - "robomaker:ListSimulationApplications": {}, - "robomaker:ListSimulationJobBatches": {}, - "robomaker:ListSimulationJobs": {}, - "robomaker:ListWorldExportJobs": {}, - "robomaker:ListWorldGenerationJobs": {}, - "robomaker:ListWorldTemplates": {}, - "robomaker:ListWorlds": {}, - "robomaker:StartSimulationJobBatch": {}, - "rolesanywhere:CreateProfile": {}, - "rolesanywhere:CreateTrustAnchor": {}, - "rolesanywhere:ImportCrl": {}, - "rolesanywhere:ListCrls": {}, - "rolesanywhere:ListProfiles": {}, - "rolesanywhere:ListSubjects": {}, - "rolesanywhere:ListTagsForResource": {}, - "rolesanywhere:ListTrustAnchors": {}, - "route53-recovery-cluster:ListRoutingControls": {}, - "route53-recovery-control-config:ListAssociatedRoute53HealthChecks": {}, - "route53-recovery-control-config:ListClusters": {}, - "route53-recovery-control-config:ListControlPanels": {}, - "route53-recovery-control-config:ListRoutingControls": {}, - "route53-recovery-control-config:ListTagsForResource": {}, - "route53-recovery-readiness:CreateCrossAccountAuthorization": {}, - "route53-recovery-readiness:DeleteCrossAccountAuthorization": {}, - "route53-recovery-readiness:ListCells": {}, - "route53-recovery-readiness:ListCrossAccountAuthorizations": {}, - "route53-recovery-readiness:ListReadinessChecks": {}, - "route53-recovery-readiness:ListRecoveryGroups": {}, - "route53-recovery-readiness:ListResourceSets": {}, - "route53-recovery-readiness:ListRules": {}, - "route53-recovery-readiness:ListTagsForResources": {}, - "route53:CreateCidrCollection": {}, - "route53:CreateHealthCheck": {}, - "route53:CreateHostedZone": {}, - "route53:CreateReusableDelegationSet": {}, - "route53:CreateTrafficPolicy": {}, - "route53:GetAccountLimit": {}, - "route53:GetCheckerIpRanges": {}, - "route53:GetGeoLocation": {}, - "route53:GetHealthCheckCount": {}, - "route53:GetHostedZoneCount": {}, - "route53:GetTrafficPolicyInstanceCount": {}, - "route53:ListCidrCollections": {}, - "route53:ListGeoLocations": {}, - "route53:ListHealthChecks": {}, - "route53:ListHostedZones": {}, - "route53:ListHostedZonesByName": {}, - "route53:ListHostedZonesByVPC": {}, - "route53:ListReusableDelegationSets": {}, - "route53:ListTrafficPolicies": {}, - "route53:ListTrafficPolicyInstances": {}, - "route53:TestDNSAnswer": {}, - "route53domains:AcceptDomainTransferFromAnotherAwsAccount": {}, - "route53domains:AssociateDelegationSignerToDomain": {}, - "route53domains:CancelDomainTransferToAnotherAwsAccount": {}, - "route53domains:CheckDomainAvailability": {}, - "route53domains:CheckDomainTransferability": {}, - "route53domains:DeleteDomain": {}, - "route53domains:DeleteTagsForDomain": {}, - "route53domains:DisableDomainAutoRenew": {}, - "route53domains:DisableDomainTransferLock": {}, - "route53domains:DisassociateDelegationSignerFromDomain": {}, - "route53domains:EnableDomainAutoRenew": {}, - "route53domains:EnableDomainTransferLock": {}, - "route53domains:GetContactReachabilityStatus": {}, - "route53domains:GetDomainDetail": {}, - "route53domains:GetDomainSuggestions": {}, - "route53domains:GetOperationDetail": {}, - "route53domains:ListDomains": {}, - "route53domains:ListOperations": {}, - "route53domains:ListPrices": {}, - "route53domains:ListTagsForDomain": {}, - "route53domains:PushDomain": {}, - "route53domains:RegisterDomain": {}, - "route53domains:RejectDomainTransferFromAnotherAwsAccount": {}, - "route53domains:RenewDomain": {}, - "route53domains:ResendContactReachabilityEmail": {}, - "route53domains:ResendOperationAuthorization": {}, - "route53domains:RetrieveDomainAuthCode": {}, - "route53domains:TransferDomain": {}, - "route53domains:TransferDomainToAnotherAwsAccount": {}, - "route53domains:UpdateDomainContact": {}, - "route53domains:UpdateDomainContactPrivacy": {}, - "route53domains:UpdateDomainNameservers": {}, - "route53domains:UpdateTagsForDomain": {}, - "route53domains:ViewBilling": {}, - "route53resolver:CreateResolverQueryLogConfig": {}, - "route53resolver:GetResolverQueryLogConfigAssociation": {}, - "route53resolver:ListFirewallConfigs": {}, - "route53resolver:ListFirewallDomainLists": {}, - "route53resolver:ListFirewallRuleGroupAssociations": {}, - "route53resolver:ListFirewallRuleGroups": {}, - "route53resolver:ListOutpostResolvers": {}, - "route53resolver:ListResolverEndpoints": {}, - "route53resolver:ListResolverQueryLogConfigAssociations": {}, - "route53resolver:ListResolverQueryLogConfigs": {}, - "route53resolver:ListResolverRuleAssociations": {}, - "route53resolver:ListResolverRules": {}, - "rum:ListAppMonitors": {}, - "rum:ListTagsForResource": {}, - "s3-outposts:GetAccessPoint": {}, - "s3-outposts:ListAccessPoints": {}, - "s3-outposts:ListEndpoints": {}, - "s3-outposts:ListOutpostsWithS3": {}, - "s3-outposts:ListRegionalBuckets": {}, - "s3-outposts:ListSharedEndpoints": {}, - "s3:CreateJob": {}, - "s3:CreateStorageLensGroup": {}, - "s3:GetAccessPoint": {}, - "s3:GetAccountPublicAccessBlock": {}, - "s3:ListAccessGrantsInstances": {}, - "s3:ListAccessPoints": {}, - "s3:ListAccessPointsForObjectLambda": {}, - "s3:ListAllMyBuckets": {}, - "s3:ListJobs": {}, - "s3:ListMultiRegionAccessPoints": {}, - "s3:ListStorageLensConfigurations": {}, - "s3:ListStorageLensGroups": {}, - "s3:PutAccessPointPublicAccessBlock": {}, - "s3:PutAccountPublicAccessBlock": {}, - "s3:PutStorageLensConfiguration": {}, - "s3express:ListAllMyDirectoryBuckets": {}, - "sagemaker-geospatial:ListEarthObservationJobs": {}, - "sagemaker-geospatial:ListRasterDataCollections": {}, - "sagemaker-geospatial:ListVectorEnrichmentJobs": {}, - "sagemaker-geospatial:SearchRasterDataCollection": {}, - "sagemaker-groundtruth-synthetic:CreateProject": {}, - "sagemaker-groundtruth-synthetic:DeleteProject": {}, - "sagemaker-groundtruth-synthetic:GetAccountDetails": {}, - "sagemaker-groundtruth-synthetic:GetBatch": {}, - "sagemaker-groundtruth-synthetic:GetProject": {}, - "sagemaker-groundtruth-synthetic:ListBatchDataTransfers": {}, - "sagemaker-groundtruth-synthetic:ListBatchSummaries": {}, - "sagemaker-groundtruth-synthetic:ListProjectDataTransfers": {}, - "sagemaker-groundtruth-synthetic:ListProjectSummaries": {}, - "sagemaker-groundtruth-synthetic:StartBatchDataTransfer": {}, - "sagemaker-groundtruth-synthetic:StartProjectDataTransfer": {}, - "sagemaker-groundtruth-synthetic:UpdateBatch": {}, - "sagemaker:CreateLineageGroupPolicy": {}, - "sagemaker:DeleteLineageGroupPolicy": {}, - "sagemaker:DescribeLineageGroup": {}, - "sagemaker:DisableSagemakerServicecatalogPortfolio": {}, - "sagemaker:EnableSagemakerServicecatalogPortfolio": {}, - "sagemaker:GetLineageGroupPolicy": {}, - "sagemaker:GetSagemakerServicecatalogPortfolioStatus": {}, - "sagemaker:GetSearchSuggestions": {}, - "sagemaker:ListActions": {}, - "sagemaker:ListAlgorithms": {}, - "sagemaker:ListAppImageConfigs": {}, - "sagemaker:ListApps": {}, - "sagemaker:ListArtifacts": {}, - "sagemaker:ListAssociations": {}, - "sagemaker:ListAutoMLJobs": {}, - "sagemaker:ListCandidatesForAutoMLJob": {}, - "sagemaker:ListClusters": {}, - "sagemaker:ListCodeRepositories": {}, - "sagemaker:ListCompilationJobs": {}, - "sagemaker:ListContexts": {}, - "sagemaker:ListDataQualityJobDefinitions": {}, - "sagemaker:ListDeviceFleets": {}, - "sagemaker:ListDevices": {}, - "sagemaker:ListDomains": {}, - "sagemaker:ListEdgeDeploymentPlans": {}, - "sagemaker:ListEdgePackagingJobs": {}, - "sagemaker:ListEndpointConfigs": {}, - "sagemaker:ListEndpoints": {}, - "sagemaker:ListExperiments": {}, - "sagemaker:ListFeatureGroups": {}, - "sagemaker:ListFlowDefinitions": {}, - "sagemaker:ListHubs": {}, - "sagemaker:ListHumanLoops": {}, - "sagemaker:ListHumanTaskUis": {}, - "sagemaker:ListHyperParameterTuningJobs": {}, - "sagemaker:ListImages": {}, - "sagemaker:ListInferenceComponents": {}, - "sagemaker:ListInferenceExperiments": {}, - "sagemaker:ListInferenceRecommendationsJobSteps": {}, - "sagemaker:ListInferenceRecommendationsJobs": {}, - "sagemaker:ListLabelingJobs": {}, - "sagemaker:ListLineageGroups": {}, - "sagemaker:ListModelBiasJobDefinitions": {}, - "sagemaker:ListModelCards": {}, - "sagemaker:ListModelExplainabilityJobDefinitions": {}, - "sagemaker:ListModelMetadata": {}, - "sagemaker:ListModelPackageGroups": {}, - "sagemaker:ListModelQualityJobDefinitions": {}, - "sagemaker:ListModels": {}, - "sagemaker:ListMonitoringAlertHistory": {}, - "sagemaker:ListMonitoringAlerts": {}, - "sagemaker:ListMonitoringExecutions": {}, - "sagemaker:ListMonitoringSchedules": {}, - "sagemaker:ListNotebookInstanceLifecycleConfigs": {}, - "sagemaker:ListNotebookInstances": {}, - "sagemaker:ListPipelines": {}, - "sagemaker:ListProcessingJobs": {}, - "sagemaker:ListProjects": {}, - "sagemaker:ListResourceCatalogs": {}, - "sagemaker:ListSharedModelEvents": {}, - "sagemaker:ListSharedModels": {}, - "sagemaker:ListSpaces": {}, - "sagemaker:ListStageDevices": {}, - "sagemaker:ListStudioLifecycleConfigs": {}, - "sagemaker:ListSubscribedWorkteams": {}, - "sagemaker:ListTrainingJobs": {}, - "sagemaker:ListTransformJobs": {}, - "sagemaker:ListTrialComponents": {}, - "sagemaker:ListTrials": {}, - "sagemaker:ListUserProfiles": {}, - "sagemaker:ListWorkforces": {}, - "sagemaker:ListWorkteams": {}, - "sagemaker:PutLineageGroupPolicy": {}, - "sagemaker:QueryLineage": {}, - "sagemaker:RenderUiTemplate": {}, - "sagemaker:Search": {}, - "savingsplans:CreateSavingsPlan": {}, - "savingsplans:DescribeSavingsPlansOfferingRates": {}, - "savingsplans:DescribeSavingsPlansOfferings": {}, - "scheduler:ListScheduleGroups": {}, - "scheduler:ListSchedules": {}, - "schemas:CreateDiscoverer": {}, - "schemas:GetDiscoveredSchema": {}, - "sdb:ListDomains": {}, - "secretsmanager:BatchGetSecretValue": {}, - "secretsmanager:GetRandomPassword": {}, - "secretsmanager:ListSecrets": {}, - "securityhub:BatchGetConfigurationPolicyAssociations": {}, - "securityhub:BatchGetSecurityControls": {}, - "securityhub:BatchGetStandardsControlAssociations": {}, - "securityhub:BatchUpdateStandardsControlAssociations": {}, - "securityhub:CreateAutomationRule": {}, - "securityhub:CreateConfigurationPolicy": {}, - "securityhub:CreateFindingAggregator": {}, - "securityhub:GetConfigurationPolicyAssociation": {}, - "securityhub:GetSecurityControlDefinition": {}, - "securityhub:ListAutomationRules": {}, - "securityhub:ListConfigurationPolicies": {}, - "securityhub:ListConfigurationPolicyAssociations": {}, - "securityhub:ListFindingAggregators": {}, - "securityhub:ListSecurityControlDefinitions": {}, - "securityhub:ListStandardsControlAssociations": {}, - "securityhub:UpdateSecurityControl": {}, - "securitylake:CreateDataLakeExceptionSubscription": {}, - "securitylake:CreateSubscriber": {}, - "securitylake:DeleteDataLakeExceptionSubscription": {}, - "securitylake:DeregisterDataLakeDelegatedAdministrator": {}, - "securitylake:GetDataLakeExceptionSubscription": {}, - "securitylake:ListDataLakeExceptions": {}, - "securitylake:ListDataLakes": {}, - "securitylake:ListLogSources": {}, - "securitylake:ListSubscribers": {}, - "securitylake:RegisterDataLakeDelegatedAdministrator": {}, - "securitylake:UpdateDataLakeExceptionSubscription": {}, - "serverlessrepo:CreateApplication": {}, - "serverlessrepo:ListApplications": {}, - "serverlessrepo:SearchApplications": {}, - "servicecatalog:AssociateBudgetWithResource": {}, - "servicecatalog:AssociateProductWithPortfolio": {}, - "servicecatalog:BatchAssociateServiceActionWithProvisioningArtifact": {}, - "servicecatalog:BatchDisassociateServiceActionFromProvisioningArtifact": {}, - "servicecatalog:CopyProduct": {}, - "servicecatalog:CreateProvisionedProductPlan": {}, - "servicecatalog:CreateServiceAction": {}, - "servicecatalog:CreateTagOption": {}, - "servicecatalog:DeleteConstraint": {}, - "servicecatalog:DeleteProvisionedProductPlan": {}, - "servicecatalog:DeleteServiceAction": {}, - "servicecatalog:DeleteTagOption": {}, - "servicecatalog:DescribeConstraint": {}, - "servicecatalog:DescribeCopyProductStatus": {}, - "servicecatalog:DescribePortfolioShareStatus": {}, - "servicecatalog:DescribeProductView": {}, - "servicecatalog:DescribeProvisionedProduct": {}, - "servicecatalog:DescribeProvisionedProductPlan": {}, - "servicecatalog:DescribeRecord": {}, - "servicecatalog:DescribeServiceAction": {}, - "servicecatalog:DescribeServiceActionExecutionParameters": {}, - "servicecatalog:DescribeTagOption": {}, - "servicecatalog:DisableAWSOrganizationsAccess": {}, - "servicecatalog:DisassociateBudgetFromResource": {}, - "servicecatalog:DisassociateProductFromPortfolio": {}, - "servicecatalog:EnableAWSOrganizationsAccess": {}, - "servicecatalog:ExecuteProvisionedProductPlan": {}, - "servicecatalog:ExecuteProvisionedProductServiceAction": {}, - "servicecatalog:GetAWSOrganizationsAccessStatus": {}, - "servicecatalog:GetConfiguration": {}, - "servicecatalog:GetProvisionedProductOutputs": {}, - "servicecatalog:ListAcceptedPortfolioShares": {}, - "servicecatalog:ListApplications": {}, - "servicecatalog:ListAttributeGroups": {}, - "servicecatalog:ListBudgetsForResource": {}, - "servicecatalog:ListConstraintsForPortfolio": {}, - "servicecatalog:ListOrganizationPortfolioAccess": {}, - "servicecatalog:ListPortfolios": {}, - "servicecatalog:ListProvisionedProductPlans": {}, - "servicecatalog:ListProvisioningArtifactsForServiceAction": {}, - "servicecatalog:ListRecordHistory": {}, - "servicecatalog:ListResourcesForTagOption": {}, - "servicecatalog:ListServiceActions": {}, - "servicecatalog:ListStackInstancesForProvisionedProduct": {}, - "servicecatalog:ListTagOptions": {}, - "servicecatalog:NotifyProvisionProductEngineWorkflowResult": {}, - "servicecatalog:NotifyTerminateProvisionedProductEngineWorkflowResult": {}, - "servicecatalog:NotifyUpdateProvisionedProductEngineWorkflowResult": {}, - "servicecatalog:PutConfiguration": {}, - "servicecatalog:ScanProvisionedProducts": {}, - "servicecatalog:SearchProducts": {}, - "servicecatalog:SearchProductsAsAdmin": {}, - "servicecatalog:SearchProvisionedProducts": {}, - "servicecatalog:SyncResource": {}, - "servicecatalog:TerminateProvisionedProduct": {}, - "servicecatalog:UpdateConstraint": {}, - "servicecatalog:UpdateProvisionedProduct": {}, - "servicecatalog:UpdateProvisionedProductProperties": {}, - "servicecatalog:UpdateServiceAction": {}, - "servicecatalog:UpdateTagOption": {}, - "servicediscovery:CreateHttpNamespace": {}, - "servicediscovery:CreatePrivateDnsNamespace": {}, - "servicediscovery:CreatePublicDnsNamespace": {}, - "servicediscovery:DiscoverInstances": {}, - "servicediscovery:DiscoverInstancesRevision": {}, - "servicediscovery:GetInstance": {}, - "servicediscovery:GetInstancesHealthStatus": {}, - "servicediscovery:GetOperation": {}, - "servicediscovery:ListInstances": {}, - "servicediscovery:ListNamespaces": {}, - "servicediscovery:ListOperations": {}, - "servicediscovery:ListServices": {}, - "servicediscovery:ListTagsForResource": {}, - "servicediscovery:TagResource": {}, - "servicediscovery:UntagResource": {}, - "servicediscovery:UpdateInstanceCustomHealthStatus": {}, - "serviceextract:GetConfig": {}, - "servicequotas:AssociateServiceQuotaTemplate": {}, - "servicequotas:DeleteServiceQuotaIncreaseRequestFromTemplate": {}, - "servicequotas:DisassociateServiceQuotaTemplate": {}, - "servicequotas:GetAWSDefaultServiceQuota": {}, - "servicequotas:GetAssociationForServiceQuotaTemplate": {}, - "servicequotas:GetRequestedServiceQuotaChange": {}, - "servicequotas:GetServiceQuota": {}, - "servicequotas:GetServiceQuotaIncreaseRequestFromTemplate": {}, - "servicequotas:ListAWSDefaultServiceQuotas": {}, - "servicequotas:ListRequestedServiceQuotaChangeHistory": {}, - "servicequotas:ListRequestedServiceQuotaChangeHistoryByQuota": {}, - "servicequotas:ListServiceQuotaIncreaseRequestsInTemplate": {}, - "servicequotas:ListServiceQuotas": {}, - "servicequotas:ListServices": {}, - "servicequotas:ListTagsForResource": {}, - "servicequotas:TagResource": {}, - "servicequotas:UntagResource": {}, - "ses:CloneReceiptRuleSet": {}, - "ses:CreateConfigurationSet": {}, - "ses:CreateConfigurationSetEventDestination": {}, - "ses:CreateConfigurationSetTrackingOptions": {}, - "ses:CreateCustomVerificationEmailTemplate": {}, - "ses:CreateDedicatedIpPool": {}, - "ses:CreateEmailIdentity": {}, - "ses:CreateExportJob": {}, - "ses:CreateImportJob": {}, - "ses:CreateReceiptFilter": {}, - "ses:CreateReceiptRule": {}, - "ses:CreateReceiptRuleSet": {}, - "ses:CreateTemplate": {}, - "ses:DeleteConfigurationSet": {}, - "ses:DeleteConfigurationSetEventDestination": {}, - "ses:DeleteConfigurationSetTrackingOptions": {}, - "ses:DeleteCustomVerificationEmailTemplate": {}, - "ses:DeleteIdentity": {}, - "ses:DeleteIdentityPolicy": {}, - "ses:DeleteReceiptFilter": {}, - "ses:DeleteReceiptRule": {}, - "ses:DeleteReceiptRuleSet": {}, - "ses:DeleteSuppressedDestination": {}, - "ses:DeleteTemplate": {}, - "ses:DeleteVerifiedEmailAddress": {}, - "ses:DescribeActiveReceiptRuleSet": {}, - "ses:DescribeConfigurationSet": {}, - "ses:DescribeReceiptRule": {}, - "ses:DescribeReceiptRuleSet": {}, - "ses:GetAccount": {}, - "ses:GetAccountSendingEnabled": {}, - "ses:GetBlacklistReports": {}, - "ses:GetCustomVerificationEmailTemplate": {}, - "ses:GetDedicatedIp": {}, - "ses:GetDeliverabilityDashboardOptions": {}, - "ses:GetDomainDeliverabilityCampaign": {}, - "ses:GetIdentityDkimAttributes": {}, - "ses:GetIdentityMailFromDomainAttributes": {}, - "ses:GetIdentityNotificationAttributes": {}, - "ses:GetIdentityPolicies": {}, - "ses:GetIdentityVerificationAttributes": {}, - "ses:GetMessageInsights": {}, - "ses:GetSendQuota": {}, - "ses:GetSendStatistics": {}, - "ses:GetSuppressedDestination": {}, - "ses:GetTemplate": {}, - "ses:ListConfigurationSets": {}, - "ses:ListContactLists": {}, - "ses:ListCustomVerificationEmailTemplates": {}, - "ses:ListDedicatedIpPools": {}, - "ses:ListDeliverabilityTestReports": {}, - "ses:ListDomainDeliverabilityCampaigns": {}, - "ses:ListEmailIdentities": {}, - "ses:ListEmailTemplates": {}, - "ses:ListExportJobs": {}, - "ses:ListIdentities": {}, - "ses:ListIdentityPolicies": {}, - "ses:ListImportJobs": {}, - "ses:ListReceiptFilters": {}, - "ses:ListReceiptRuleSets": {}, - "ses:ListSuppressedDestinations": {}, - "ses:ListTemplates": {}, - "ses:ListVerifiedEmailAddresses": {}, - "ses:PutAccountDedicatedIpWarmupAttributes": {}, - "ses:PutAccountDetails": {}, - "ses:PutAccountSendingAttributes": {}, - "ses:PutAccountSuppressionAttributes": {}, - "ses:PutAccountVdmAttributes": {}, - "ses:PutConfigurationSetDeliveryOptions": {}, - "ses:PutDedicatedIpWarmupAttributes": {}, - "ses:PutDeliverabilityDashboardOption": {}, - "ses:PutIdentityPolicy": {}, - "ses:PutSuppressedDestination": {}, - "ses:ReorderReceiptRuleSet": {}, - "ses:SetActiveReceiptRuleSet": {}, - "ses:SetIdentityDkimEnabled": {}, - "ses:SetIdentityFeedbackForwardingEnabled": {}, - "ses:SetIdentityHeadersInNotificationsEnabled": {}, - "ses:SetIdentityMailFromDomain": {}, - "ses:SetIdentityNotificationTopic": {}, - "ses:SetReceiptRulePosition": {}, - "ses:TestRenderTemplate": {}, - "ses:UpdateAccountSendingEnabled": {}, - "ses:UpdateConfigurationSetEventDestination": {}, - "ses:UpdateConfigurationSetReputationMetricsEnabled": {}, - "ses:UpdateConfigurationSetSendingEnabled": {}, - "ses:UpdateConfigurationSetTrackingOptions": {}, - "ses:UpdateCustomVerificationEmailTemplate": {}, - "ses:UpdateReceiptRule": {}, - "ses:UpdateTemplate": {}, - "ses:VerifyDomainDkim": {}, - "ses:VerifyDomainIdentity": {}, - "ses:VerifyEmailAddress": {}, - "ses:VerifyEmailIdentity": {}, - "shield:AssociateDRTLogBucket": {}, - "shield:AssociateDRTRole": {}, - "shield:AssociateProactiveEngagementDetails": {}, - "shield:CreateProtection": {}, - "shield:CreateProtectionGroup": {}, - "shield:CreateSubscription": {}, - "shield:DeleteSubscription": {}, - "shield:DescribeAttackStatistics": {}, - "shield:DescribeDRTAccess": {}, - "shield:DescribeEmergencyContactSettings": {}, - "shield:DescribeSubscription": {}, - "shield:DisableApplicationLayerAutomaticResponse": {}, - "shield:DisableProactiveEngagement": {}, - "shield:DisassociateDRTLogBucket": {}, - "shield:DisassociateDRTRole": {}, - "shield:EnableApplicationLayerAutomaticResponse": {}, - "shield:EnableProactiveEngagement": {}, - "shield:GetSubscriptionState": {}, - "shield:ListAttacks": {}, - "shield:ListProtectionGroups": {}, - "shield:ListProtections": {}, - "shield:UpdateApplicationLayerAutomaticResponse": {}, - "shield:UpdateEmergencyContactSettings": {}, - "shield:UpdateSubscription": {}, - "signer:GetSigningPlatform": {}, - "signer:ListSigningJobs": {}, - "signer:ListSigningPlatforms": {}, - "signer:ListSigningProfiles": {}, - "signer:PutSigningProfile": {}, - "simspaceweaver:ListSimulations": {}, - "simspaceweaver:ListTagsForResource": {}, - "simspaceweaver:StartSimulation": {}, - "sms-voice:CreateConfigurationSet": {}, - "sms-voice:CreateConfigurationSetEventDestination": {}, - "sms-voice:CreateOptOutList": {}, - "sms-voice:CreateRegistration": {}, - "sms-voice:CreateRegistrationAttachment": {}, - "sms-voice:CreateVerifiedDestinationNumber": {}, - "sms-voice:DeleteConfigurationSet": {}, - "sms-voice:DeleteConfigurationSetEventDestination": {}, - "sms-voice:DeleteTextMessageSpendLimitOverride": {}, - "sms-voice:DeleteVoiceMessageSpendLimitOverride": {}, - "sms-voice:DescribeAccountAttributes": {}, - "sms-voice:DescribeAccountLimits": {}, - "sms-voice:DescribeRegistrationFieldDefinitions": {}, - "sms-voice:DescribeRegistrationSectionDefinitions": {}, - "sms-voice:DescribeRegistrationTypeDefinitions": {}, - "sms-voice:DescribeSpendLimits": {}, - "sms-voice:GetConfigurationSetEventDestinations": {}, - "sms-voice:ListConfigurationSets": {}, - "sms-voice:RequestSenderId": {}, - "sms-voice:SendVoiceMessage": {}, - "sms-voice:SetTextMessageSpendLimitOverride": {}, - "sms-voice:SetVoiceMessageSpendLimitOverride": {}, - "sms-voice:UpdateConfigurationSetEventDestination": {}, - "sms:CreateApp": {}, - "sms:CreateReplicationJob": {}, - "sms:DeleteApp": {}, - "sms:DeleteAppLaunchConfiguration": {}, - "sms:DeleteAppReplicationConfiguration": {}, - "sms:DeleteAppValidationConfiguration": {}, - "sms:DeleteReplicationJob": {}, - "sms:DeleteServerCatalog": {}, - "sms:DisassociateConnector": {}, - "sms:GenerateChangeSet": {}, - "sms:GenerateTemplate": {}, - "sms:GetApp": {}, - "sms:GetAppLaunchConfiguration": {}, - "sms:GetAppReplicationConfiguration": {}, - "sms:GetAppValidationConfiguration": {}, - "sms:GetAppValidationOutput": {}, - "sms:GetConnectors": {}, - "sms:GetReplicationJobs": {}, - "sms:GetReplicationRuns": {}, - "sms:GetServers": {}, - "sms:ImportAppCatalog": {}, - "sms:ImportServerCatalog": {}, - "sms:LaunchApp": {}, - "sms:ListApps": {}, - "sms:NotifyAppValidationOutput": {}, - "sms:PutAppLaunchConfiguration": {}, - "sms:PutAppReplicationConfiguration": {}, - "sms:PutAppValidationConfiguration": {}, - "sms:StartAppReplication": {}, - "sms:StartOnDemandAppReplication": {}, - "sms:StartOnDemandReplicationRun": {}, - "sms:StopAppReplication": {}, - "sms:TerminateApp": {}, - "sms:UpdateApp": {}, - "sms:UpdateReplicationJob": {}, - "snow-device-management:CreateTask": {}, - "snow-device-management:DescribeExecution": {}, - "snow-device-management:ListDevices": {}, - "snow-device-management:ListExecutions": {}, - "snow-device-management:ListTagsForResource": {}, - "snow-device-management:ListTasks": {}, - "snowball:CancelCluster": {}, - "snowball:CancelJob": {}, - "snowball:CreateAddress": {}, - "snowball:CreateCluster": {}, - "snowball:CreateJob": {}, - "snowball:CreateLongTermPricing": {}, - "snowball:CreateReturnShippingLabel": {}, - "snowball:DescribeAddress": {}, - "snowball:DescribeAddresses": {}, - "snowball:DescribeCluster": {}, - "snowball:DescribeJob": {}, - "snowball:DescribeReturnShippingLabel": {}, - "snowball:GetJobManifest": {}, - "snowball:GetJobUnlockCode": {}, - "snowball:GetSnowballUsage": {}, - "snowball:GetSoftwareUpdates": {}, - "snowball:ListClusterJobs": {}, - "snowball:ListClusters": {}, - "snowball:ListCompatibleImages": {}, - "snowball:ListJobs": {}, - "snowball:ListLongTermPricing": {}, - "snowball:ListPickupLocations": {}, - "snowball:ListServiceVersions": {}, - "snowball:UpdateCluster": {}, - "snowball:UpdateJob": {}, - "snowball:UpdateJobShipmentState": {}, - "snowball:UpdateLongTermPricing": {}, - "sns:CheckIfPhoneNumberIsOptedOut": {}, - "sns:CreatePlatformApplication": {}, - "sns:CreatePlatformEndpoint": {}, - "sns:CreateSMSSandboxPhoneNumber": {}, - "sns:DeleteEndpoint": {}, - "sns:DeletePlatformApplication": {}, - "sns:DeleteSMSSandboxPhoneNumber": {}, - "sns:GetEndpointAttributes": {}, - "sns:GetPlatformApplicationAttributes": {}, - "sns:GetSMSAttributes": {}, - "sns:GetSMSSandboxAccountStatus": {}, - "sns:GetSubscriptionAttributes": {}, - "sns:ListEndpointsByPlatformApplication": {}, - "sns:ListOriginationNumbers": {}, - "sns:ListPhoneNumbersOptedOut": {}, - "sns:ListPlatformApplications": {}, - "sns:ListSMSSandboxPhoneNumbers": {}, - "sns:ListSubscriptions": {}, - "sns:ListTopics": {}, - "sns:OptInPhoneNumber": {}, - "sns:SetEndpointAttributes": {}, - "sns:SetPlatformApplicationAttributes": {}, - "sns:SetSMSAttributes": {}, - "sns:SetSubscriptionAttributes": {}, - "sns:Unsubscribe": {}, - "sns:VerifySMSSandboxPhoneNumber": {}, - "sqlworkbench:BatchDeleteFolder": {}, - "sqlworkbench:CreateAccount": {}, - "sqlworkbench:CreateFolder": {}, - "sqlworkbench:DeleteTab": {}, - "sqlworkbench:GenerateSession": {}, - "sqlworkbench:GetAccountInfo": {}, - "sqlworkbench:GetAccountSettings": {}, - "sqlworkbench:GetAutocompletionMetadata": {}, - "sqlworkbench:GetAutocompletionResource": {}, - "sqlworkbench:GetQSqlRecommendations": {}, - "sqlworkbench:GetQueryExecutionHistory": {}, - "sqlworkbench:GetSchemaInference": {}, - "sqlworkbench:GetUserInfo": {}, - "sqlworkbench:GetUserWorkspaceSettings": {}, - "sqlworkbench:ListConnections": {}, - "sqlworkbench:ListDatabases": {}, - "sqlworkbench:ListFiles": {}, - "sqlworkbench:ListNotebooks": {}, - "sqlworkbench:ListQueryExecutionHistory": {}, - "sqlworkbench:ListRedshiftClusters": {}, - "sqlworkbench:ListSampleDatabases": {}, - "sqlworkbench:ListTabs": {}, - "sqlworkbench:ListTaggedResources": {}, - "sqlworkbench:PutTab": {}, - "sqlworkbench:PutUserWorkspaceSettings": {}, - "sqlworkbench:UpdateAccountConnectionSettings": {}, - "sqlworkbench:UpdateAccountExportSettings": {}, - "sqlworkbench:UpdateAccountGeneralSettings": {}, - "sqlworkbench:UpdateAccountQSqlSettings": {}, - "sqlworkbench:UpdateFolder": {}, - "sqs:ListQueues": {}, - "ssm-contacts:ListContacts": {}, - "ssm-contacts:ListEngagements": {}, - "ssm-contacts:ListRotations": {}, - "ssm-guiconnect:CancelConnection": {}, - "ssm-guiconnect:GetConnection": {}, - "ssm-guiconnect:StartConnection": {}, - "ssm-incidents:CreateReplicationSet": {}, - "ssm-incidents:CreateResponsePlan": {}, - "ssm-incidents:ListIncidentRecords": {}, - "ssm-incidents:ListReplicationSets": {}, - "ssm-incidents:ListResponsePlans": {}, - "ssm-sap:BackupDatabase": {}, - "ssm-sap:DeleteResourcePermission": {}, - "ssm-sap:GetApplication": {}, - "ssm-sap:GetDatabase": {}, - "ssm-sap:GetOperation": {}, - "ssm-sap:GetResourcePermission": {}, - "ssm-sap:ListApplications": {}, - "ssm-sap:ListDatabases": {}, - "ssm-sap:ListOperations": {}, - "ssm-sap:ListTagsForResource": {}, - "ssm-sap:PutResourcePermission": {}, - "ssm-sap:RegisterApplication": {}, - "ssm-sap:RestoreDatabase": {}, - "ssm-sap:UpdateHANABackupSettings": {}, - "ssm:CancelCommand": {}, - "ssm:CreateActivation": {}, - "ssm:CreateMaintenanceWindow": {}, - "ssm:CreateOpsItem": {}, - "ssm:CreateOpsMetadata": {}, - "ssm:CreatePatchBaseline": {}, - "ssm:DeleteActivation": {}, - "ssm:DeleteInventory": {}, - "ssm:DescribeActivations": {}, - "ssm:DescribeAutomationExecutions": {}, - "ssm:DescribeAvailablePatches": {}, - "ssm:DescribeInstanceInformation": {}, - "ssm:DescribeInstancePatchStates": {}, - "ssm:DescribeInstancePatchStatesForPatchGroup": {}, - "ssm:DescribeInstancePatches": {}, - "ssm:DescribeInstanceProperties": {}, - "ssm:DescribeInventoryDeletions": {}, - "ssm:DescribeMaintenanceWindowExecutionTaskInvocations": {}, - "ssm:DescribeMaintenanceWindowSchedule": {}, - "ssm:DescribeMaintenanceWindows": {}, - "ssm:DescribeMaintenanceWindowsForTarget": {}, - "ssm:DescribeOpsItems": {}, - "ssm:DescribeParameters": {}, - "ssm:DescribePatchBaselines": {}, - "ssm:DescribePatchGroupState": {}, - "ssm:DescribePatchGroups": {}, - "ssm:DescribePatchProperties": {}, - "ssm:DescribeSessions": {}, - "ssm:GetCommandInvocation": {}, - "ssm:GetDeployablePatchSnapshotForInstance": {}, - "ssm:GetInventory": {}, - "ssm:GetInventorySchema": {}, - "ssm:GetMaintenanceWindowExecution": {}, - "ssm:GetMaintenanceWindowExecutionTask": {}, - "ssm:GetMaintenanceWindowExecutionTaskInvocation": {}, - "ssm:GetManifest": {}, - "ssm:ListAssociations": {}, - "ssm:ListCommandInvocations": {}, - "ssm:ListCommands": {}, - "ssm:ListComplianceItems": {}, - "ssm:ListComplianceSummaries": {}, - "ssm:ListDocuments": {}, - "ssm:ListInventoryEntries": {}, - "ssm:ListOpsItemEvents": {}, - "ssm:ListOpsItemRelatedItems": {}, - "ssm:ListOpsMetadata": {}, - "ssm:ListResourceComplianceSummaries": {}, - "ssm:ListResourceDataSync": {}, - "ssm:PutConfigurePackageResult": {}, - "ssm:PutInventory": {}, - "ssm:RegisterManagedInstance": {}, - "ssmmessages:CreateControlChannel": {}, - "ssmmessages:CreateDataChannel": {}, - "ssmmessages:OpenControlChannel": {}, - "ssmmessages:OpenDataChannel": {}, - "sso-directory:AddMemberToGroup": {}, - "sso-directory:CompleteVirtualMfaDeviceRegistration": {}, - "sso-directory:CompleteWebAuthnDeviceRegistration": {}, - "sso-directory:CreateAlias": {}, - "sso-directory:CreateBearerToken": {}, - "sso-directory:CreateExternalIdPConfigurationForDirectory": {}, - "sso-directory:CreateGroup": {}, - "sso-directory:CreateProvisioningTenant": {}, - "sso-directory:CreateUser": {}, - "sso-directory:DeleteBearerToken": {}, - "sso-directory:DeleteExternalIdPCertificate": {}, - "sso-directory:DeleteExternalIdPConfigurationForDirectory": {}, - "sso-directory:DeleteGroup": {}, - "sso-directory:DeleteMfaDeviceForUser": {}, - "sso-directory:DeleteProvisioningTenant": {}, - "sso-directory:DeleteUser": {}, - "sso-directory:DescribeDirectory": {}, - "sso-directory:DescribeGroup": {}, - "sso-directory:DescribeGroups": {}, - "sso-directory:DescribeProvisioningTenant": {}, - "sso-directory:DescribeUser": {}, - "sso-directory:DescribeUserByUniqueAttribute": {}, - "sso-directory:DescribeUsers": {}, - "sso-directory:DisableExternalIdPConfigurationForDirectory": {}, - "sso-directory:DisableUser": {}, - "sso-directory:EnableExternalIdPConfigurationForDirectory": {}, - "sso-directory:EnableUser": {}, - "sso-directory:GetAWSSPConfigurationForDirectory": {}, - "sso-directory:GetUserPoolInfo": {}, - "sso-directory:ImportExternalIdPCertificate": {}, - "sso-directory:IsMemberInGroup": {}, - "sso-directory:ListBearerTokens": {}, - "sso-directory:ListExternalIdPCertificates": {}, - "sso-directory:ListExternalIdPConfigurationsForDirectory": {}, - "sso-directory:ListGroupsForMember": {}, - "sso-directory:ListGroupsForUser": {}, - "sso-directory:ListMembersInGroup": {}, - "sso-directory:ListMfaDevicesForUser": {}, - "sso-directory:ListProvisioningTenants": {}, - "sso-directory:RemoveMemberFromGroup": {}, - "sso-directory:SearchGroups": {}, - "sso-directory:SearchUsers": {}, - "sso-directory:StartVirtualMfaDeviceRegistration": {}, - "sso-directory:StartWebAuthnDeviceRegistration": {}, - "sso-directory:UpdateExternalIdPConfigurationForDirectory": {}, - "sso-directory:UpdateGroup": {}, - "sso-directory:UpdateGroupDisplayName": {}, - "sso-directory:UpdateMfaDeviceForUser": {}, - "sso-directory:UpdatePassword": {}, - "sso-directory:UpdateUser": {}, - "sso-directory:UpdateUserName": {}, - "sso-directory:VerifyEmail": {}, - "sso:AssociateDirectory": {}, - "sso:AssociateProfile": {}, - "sso:CreateApplicationInstance": {}, - "sso:CreateApplicationInstanceCertificate": {}, - "sso:CreateManagedApplicationInstance": {}, - "sso:CreateProfile": {}, - "sso:CreateTrust": {}, - "sso:DeleteApplicationInstance": {}, - "sso:DeleteApplicationInstanceCertificate": {}, - "sso:DeleteManagedApplicationInstance": {}, - "sso:DeletePermissionsPolicy": {}, - "sso:DeleteProfile": {}, - "sso:DescribeDirectories": {}, - "sso:DescribePermissionsPolicies": {}, - "sso:DescribeRegisteredRegions": {}, - "sso:DescribeTrusts": {}, - "sso:DisassociateDirectory": {}, - "sso:DisassociateProfile": {}, - "sso:GetApplicationInstance": {}, - "sso:GetApplicationTemplate": {}, - "sso:GetManagedApplicationInstance": {}, - "sso:GetMfaDeviceManagementForDirectory": {}, - "sso:GetPermissionSet": {}, - "sso:GetPermissionsPolicy": {}, - "sso:GetProfile": {}, - "sso:GetSSOStatus": {}, - "sso:GetSharedSsoConfiguration": {}, - "sso:GetSsoConfiguration": {}, - "sso:GetTrust": {}, - "sso:ImportApplicationInstanceServiceProviderMetadata": {}, - "sso:ListApplicationInstanceCertificates": {}, - "sso:ListApplicationInstances": {}, - "sso:ListApplicationTemplates": {}, - "sso:ListApplications": {}, - "sso:ListDirectoryAssociations": {}, - "sso:ListInstances": {}, - "sso:ListProfileAssociations": {}, - "sso:ListProfiles": {}, - "sso:PutMfaDeviceManagementForDirectory": {}, - "sso:PutPermissionsPolicy": {}, - "sso:SearchGroups": {}, - "sso:SearchUsers": {}, - "sso:StartSSO": {}, - "sso:UpdateApplicationInstanceActiveCertificate": {}, - "sso:UpdateApplicationInstanceDisplayData": {}, - "sso:UpdateApplicationInstanceResponseConfiguration": {}, - "sso:UpdateApplicationInstanceResponseSchemaConfiguration": {}, - "sso:UpdateApplicationInstanceSecurityConfiguration": {}, - "sso:UpdateApplicationInstanceServiceProviderConfiguration": {}, - "sso:UpdateApplicationInstanceStatus": {}, - "sso:UpdateDirectoryAssociation": {}, - "sso:UpdateManagedApplicationInstanceStatus": {}, - "sso:UpdateProfile": {}, - "sso:UpdateSSOConfiguration": {}, - "sso:UpdateTrust": {}, - "states:InvokeHTTPEndpoint": {}, - "states:ListActivities": {}, - "states:ListStateMachines": {}, - "states:RevealSecrets": {}, - "states:SendTaskFailure": {}, - "states:SendTaskHeartbeat": {}, - "states:SendTaskSuccess": {}, - "states:TestState": {}, - "storagegateway:ActivateGateway": {}, - "storagegateway:CreateTapePool": {}, - "storagegateway:DeleteTapeArchive": {}, - "storagegateway:DescribeTapeArchives": {}, - "storagegateway:ListAutomaticTapeCreationPolicies": {}, - "storagegateway:ListFileShares": {}, - "storagegateway:ListFileSystemAssociations": {}, - "storagegateway:ListGateways": {}, - "storagegateway:ListTapePools": {}, - "storagegateway:ListTapes": {}, - "storagegateway:ListVolumes": {}, - "sts:DecodeAuthorizationMessage": {}, - "sts:GetAccessKeyInfo": {}, - "sts:GetCallerIdentity": {}, - "sts:GetServiceBearerToken": {}, - "sts:GetSessionToken": {}, - "support:AddAttachmentsToSet": {}, - "support:AddCommunicationToCase": {}, - "support:CreateCase": {}, - "support:DescribeAttachment": {}, - "support:DescribeCaseAttributes": {}, - "support:DescribeCases": {}, - "support:DescribeCommunication": {}, - "support:DescribeCommunications": {}, - "support:DescribeCreateCaseOptions": {}, - "support:DescribeIssueTypes": {}, - "support:DescribeServices": {}, - "support:DescribeSeverityLevels": {}, - "support:DescribeSupportLevel": {}, - "support:DescribeSupportedLanguages": {}, - "support:DescribeTrustedAdvisorCheckRefreshStatuses": {}, - "support:DescribeTrustedAdvisorCheckResult": {}, - "support:DescribeTrustedAdvisorCheckSummaries": {}, - "support:DescribeTrustedAdvisorChecks": {}, - "support:InitiateCallForCase": {}, - "support:InitiateChatForCase": {}, - "support:PutCaseAttributes": {}, - "support:RateCaseCommunication": {}, - "support:RefreshTrustedAdvisorCheck": {}, - "support:ResolveCase": {}, - "support:SearchForCases": {}, - "supportapp:CreateSlackChannelConfiguration": {}, - "supportapp:DeleteAccountAlias": {}, - "supportapp:DeleteSlackChannelConfiguration": {}, - "supportapp:DeleteSlackWorkspaceConfiguration": {}, - "supportapp:DescribeSlackChannels": {}, - "supportapp:GetAccountAlias": {}, - "supportapp:GetSlackOauthParameters": {}, - "supportapp:ListSlackChannelConfigurations": {}, - "supportapp:ListSlackWorkspaceConfigurations": {}, - "supportapp:PutAccountAlias": {}, - "supportapp:RedeemSlackOauthCode": {}, - "supportapp:RegisterSlackWorkspaceForOrganization": {}, - "supportapp:UpdateSlackChannelConfiguration": {}, - "supportplans:CreateSupportPlanSchedule": {}, - "supportplans:GetSupportPlan": {}, - "supportplans:GetSupportPlanUpdateStatus": {}, - "supportplans:StartSupportPlanUpdate": {}, - "sustainability:GetCarbonFootprintSummary": {}, - "swf:ListDomains": {}, - "swf:RegisterDomain": {}, - "synthetics:CreateCanary": {}, - "synthetics:CreateGroup": {}, - "synthetics:DescribeCanaries": {}, - "synthetics:DescribeCanariesLastRun": {}, - "synthetics:DescribeRuntimeVersions": {}, - "synthetics:ListGroups": {}, - "tag:DescribeReportCreation": {}, - "tag:GetComplianceSummary": {}, - "tag:GetResources": {}, - "tag:GetTagKeys": {}, - "tag:GetTagValues": {}, - "tag:StartReportCreation": {}, - "tag:TagResources": {}, - "tag:UntagResources": {}, - "tax:BatchPutTaxRegistration": {}, - "tax:DeleteTaxRegistration": {}, - "tax:GetExemptions": {}, - "tax:GetTaxInfoReportingDocument": {}, - "tax:GetTaxInheritance": {}, - "tax:GetTaxInterview": {}, - "tax:GetTaxRegistration": {}, - "tax:GetTaxRegistrationDocument": {}, - "tax:ListTaxRegistrations": {}, - "tax:PutTaxInheritance": {}, - "tax:PutTaxInterview": {}, - "tax:PutTaxRegistration": {}, - "tax:UpdateExemptions": {}, - "textract:AnalyzeDocument": {}, - "textract:AnalyzeExpense": {}, - "textract:AnalyzeID": {}, - "textract:CreateAdapter": {}, - "textract:DetectDocumentText": {}, - "textract:GetDocumentAnalysis": {}, - "textract:GetDocumentTextDetection": {}, - "textract:GetExpenseAnalysis": {}, - "textract:GetLendingAnalysis": {}, - "textract:GetLendingAnalysisSummary": {}, - "textract:ListAdapterVersions": {}, - "textract:ListAdapters": {}, - "textract:StartDocumentAnalysis": {}, - "textract:StartDocumentTextDetection": {}, - "textract:StartExpenseAnalysis": {}, - "textract:StartLendingAnalysis": {}, - "thinclient:CreateEnvironment": {}, - "thinclient:ListDeviceSessions": {}, - "thinclient:ListDevices": {}, - "thinclient:ListEnvironments": {}, - "thinclient:ListSoftwareSets": {}, - "thinclient:ListTagsForResource": {}, - "timestream:CancelQuery": {}, - "timestream:CreateScheduledQuery": {}, - "timestream:DescribeBatchLoadTask": {}, - "timestream:DescribeEndpoints": {}, - "timestream:GetAwsBackupStatus": {}, - "timestream:GetAwsRestoreStatus": {}, - "timestream:ListBatchLoadTasks": {}, - "timestream:ListDatabases": {}, - "timestream:ListScheduledQueries": {}, - "timestream:ResumeBatchLoadTask": {}, - "timestream:SelectValues": {}, - "tiros:CreateQuery": {}, - "tiros:ExtendQuery": {}, - "tiros:GetQueryAnswer": {}, - "tiros:GetQueryExplanation": {}, - "tiros:GetQueryExtensionAccounts": {}, - "tnb:ListTagsForResource": {}, - "transcribe:CreateCallAnalyticsCategory": {}, - "transcribe:CreateLanguageModel": {}, - "transcribe:CreateMedicalVocabulary": {}, - "transcribe:CreateVocabulary": {}, - "transcribe:CreateVocabularyFilter": {}, - "transcribe:DeleteCallAnalyticsCategory": {}, - "transcribe:DeleteCallAnalyticsJob": {}, - "transcribe:GetCallAnalyticsCategory": {}, - "transcribe:GetCallAnalyticsJob": {}, - "transcribe:ListCallAnalyticsCategories": {}, - "transcribe:ListCallAnalyticsJobs": {}, - "transcribe:ListLanguageModels": {}, - "transcribe:ListMedicalScribeJobs": {}, - "transcribe:ListMedicalTranscriptionJobs": {}, - "transcribe:ListMedicalVocabularies": {}, - "transcribe:ListTagsForResource": {}, - "transcribe:ListTranscriptionJobs": {}, - "transcribe:ListVocabularies": {}, - "transcribe:ListVocabularyFilters": {}, - "transcribe:StartCallAnalyticsJob": {}, - "transcribe:StartCallAnalyticsStreamTranscription": {}, - "transcribe:StartCallAnalyticsStreamTranscriptionWebSocket": {}, - "transcribe:StartMedicalScribeJob": {}, - "transcribe:StartMedicalStreamTranscription": {}, - "transcribe:StartMedicalStreamTranscriptionWebSocket": {}, - "transcribe:StartMedicalTranscriptionJob": {}, - "transcribe:StartStreamTranscription": {}, - "transcribe:StartStreamTranscriptionWebSocket": {}, - "transcribe:StartTranscriptionJob": {}, - "transcribe:TagResource": {}, - "transcribe:UntagResource": {}, - "transcribe:UpdateCallAnalyticsCategory": {}, - "transfer:CreateConnector": {}, - "transfer:CreateProfile": {}, - "transfer:CreateServer": {}, - "transfer:CreateWorkflow": {}, - "transfer:DescribeSecurityPolicy": {}, - "transfer:ImportCertificate": {}, - "transfer:ListCertificates": {}, - "transfer:ListConnectors": {}, - "transfer:ListProfiles": {}, - "transfer:ListSecurityPolicies": {}, - "transfer:ListServers": {}, - "transfer:ListWorkflows": {}, - "transfer:UpdateAccess": {}, - "translate:DescribeTextTranslationJob": {}, - "translate:ListLanguages": {}, - "translate:ListParallelData": {}, - "translate:ListTerminologies": {}, - "translate:ListTextTranslationJobs": {}, - "translate:StopTextTranslationJob": {}, - "trustedadvisor:CreateEngagement": {}, - "trustedadvisor:CreateEngagementAttachment": {}, - "trustedadvisor:CreateEngagementCommunication": {}, - "trustedadvisor:DeleteNotificationConfigurationForDelegatedAdmin": {}, - "trustedadvisor:DescribeAccount": {}, - "trustedadvisor:DescribeAccountAccess": {}, - "trustedadvisor:DescribeChecks": {}, - "trustedadvisor:DescribeNotificationConfigurations": {}, - "trustedadvisor:DescribeNotificationPreferences": {}, - "trustedadvisor:DescribeOrganization": {}, - "trustedadvisor:DescribeOrganizationAccounts": {}, - "trustedadvisor:DescribeReports": {}, - "trustedadvisor:DescribeRisk": {}, - "trustedadvisor:DescribeRiskResources": {}, - "trustedadvisor:DescribeRisks": {}, - "trustedadvisor:DescribeServiceMetadata": {}, - "trustedadvisor:DownloadRisk": {}, - "trustedadvisor:GenerateReport": {}, - "trustedadvisor:GetEngagement": {}, - "trustedadvisor:GetEngagementAttachment": {}, - "trustedadvisor:GetEngagementType": {}, - "trustedadvisor:GetOrganizationRecommendation": {}, - "trustedadvisor:GetRecommendation": {}, - "trustedadvisor:ListAccountsForParent": {}, - "trustedadvisor:ListChecks": {}, - "trustedadvisor:ListEngagementCommunications": {}, - "trustedadvisor:ListEngagementTypes": {}, - "trustedadvisor:ListEngagements": {}, - "trustedadvisor:ListOrganizationRecommendationAccounts": {}, - "trustedadvisor:ListOrganizationRecommendationResources": {}, - "trustedadvisor:ListOrganizationRecommendations": {}, - "trustedadvisor:ListOrganizationalUnitsForParent": {}, - "trustedadvisor:ListRecommendationResources": {}, - "trustedadvisor:ListRecommendations": {}, - "trustedadvisor:ListRoots": {}, - "trustedadvisor:SetAccountAccess": {}, - "trustedadvisor:SetOrganizationAccess": {}, - "trustedadvisor:UpdateEngagement": {}, - "trustedadvisor:UpdateEngagementStatus": {}, - "trustedadvisor:UpdateNotificationConfigurations": {}, - "trustedadvisor:UpdateNotificationPreferences": {}, - "trustedadvisor:UpdateOrganizationRecommendationLifecycle": {}, - "trustedadvisor:UpdateRecommendationLifecycle": {}, - "trustedadvisor:UpdateRiskStatus": {}, - "ts:ListExecutions": {}, - "ts:ListTools": {}, - "ts:StartExecution": {}, - "vendor-insights:CreateDataSource": {}, - "vendor-insights:CreateSecurityProfile": {}, - "vendor-insights:GetProfileAccessTerms": {}, - "vendor-insights:ListDataSources": {}, - "vendor-insights:ListEntitledSecurityProfiles": {}, - "vendor-insights:ListSecurityProfiles": {}, - "verified-access:AllowVerifiedAccess": {}, - "verifiedpermissions:CreatePolicyStore": {}, - "verifiedpermissions:ListPolicyStores": {}, - "voiceid:CreateDomain": {}, - "voiceid:DescribeComplianceConsent": {}, - "voiceid:ListDomains": {}, - "voiceid:RegisterComplianceConsent": {}, - "vpc-lattice:ListAccessLogSubscriptions": {}, - "vpc-lattice:ListListeners": {}, - "vpc-lattice:ListRules": {}, - "vpc-lattice:ListServiceNetworkServiceAssociations": {}, - "vpc-lattice:ListServiceNetworkVpcAssociations": {}, - "vpc-lattice:ListServiceNetworks": {}, - "vpc-lattice:ListServices": {}, - "vpc-lattice:ListTagsForResource": {}, - "vpc-lattice:ListTargetGroups": {}, - "waf-regional:GetChangeToken": {}, - "waf-regional:GetChangeTokenStatus": {}, - "waf-regional:ListActivatedRulesInRuleGroup": {}, - "waf-regional:ListByteMatchSets": {}, - "waf-regional:ListGeoMatchSets": {}, - "waf-regional:ListIPSets": {}, - "waf-regional:ListLoggingConfigurations": {}, - "waf-regional:ListRateBasedRules": {}, - "waf-regional:ListRegexMatchSets": {}, - "waf-regional:ListRegexPatternSets": {}, - "waf-regional:ListRuleGroups": {}, - "waf-regional:ListRules": {}, - "waf-regional:ListSizeConstraintSets": {}, - "waf-regional:ListSqlInjectionMatchSets": {}, - "waf-regional:ListSubscribedRuleGroups": {}, - "waf-regional:ListWebACLs": {}, - "waf-regional:ListXssMatchSets": {}, - "waf:GetChangeToken": {}, - "waf:GetChangeTokenStatus": {}, - "waf:ListActivatedRulesInRuleGroup": {}, - "waf:ListByteMatchSets": {}, - "waf:ListGeoMatchSets": {}, - "waf:ListIPSets": {}, - "waf:ListLoggingConfigurations": {}, - "waf:ListRateBasedRules": {}, - "waf:ListRegexMatchSets": {}, - "waf:ListRegexPatternSets": {}, - "waf:ListRuleGroups": {}, - "waf:ListRules": {}, - "waf:ListSizeConstraintSets": {}, - "waf:ListSqlInjectionMatchSets": {}, - "waf:ListSubscribedRuleGroups": {}, - "waf:ListWebACLs": {}, - "waf:ListXssMatchSets": {}, - "wafv2:CheckCapacity": {}, - "wafv2:CreateAPIKey": {}, - "wafv2:DescribeAllManagedProducts": {}, - "wafv2:DescribeManagedProductsByVendor": {}, - "wafv2:DescribeManagedRuleGroup": {}, - "wafv2:GenerateMobileSdkReleaseUrl": {}, - "wafv2:GetDecryptedAPIKey": {}, - "wafv2:GetMobileSdkRelease": {}, - "wafv2:ListAPIKeys": {}, - "wafv2:ListAvailableManagedRuleGroupVersions": {}, - "wafv2:ListAvailableManagedRuleGroups": {}, - "wafv2:ListIPSets": {}, - "wafv2:ListLoggingConfigurations": {}, - "wafv2:ListManagedRuleSets": {}, - "wafv2:ListMobileSdkReleases": {}, - "wafv2:ListRegexPatternSets": {}, - "wafv2:ListRuleGroups": {}, - "wafv2:ListWebACLs": {}, - "wam:AuthenticatePackager": {}, - "wellarchitected:CreateProfile": {}, - "wellarchitected:CreateReviewTemplate": {}, - "wellarchitected:CreateWorkload": {}, - "wellarchitected:GetConsolidatedReport": {}, - "wellarchitected:GetProfileTemplate": {}, - "wellarchitected:ImportLens": {}, - "wellarchitected:ListLenses": {}, - "wellarchitected:ListNotifications": {}, - "wellarchitected:ListProfileNotifications": {}, - "wellarchitected:ListProfiles": {}, - "wellarchitected:ListReviewTemplates": {}, - "wellarchitected:ListShareInvitations": {}, - "wellarchitected:ListWorkloads": {}, - "wellarchitected:UpdateGlobalSettings": {}, - "wellarchitected:UpdateShareInvitation": {}, - "wickr:CreateNetwork": {}, - "wickr:ListNetworks": {}, - "wickr:ListTagsForResource": {}, - "wisdom:CreateAssistant": {}, - "wisdom:CreateKnowledgeBase": {}, - "wisdom:ListAssistants": {}, - "wisdom:ListKnowledgeBases": {}, - "wisdom:ListTagsForResource": {}, - "workdocs:AbortDocumentVersionUpload": {}, - "workdocs:ActivateUser": {}, - "workdocs:AddNotificationPermissions": {}, - "workdocs:AddResourcePermissions": {}, - "workdocs:AddUserToGroup": {}, - "workdocs:CheckAlias": {}, - "workdocs:CreateComment": {}, - "workdocs:CreateCustomMetadata": {}, - "workdocs:CreateFolder": {}, - "workdocs:CreateInstance": {}, - "workdocs:CreateLabels": {}, - "workdocs:CreateNotificationSubscription": {}, - "workdocs:CreateUser": {}, - "workdocs:DeactivateUser": {}, - "workdocs:DeleteComment": {}, - "workdocs:DeleteCustomMetadata": {}, - "workdocs:DeleteDocument": {}, - "workdocs:DeleteDocumentVersion": {}, - "workdocs:DeleteFolder": {}, - "workdocs:DeleteFolderContents": {}, - "workdocs:DeleteInstance": {}, - "workdocs:DeleteLabels": {}, - "workdocs:DeleteNotificationPermissions": {}, - "workdocs:DeleteNotificationSubscription": {}, - "workdocs:DeleteUser": {}, - "workdocs:DeregisterDirectory": {}, - "workdocs:DescribeActivities": {}, - "workdocs:DescribeAvailableDirectories": {}, - "workdocs:DescribeComments": {}, - "workdocs:DescribeDocumentVersions": {}, - "workdocs:DescribeFolderContents": {}, - "workdocs:DescribeGroups": {}, - "workdocs:DescribeInstances": {}, - "workdocs:DescribeNotificationPermissions": {}, - "workdocs:DescribeNotificationSubscriptions": {}, - "workdocs:DescribeResourcePermissions": {}, - "workdocs:DescribeRootFolders": {}, - "workdocs:DescribeUsers": {}, - "workdocs:DownloadDocumentVersion": {}, - "workdocs:GetCurrentUser": {}, - "workdocs:GetDocument": {}, - "workdocs:GetDocumentPath": {}, - "workdocs:GetDocumentVersion": {}, - "workdocs:GetFolder": {}, - "workdocs:GetFolderPath": {}, - "workdocs:GetGroup": {}, - "workdocs:GetResources": {}, - "workdocs:InitiateDocumentVersionUpload": {}, - "workdocs:RegisterDirectory": {}, - "workdocs:RemoveAllResourcePermissions": {}, - "workdocs:RemoveResourcePermission": {}, - "workdocs:RestoreDocumentVersions": {}, - "workdocs:SearchResources": {}, - "workdocs:UpdateDocument": {}, - "workdocs:UpdateDocumentVersion": {}, - "workdocs:UpdateFolder": {}, - "workdocs:UpdateInstanceAlias": {}, - "workdocs:UpdateUser": {}, - "workdocs:UpdateUserAdministrativeSettings": {}, - "worklink:CreateFleet": {}, - "worklink:ListFleets": {}, - "workmail:CreateOrganization": {}, - "workmail:DescribeDirectories": {}, - "workmail:DescribeKmsKeys": {}, - "workmail:DescribeOrganizations": {}, - "workmail:ListOrganizations": {}, - "workspaces-web:CreateBrowserSettings": {}, - "workspaces-web:CreateIpAccessSettings": {}, - "workspaces-web:CreateNetworkSettings": {}, - "workspaces-web:CreatePortal": {}, - "workspaces-web:CreateTrustStore": {}, - "workspaces-web:CreateUserAccessLoggingSettings": {}, - "workspaces-web:CreateUserSettings": {}, - "workspaces-web:ListBrowserSettings": {}, - "workspaces-web:ListIpAccessSettings": {}, - "workspaces-web:ListNetworkSettings": {}, - "workspaces-web:ListPortals": {}, - "workspaces-web:ListTagsForResource": {}, - "workspaces-web:ListTrustStoreCertificates": {}, - "workspaces-web:ListTrustStores": {}, - "workspaces-web:ListUserAccessLoggingSettings": {}, - "workspaces-web:ListUserSettings": {}, - "workspaces:CreateConnectionAlias": {}, - "workspaces:CreateIpGroup": {}, - "workspaces:CreateTags": {}, - "workspaces:DeleteTags": {}, - "workspaces:DescribeAccount": {}, - "workspaces:DescribeAccountModifications": {}, - "workspaces:DescribeApplications": {}, - "workspaces:DescribeConnectionAliases": {}, - "workspaces:DescribeTags": {}, - "workspaces:DescribeWorkspaceBundles": {}, - "workspaces:DescribeWorkspaceDirectories": {}, - "workspaces:DescribeWorkspaceImages": {}, - "workspaces:DescribeWorkspaces": {}, - "workspaces:DescribeWorkspacesConnectionStatus": {}, - "workspaces:ImportWorkspaceImage": {}, - "workspaces:ListAvailableManagementCidrRanges": {}, - "workspaces:ModifyAccount": {}, - "xray:BatchGetTraceSummaryById": {}, - "xray:BatchGetTraces": {}, - "xray:DeleteResourcePolicy": {}, - "xray:GetDistinctTraceGraphs": {}, - "xray:GetEncryptionConfig": {}, - "xray:GetGroups": {}, - "xray:GetInsight": {}, - "xray:GetInsightEvents": {}, - "xray:GetInsightImpactGraph": {}, - "xray:GetInsightSummaries": {}, - "xray:GetSamplingRules": {}, - "xray:GetSamplingStatisticSummaries": {}, - "xray:GetSamplingTargets": {}, - "xray:GetServiceGraph": {}, - "xray:GetTimeSeriesServiceStatistics": {}, - "xray:GetTraceGraph": {}, - "xray:GetTraceSummaries": {}, - "xray:Link": {}, - "xray:ListResourcePolicies": {}, - "xray:PutEncryptionConfig": {}, - "xray:PutResourcePolicy": {}, - "xray:PutTelemetryRecords": {}, - "xray:PutTraceSegments": {}, -} diff --git a/pkg/iac/providers/aws/iam/iam.go b/pkg/iac/providers/aws/iam/iam.go index 7bec336a8960..9a90a857c9d7 100644 --- a/pkg/iac/providers/aws/iam/iam.go +++ b/pkg/iac/providers/aws/iam/iam.go @@ -1,8 +1,7 @@ package iam import ( - "github.com/liamg/iamgo" - + "github.com/aquasecurity/iamgo" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" ) diff --git a/pkg/iac/providers/aws/iam/wildcards.go b/pkg/iac/providers/aws/iam/wildcards.go deleted file mode 100755 index bee5c4e9637c..000000000000 --- a/pkg/iac/providers/aws/iam/wildcards.go +++ /dev/null @@ -1,10 +0,0 @@ -package iam - -func IsWildcardAllowed(actions ...string) (bool, string) { - for _, action := range actions { - if _, exist := allowedActionsForResourceWildcardsMap[action]; !exist { - return false, action - } - } - return true, "" -} diff --git a/pkg/iac/rego/embed.go b/pkg/iac/rego/embed.go index c5416f50c0cc..71110d7fd7b7 100644 --- a/pkg/iac/rego/embed.go +++ b/pkg/iac/rego/embed.go @@ -13,6 +13,7 @@ import ( checks "github.com/aquasecurity/trivy-checks" "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) var LoadAndRegister = sync.OnceFunc(func() { @@ -49,7 +50,7 @@ func RegisterRegoRules(modules map[string]*ast.Module) { } retriever := NewMetadataRetriever(compiler) - regoCheckIDs := make(map[string]struct{}) + regoCheckIDs := set.New[string]() for _, module := range modules { metadata, err := retriever.RetrieveMetadata(ctx, module) @@ -66,7 +67,7 @@ func RegisterRegoRules(modules map[string]*ast.Module) { } if !metadata.Deprecated { - regoCheckIDs[metadata.AVDID] = struct{}{} + regoCheckIDs.Append(metadata.AVDID) } rules.Register(metadata.ToRule()) diff --git a/pkg/iac/rego/load.go b/pkg/iac/rego/load.go index 7356384a3327..dba0eda4917d 100644 --- a/pkg/iac/rego/load.go +++ b/pkg/iac/rego/load.go @@ -12,16 +12,13 @@ import ( "github.com/samber/lo" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) -var builtinNamespaces = map[string]struct{}{ - "builtin": {}, - "defsec": {}, - "appshield": {}, -} +var builtinNamespaces = set.New("builtin", "defsec", "appshield") func BuiltinNamespaces() []string { - return lo.Keys(builtinNamespaces) + return builtinNamespaces.Items() } func IsBuiltinNamespace(namespace string) bool { @@ -122,15 +119,12 @@ func (s *Scanner) LoadPolicies(srcFS fs.FS) error { } // gather namespaces - uniq := make(map[string]struct{}) + uniq := set.New[string]() for _, module := range s.policies { namespace := getModuleNamespace(module) - uniq[namespace] = struct{}{} - } - var namespaces []string - for namespace := range uniq { - namespaces = append(namespaces, namespace) + uniq.Append(namespace) } + namespaces := uniq.Items() dataFS := srcFS if s.dataFS != nil { @@ -296,7 +290,7 @@ func (s *Scanner) filterModules(retriever *MetadataRetriever) error { } if IsBuiltinNamespace(getModuleNamespace(module)) { - if _, disabled := s.disabledCheckIDs[meta.ID]; disabled { // ignore builtin disabled checks + if s.disabledCheckIDs.Contains(meta.ID) { // ignore builtin disabled checks continue } } diff --git a/pkg/iac/rego/metadata.go b/pkg/iac/rego/metadata.go index ac2eb84a36d2..637b30ea5122 100644 --- a/pkg/iac/rego/metadata.go +++ b/pkg/iac/rego/metadata.go @@ -2,6 +2,7 @@ package rego import ( "context" + "errors" "fmt" "strings" @@ -39,6 +40,7 @@ type StaticMetadata struct { Library bool CloudFormation *scan.EngineMetadata Terraform *scan.EngineMetadata + Examples string } func NewStaticMetadata(pkgPath string, inputOpt InputOptions) *StaticMetadata { @@ -75,6 +77,7 @@ func (sm *StaticMetadata) update(meta map[string]any) error { upd(&sm.Provider, "provider") upd(&sm.RecommendedActions, "recommended_actions") upd(&sm.RecommendedActions, "recommended_action") + upd(&sm.Examples, "examples") if raw, ok := meta["deprecated"]; ok { if dep, ok := raw.(bool); ok { @@ -269,6 +272,7 @@ func (m StaticMetadata) ToRule() scan.Rule { Frameworks: m.Frameworks, CloudFormation: m.CloudFormation, Terraform: m.Terraform, + Examples: m.Examples, } } @@ -329,15 +333,15 @@ func (m *MetadataRetriever) RetrieveMetadata(ctx context.Context, module *ast.Mo } if len(set) != 1 { - return nil, fmt.Errorf("failed to parse metadata: unexpected set length") + return nil, errors.New("failed to parse metadata: unexpected set length") } if len(set[0].Expressions) != 1 { - return nil, fmt.Errorf("failed to parse metadata: unexpected expression length") + return nil, errors.New("failed to parse metadata: unexpected expression length") } expression := set[0].Expressions[0] meta, ok := expression.Value.(map[string]any) if !ok { - return nil, fmt.Errorf("failed to parse metadata: not an object") + return nil, errors.New("failed to parse metadata: not an object") } if err := metadata.update(meta); err != nil { diff --git a/pkg/iac/rego/options.go b/pkg/iac/rego/options.go index 79a1b951746d..31026b2f3b57 100644 --- a/pkg/iac/rego/options.go +++ b/pkg/iac/rego/options.go @@ -69,9 +69,7 @@ func WithDataDirs(paths ...string) options.ScannerOption { func WithPolicyNamespaces(namespaces ...string) options.ScannerOption { return func(s options.ConfigurableScanner) { if ss, ok := s.(*Scanner); ok { - for _, namespace := range namespaces { - ss.ruleNamespaces[namespace] = struct{}{} - } + ss.ruleNamespaces.Append(namespaces...) } } } @@ -112,9 +110,7 @@ func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption { func WithDisabledCheckIDs(ids ...string) options.ScannerOption { return func(s options.ConfigurableScanner) { if ss, ok := s.(*Scanner); ok { - for _, id := range ids { - ss.disabledCheckIDs[id] = struct{}{} - } + ss.disabledCheckIDs.Append(ids...) } } } diff --git a/pkg/iac/rego/result.go b/pkg/iac/rego/result.go index c4045705249c..87723a11ee3d 100644 --- a/pkg/iac/rego/result.go +++ b/pkg/iac/rego/result.go @@ -121,7 +121,7 @@ func parseLineNumber(raw any) int { return n } -func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace, rule string, traces []string) scan.Results { +func (s *Scanner) convertResults(resultSet rego.ResultSet, input Input, namespace, rule string, traces []string) scan.Results { var results scan.Results offset := 0 @@ -136,7 +136,7 @@ func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace, rul } } } - for _, result := range set { + for _, result := range resultSet { for _, expression := range result.Expressions { values, ok := expression.Value.([]any) if !ok { diff --git a/pkg/iac/rego/scanner.go b/pkg/iac/rego/scanner.go index c46e580ac3bd..70bb98dd6bf4 100644 --- a/pkg/iac/rego/scanner.go +++ b/pkg/iac/rego/scanner.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "io/fs" - "maps" "strings" "github.com/open-policy-agent/opa/ast" @@ -22,29 +21,26 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) -var checkTypesWithSubtype = map[types.Source]struct{}{ - types.SourceCloud: {}, - types.SourceDefsec: {}, - types.SourceKubernetes: {}, -} +var checkTypesWithSubtype = set.New[types.Source](types.SourceCloud, types.SourceDefsec, types.SourceKubernetes) var supportedProviders = makeSupportedProviders() -func makeSupportedProviders() map[string]struct{} { - m := make(map[string]struct{}) +func makeSupportedProviders() set.Set[string] { + m := set.New[string]() for _, p := range providers.AllProviders() { - m[string(p)] = struct{}{} + m.Append(string(p)) } - m["kind"] = struct{}{} // kubernetes + m.Append("kind") // kubernetes return m } var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - ruleNamespaces map[string]struct{} + ruleNamespaces set.Set[string] policies map[string]*ast.Module store storage.Store runtimeValues *ast.Term @@ -70,7 +66,7 @@ type Scanner struct { embeddedChecks map[string]*ast.Module customSchemas map[string][]byte - disabledCheckIDs map[string]struct{} + disabledCheckIDs set.Set[string] } func (s *Scanner) trace(heading string, input any) { @@ -103,15 +99,13 @@ func NewScanner(source types.Source, opts ...options.ScannerOption) *Scanner { s := &Scanner{ regoErrorLimit: ast.CompileErrorLimitDefault, sourceType: source, - ruleNamespaces: make(map[string]struct{}), + ruleNamespaces: builtinNamespaces.Clone(), runtimeValues: addRuntimeValues(), logger: log.WithPrefix("rego"), customSchemas: make(map[string][]byte), - disabledCheckIDs: make(map[string]struct{}), + disabledCheckIDs: set.New[string](), } - maps.Copy(s.ruleNamespaces, builtinNamespaces) - for _, opt := range opts { opt(s) } @@ -147,7 +141,7 @@ func (s *Scanner) runQuery(ctx context.Context, query string, input ast.Value, d } instance := rego.New(regoOptions...) - set, err := instance.Eval(ctx) + resultSet, err := instance.Eval(ctx) if err != nil { return nil, nil, err } @@ -165,7 +159,7 @@ func (s *Scanner) runQuery(ctx context.Context, query string, input ast.Value, d traces = strings.Split(traceBuffer.String(), "\n") } } - return set, traces, nil + return resultSet, traces, nil } type Input struct { @@ -198,7 +192,7 @@ func (s *Scanner) ScanInput(ctx context.Context, inputs ...Input) (scan.Results, namespace := getModuleNamespace(module) topLevel := strings.Split(namespace, ".")[0] - if _, ok := s.ruleNamespaces[topLevel]; !ok { + if !s.ruleNamespaces.Contains(topLevel) { continue } @@ -227,15 +221,15 @@ func (s *Scanner) ScanInput(ctx context.Context, inputs ...Input) (scan.Results, continue } - usedRules := make(map[string]struct{}) + usedRules := set.New[string]() // all rules for _, rule := range module.Rules { ruleName := rule.Head.Name.String() - if _, ok := usedRules[ruleName]; ok { + if usedRules.Contains(ruleName) { continue } - usedRules[ruleName] = struct{}{} + usedRules.Append(ruleName) if isEnforcedRule(ruleName) { ruleResults, err := s.applyRule(ctx, namespace, ruleName, inputs) if err != nil { @@ -257,8 +251,7 @@ func (s *Scanner) ScanInput(ctx context.Context, inputs ...Input) (scan.Results, } func isPolicyWithSubtype(sourceType types.Source) bool { - _, exists := checkTypesWithSubtype[sourceType] - return exists + return checkTypesWithSubtype.Contains(sourceType) } func checkSubtype(ii map[string]any, provider string, subTypes []SubType) bool { @@ -290,7 +283,7 @@ func isPolicyApplicable(staticMetadata *StaticMetadata, inputs ...Input) bool { for _, input := range inputs { if ii, ok := input.Contents.(map[string]any); ok { for provider := range ii { - if _, exists := supportedProviders[provider]; !exists { + if !supportedProviders.Contains(provider) { continue } @@ -329,12 +322,12 @@ func (s *Scanner) applyRule(ctx context.Context, namespace, rule string, inputs continue } - set, traces, err := s.runQuery(ctx, qualified, parsedInput, false) + resultSet, traces, err := s.runQuery(ctx, qualified, parsedInput, false) if err != nil { return nil, err } - s.trace("RESULTSET", set) - ruleResults := s.convertResults(set, input, namespace, rule, traces) + s.trace("RESULTSET", resultSet) + ruleResults := s.convertResults(resultSet, input, namespace, rule, traces) if len(ruleResults) == 0 { // It passed because we didn't find anything wrong (NOT because it didn't exist) var result regoResult result.FS = input.FS diff --git a/pkg/iac/rego/schemas/builder.go b/pkg/iac/rego/schemas/builder.go index 649bf0a1aacf..38f3c0c13594 100644 --- a/pkg/iac/rego/schemas/builder.go +++ b/pkg/iac/rego/schemas/builder.go @@ -1,6 +1,7 @@ package schemas import ( + "errors" "fmt" "reflect" "strings" @@ -56,7 +57,7 @@ func (b *builder) fromInput(inputValue reflect.Value) error { return err } if prop == nil { - return fmt.Errorf("property is nil") + return errors.New("property is nil") } b.schema.Properties = prop.Properties b.schema.Type = prop.Type diff --git a/pkg/iac/rules/register.go b/pkg/iac/rules/register.go index e07268255417..207502672c51 100755 --- a/pkg/iac/rules/register.go +++ b/pkg/iac/rules/register.go @@ -10,6 +10,7 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/scan" dftypes "github.com/aquasecurity/trivy/pkg/iac/types" ruleTypes "github.com/aquasecurity/trivy/pkg/iac/types/rules" + "github.com/aquasecurity/trivy/pkg/set" ) type registry struct { @@ -74,14 +75,14 @@ func (r *registry) getFrameworkRules(fw ...framework.Framework) []ruleTypes.Regi if len(fw) == 0 { fw = []framework.Framework{framework.Default} } - unique := make(map[int]struct{}) + unique := set.New[int]() for _, f := range fw { for _, rule := range r.frameworks[f] { - if _, ok := unique[rule.Number]; ok { + if unique.Contains(rule.Number) { continue } registered = append(registered, rule) - unique[rule.Number] = struct{}{} + unique.Append(rule.Number) } } return registered diff --git a/pkg/iac/scan/code.go b/pkg/iac/scan/code.go index 8388dd4dbf6e..11bd27813dfc 100644 --- a/pkg/iac/scan/code.go +++ b/pkg/iac/scan/code.go @@ -2,6 +2,7 @@ package scan import ( "bufio" + "errors" "fmt" "io/fs" "path/filepath" @@ -141,7 +142,7 @@ func (r *Result) GetCode(opts ...CodeOption) (*Code, error) { fsys := r.Metadata().Range().GetFS() if fsys == nil { - return nil, fmt.Errorf("code unavailable: result was not mapped to a known filesystem") + return nil, errors.New("code unavailable: result was not mapped to a known filesystem") } innerRange := r.metadata.Range() diff --git a/pkg/iac/scan/result.go b/pkg/iac/scan/result.go index 9c9e8c5e3274..f00e5691836e 100644 --- a/pkg/iac/scan/result.go +++ b/pkg/iac/scan/result.go @@ -5,6 +5,7 @@ import ( "io/fs" "path/filepath" "reflect" + "strconv" "strings" "github.com/aquasecurity/trivy/pkg/iac/ignore" @@ -311,9 +312,9 @@ func rawToString(raw any) string { } switch t := raw.(type) { case int: - return fmt.Sprintf("%d", t) + return strconv.Itoa(t) case bool: - return fmt.Sprintf("%t", t) + return strconv.FormatBool(t) case float64: return fmt.Sprintf("%f", t) case string: diff --git a/pkg/iac/scan/rule.go b/pkg/iac/scan/rule.go index 96db0007ffcc..0ed48d8a6145 100755 --- a/pkg/iac/scan/rule.go +++ b/pkg/iac/scan/rule.go @@ -50,6 +50,7 @@ type Rule struct { Severity severity.Severity `json:"severity"` Terraform *EngineMetadata `json:"terraform,omitempty"` CloudFormation *EngineMetadata `json:"cloud_formation,omitempty"` + Examples string `json:"-"` CustomChecks CustomChecks `json:"-"` RegoPackage string `json:"-"` Frameworks map[framework.Framework][]string `json:"frameworks"` diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/decode.go b/pkg/iac/scanners/azure/arm/parser/armjson/decode.go index c0c476db7681..dcce24f3a5d9 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/decode.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/decode.go @@ -1,6 +1,7 @@ package armjson import ( + "errors" "fmt" "reflect" @@ -40,7 +41,7 @@ func (n *node) decodeToValue(v reflect.Value) error { } if !v.CanSet() { - return fmt.Errorf("target is not settable") + return errors.New("target is not settable") } switch n.kind { @@ -59,7 +60,7 @@ func (n *node) decodeToValue(v reflect.Value) error { case KindComment: return n.decodeString(v) case KindUnknown: - return fmt.Errorf("cannot decode unknown kind") + return errors.New("cannot decode unknown kind") default: return fmt.Errorf("decoding of kind 0x%x is not supported", n.kind) } diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/decode_array.go b/pkg/iac/scanners/azure/arm/parser/armjson/decode_array.go index 483880814383..457b78b5f0d7 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/decode_array.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/decode_array.go @@ -1,7 +1,7 @@ package armjson import ( - "fmt" + "errors" "reflect" ) @@ -14,7 +14,7 @@ func (n *node) decodeArray(v reflect.Value) error { switch v.Kind() { case reflect.Array: if v.Len() != length { - return fmt.Errorf("invalid length") + return errors.New("invalid length") } case reflect.Slice: v.Set(reflect.MakeSlice(v.Type(), length, length)) @@ -24,7 +24,7 @@ func (n *node) decodeArray(v reflect.Value) error { v = reflect.New(slice.Type()).Elem() v.Set(slice) default: - return fmt.Errorf("invalid target type") + return errors.New("invalid target type") } elementType := v.Type().Elem() diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/decode_number.go b/pkg/iac/scanners/azure/arm/parser/armjson/decode_number.go index 653f6f1fbe06..4b477e89ca70 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/decode_number.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/decode_number.go @@ -1,6 +1,7 @@ package armjson import ( + "errors" "fmt" "reflect" ) @@ -42,5 +43,5 @@ func (n *node) decodeNumber(v reflect.Value) error { return fmt.Errorf("cannot decode number value to %s target", v.Kind()) } - return fmt.Errorf("internal value is not numeric") + return errors.New("internal value is not numeric") } diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/decode_object.go b/pkg/iac/scanners/azure/arm/parser/armjson/decode_object.go index fdc58f6c8e34..5d7e15357007 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/decode_object.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/decode_object.go @@ -1,6 +1,7 @@ package armjson import ( + "errors" "fmt" "reflect" "strings" @@ -54,19 +55,19 @@ func (n *node) decodeObjectToMap(v reflect.Value) error { func (n *node) objectAsMap() (map[string]Node, error) { if n.kind != KindObject { - return nil, fmt.Errorf("not an object") + return nil, errors.New("not an object") } properties := make(map[string]Node) contents := n.content for i := 0; i < len(contents); i += 2 { key := contents[i] if key.Kind() != KindString { - return nil, fmt.Errorf("invalid object key - please report this bug") + return nil, errors.New("invalid object key - please report this bug") } keyStr := key.(*node).raw.(string) if i+1 >= len(contents) { - return nil, fmt.Errorf("missing object value - please report this bug") + return nil, errors.New("missing object value - please report this bug") } properties[keyStr] = contents[i+1] } diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/parse_boolean.go b/pkg/iac/scanners/azure/arm/parser/armjson/parse_boolean.go index 30903ea85973..59a5fffb114b 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/parse_boolean.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/parse_boolean.go @@ -1,7 +1,7 @@ package armjson import ( - "fmt" + "errors" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -21,7 +21,7 @@ func (p *parser) parseBoolean(parentMetadata *types.Metadata) (Node, error) { if r == 't' { for _, expected := range trueRunes { if !p.swallowIfEqual(expected) { - return nil, fmt.Errorf("unexpected character in boolean value") + return nil, errors.New("unexpected character in boolean value") } } n.raw = true @@ -31,7 +31,7 @@ func (p *parser) parseBoolean(parentMetadata *types.Metadata) (Node, error) { for _, expected := range falseRunes { if !p.swallowIfEqual(expected) { - return nil, fmt.Errorf("unexpected character in boolean value") + return nil, errors.New("unexpected character in boolean value") } } n.raw = false diff --git a/pkg/iac/scanners/azure/arm/parser/armjson/parse_null.go b/pkg/iac/scanners/azure/arm/parser/armjson/parse_null.go index 1a0011ec5dac..0ae20a8c9edf 100644 --- a/pkg/iac/scanners/azure/arm/parser/armjson/parse_null.go +++ b/pkg/iac/scanners/azure/arm/parser/armjson/parse_null.go @@ -1,7 +1,7 @@ package armjson import ( - "fmt" + "errors" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -14,7 +14,7 @@ func (p *parser) parseNull(parentMetadata *types.Metadata) (Node, error) { for _, expected := range nullRunes { if !p.swallowIfEqual(expected) { - return nil, fmt.Errorf("unexpected character") + return nil, errors.New("unexpected character") } } n.raw = nil diff --git a/pkg/iac/scanners/azure/expressions/lex.go b/pkg/iac/scanners/azure/expressions/lex.go index f5cfb2a34705..6bbb4717e745 100644 --- a/pkg/iac/scanners/azure/expressions/lex.go +++ b/pkg/iac/scanners/azure/expressions/lex.go @@ -2,6 +2,7 @@ package expressions import ( "bufio" + "errors" "fmt" "strconv" "strings" @@ -119,7 +120,7 @@ func (l *lexer) lexString(terminator rune) (Token, error) { func (l *lexer) readEscapedChar() (rune, error) { r, err := l.read() if err != nil { - return 0, fmt.Errorf("unexpected EOF") + return 0, errors.New("unexpected EOF") } switch r { case 'n': diff --git a/pkg/iac/scanners/azure/functions/date_time_add.go b/pkg/iac/scanners/azure/functions/date_time_add.go index bbd03b47bdfa..2e3c06ae8220 100644 --- a/pkg/iac/scanners/azure/functions/date_time_add.go +++ b/pkg/iac/scanners/azure/functions/date_time_add.go @@ -1,6 +1,7 @@ package functions import ( + "errors" "fmt" "regexp" "strconv" @@ -65,7 +66,7 @@ func parseISO8601(from string) (Iso8601Duration, error) { if pattern.MatchString(from) { match = pattern.FindStringSubmatch(from) } else { - return d, fmt.Errorf("could not parse duration string") + return d, errors.New("could not parse duration string") } for i, name := range pattern.SubexpNames() { diff --git a/pkg/iac/scanners/azure/functions/unique_string.go b/pkg/iac/scanners/azure/functions/unique_string.go index 1411d2b1fdc0..72b5fb5aabc6 100644 --- a/pkg/iac/scanners/azure/functions/unique_string.go +++ b/pkg/iac/scanners/azure/functions/unique_string.go @@ -2,7 +2,7 @@ package functions import ( "crypto/sha256" - "fmt" + "encoding/hex" "strings" ) @@ -17,5 +17,5 @@ func UniqueString(args ...any) any { } hash := sha256.New().Sum([]byte(strings.Join(hashParts, ""))) - return fmt.Sprintf("%x", hash)[:13] + return hex.EncodeToString(hash)[:13] } diff --git a/pkg/iac/scanners/azure/functions/utc_now_test.go b/pkg/iac/scanners/azure/functions/utc_now_test.go index 5ee8a3c78021..94263af9f9aa 100644 --- a/pkg/iac/scanners/azure/functions/utc_now_test.go +++ b/pkg/iac/scanners/azure/functions/utc_now_test.go @@ -2,6 +2,7 @@ package functions import ( "fmt" + "strconv" "testing" "time" @@ -20,7 +21,7 @@ func Test_UTCNow(t *testing.T) { args: []any{ "d", }, - expected: fmt.Sprintf("%d", time.Now().UTC().Day()), + expected: strconv.Itoa(time.Now().UTC().Day()), }, { name: "utc now date", diff --git a/pkg/iac/scanners/cloudformation/parser/fn_builtin.go b/pkg/iac/scanners/cloudformation/parser/fn_builtin.go index 3fb21dca82de..6859fa0f4ff2 100644 --- a/pkg/iac/scanners/cloudformation/parser/fn_builtin.go +++ b/pkg/iac/scanners/cloudformation/parser/fn_builtin.go @@ -1,7 +1,7 @@ package parser import ( - "fmt" + "errors" "net" "github.com/apparentlymart/go-cidr/cidr" @@ -55,7 +55,7 @@ func calculateCidrs(ipaddress string, count, bit int, original *Property) ([]*Pr for i := 0; i < count; i++ { next, err := cidr.Subnet(network, bit, i) if err != nil { - return nil, fmt.Errorf("failed to create cidr blocks") + return nil, errors.New("failed to create cidr blocks") } cidrProperties = append(cidrProperties, original.deriveResolved(cftypes.String, next.String())) diff --git a/pkg/iac/scanners/cloudformation/parser/fn_sub.go b/pkg/iac/scanners/cloudformation/parser/fn_sub.go index 52db66cf9757..ad990bba3b32 100644 --- a/pkg/iac/scanners/cloudformation/parser/fn_sub.go +++ b/pkg/iac/scanners/cloudformation/parser/fn_sub.go @@ -46,7 +46,7 @@ func resolveMapSub(refValue, original *Property) (*Property, bool) { case cftypes.Int: replacement = strconv.Itoa(v.AsInt()) case cftypes.Bool: - replacement = fmt.Sprintf("%v", v.AsBool()) + replacement = strconv.FormatBool(v.AsBool()) case cftypes.List: var parts []string for _, p := range v.AsList() { diff --git a/pkg/iac/scanners/cloudformation/parser/parameter.go b/pkg/iac/scanners/cloudformation/parser/parameter.go index 20e2011417d5..4cfdfd1705b6 100644 --- a/pkg/iac/scanners/cloudformation/parser/parameter.go +++ b/pkg/iac/scanners/cloudformation/parser/parameter.go @@ -3,13 +3,14 @@ package parser import ( "bytes" "encoding/json" + "errors" "fmt" "strconv" "strings" - "github.com/liamg/jfather" "gopkg.in/yaml.v3" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/cftypes" ) @@ -137,7 +138,7 @@ func (p *Parameters) UnmarshalJSON(data []byte) error { (*p)[param.ParameterKey] = param.ParameterValue } default: - return fmt.Errorf("unsupported parameters format") + return errors.New("unsupported parameters format") } return nil diff --git a/pkg/iac/scanners/cloudformation/parser/parser.go b/pkg/iac/scanners/cloudformation/parser/parser.go index 24d85ba4bbbb..eda88408ec06 100644 --- a/pkg/iac/scanners/cloudformation/parser/parser.go +++ b/pkg/iac/scanners/cloudformation/parser/parser.go @@ -11,9 +11,9 @@ import ( "strings" "github.com/hashicorp/go-multierror" - "github.com/liamg/jfather" "gopkg.in/yaml.v3" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/iac/ignore" "github.com/aquasecurity/trivy/pkg/log" ) diff --git a/pkg/iac/scanners/cloudformation/parser/property.go b/pkg/iac/scanners/cloudformation/parser/property.go index 4748126e0892..606b9d28b341 100644 --- a/pkg/iac/scanners/cloudformation/parser/property.go +++ b/pkg/iac/scanners/cloudformation/parser/property.go @@ -6,9 +6,9 @@ import ( "strconv" "strings" - "github.com/liamg/jfather" "gopkg.in/yaml.v3" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/cftypes" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" ) diff --git a/pkg/iac/scanners/cloudformation/parser/property_conversion.go b/pkg/iac/scanners/cloudformation/parser/property_conversion.go index d1ef23d396f2..1053afa1b3f7 100644 --- a/pkg/iac/scanners/cloudformation/parser/property_conversion.go +++ b/pkg/iac/scanners/cloudformation/parser/property_conversion.go @@ -2,11 +2,11 @@ package parser import ( "fmt" - "os" "strconv" "strings" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/cftypes" + "github.com/aquasecurity/trivy/pkg/log" ) func (p *Property) IsConvertableTo(conversionType cftypes.CfType) bool { @@ -75,7 +75,11 @@ func (p *Property) ConvertTo(conversionType cftypes.CfType) *Property { } if !p.IsConvertableTo(conversionType) { - _, _ = fmt.Fprintf(os.Stderr, "property of type %s cannot be converted to %s\n", p.Type(), conversionType) + log.Debug("Failed to convert property", + log.String("from", string(p.Type())), + log.String("to", string(conversionType)), + log.Any("range", p.Range().String()), + ) return p } switch conversionType { @@ -94,7 +98,7 @@ func (p *Property) convertToString() *Property { case cftypes.Int: return p.deriveResolved(cftypes.String, strconv.Itoa(p.AsInt())) case cftypes.Bool: - return p.deriveResolved(cftypes.String, fmt.Sprintf("%v", p.AsBool())) + return p.deriveResolved(cftypes.String, strconv.FormatBool(p.AsBool())) case cftypes.List: var parts []string for _, property := range p.AsList() { diff --git a/pkg/iac/scanners/cloudformation/parser/resource.go b/pkg/iac/scanners/cloudformation/parser/resource.go index ed4b2834d573..b5910c144bcf 100644 --- a/pkg/iac/scanners/cloudformation/parser/resource.go +++ b/pkg/iac/scanners/cloudformation/parser/resource.go @@ -4,9 +4,9 @@ import ( "io/fs" "strings" - "github.com/liamg/jfather" "gopkg.in/yaml.v3" + "github.com/aquasecurity/jfather" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" ) diff --git a/pkg/iac/scanners/cloudformation/parser/util.go b/pkg/iac/scanners/cloudformation/parser/util.go index 5ee61de17b9d..c6babcb7a8f3 100644 --- a/pkg/iac/scanners/cloudformation/parser/util.go +++ b/pkg/iac/scanners/cloudformation/parser/util.go @@ -3,9 +3,9 @@ package parser import ( "strconv" - "github.com/liamg/jfather" "gopkg.in/yaml.v3" + "github.com/aquasecurity/jfather" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/cftypes" "github.com/aquasecurity/trivy/pkg/iac/scanners/kubernetes/parser" ) diff --git a/pkg/iac/scanners/dockerfile/parser/parser.go b/pkg/iac/scanners/dockerfile/parser/parser.go index 128d9515e8b1..2079b269f124 100644 --- a/pkg/iac/scanners/dockerfile/parser/parser.go +++ b/pkg/iac/scanners/dockerfile/parser/parser.go @@ -30,7 +30,7 @@ func Parse(_ context.Context, r io.Reader, path string) (any, error) { instr, err := instructions.ParseInstruction(child) if err != nil { - return nil, fmt.Errorf("process dockerfile instructions: %w", err) + return nil, fmt.Errorf("parse dockerfile instruction: %w", err) } if _, ok := instr.(*instructions.Stage); ok { @@ -56,14 +56,27 @@ func Parse(_ context.Context, r io.Reader, path string) (any, error) { EndLine: child.EndLine, } + // processing statement with sub-statement + // example: ONBUILD RUN foo bar + // https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#onbuild if child.Next != nil && len(child.Next.Children) > 0 { cmd.SubCmd = child.Next.Children[0].Value child = child.Next.Children[0] } + // mark if the instruction is in exec form + // https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#exec-form cmd.JSON = child.Attributes["json"] - for n := child.Next; n != nil; n = n.Next { - cmd.Value = append(cmd.Value, n.Value) + + // heredoc may contain a script that will be executed in the shell, so we need to process it + // https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#here-documents + if len(child.Heredocs) > 0 && child.Next != nil { + cmd.Original = originalFromHeredoc(child) + cmd.Value = []string{processHeredoc(child)} + } else { + for n := child.Next; n != nil; n = n.Next { + cmd.Value = append(cmd.Value, n.Value) + } } stage.Commands = append(stage.Commands, cmd) @@ -75,3 +88,44 @@ func Parse(_ context.Context, r io.Reader, path string) (any, error) { return &parsedFile, nil } + +func originalFromHeredoc(node *parser.Node) string { + var sb strings.Builder + sb.WriteString(node.Original) + sb.WriteRune('\n') + for i, heredoc := range node.Heredocs { + sb.WriteString(heredoc.Content) + sb.WriteString(heredoc.Name) + if i != len(node.Heredocs)-1 { + sb.WriteRune('\n') + } + } + + return sb.String() +} + +// heredoc processing taken from here +// https://github.com/moby/buildkit/blob/9a39e2c112b7c98353c27e64602bc08f31fe356e/frontend/dockerfile/dockerfile2llb/convert.go#L1200 +func processHeredoc(node *parser.Node) string { + if parser.MustParseHeredoc(node.Next.Value) == nil || strings.HasPrefix(node.Heredocs[0].Content, "#!") { + // more complex heredoc is passed to the shell as is + var sb strings.Builder + sb.WriteString(node.Next.Value) + for _, heredoc := range node.Heredocs { + sb.WriteRune('\n') + sb.WriteString(heredoc.Content) + sb.WriteString(heredoc.Name) + } + return sb.String() + } + + // simple heredoc and the content is run in a shell + content := node.Heredocs[0].Content + if node.Heredocs[0].Chomp { + content = parser.ChompHeredocContent(content) + } + + content = strings.ReplaceAll(content, "\r\n", "\n") + cmds := strings.Split(strings.TrimSuffix(content, "\n"), "\n") + return strings.Join(cmds, " ; ") +} diff --git a/pkg/iac/scanners/dockerfile/parser/parser_test.go b/pkg/iac/scanners/dockerfile/parser/parser_test.go index ad1acf193bf3..ed73def7e9f8 100644 --- a/pkg/iac/scanners/dockerfile/parser/parser_test.go +++ b/pkg/iac/scanners/dockerfile/parser/parser_test.go @@ -59,3 +59,60 @@ CMD python /app/app.py assert.Equal(t, 4, commands[3].StartLine) assert.Equal(t, 4, commands[3].EndLine) } + +func Test_ParseHeredocs(t *testing.T) { + tests := []struct { + name string + src string + expected string + }{ + { + name: "multi-line script", + src: `RUN < /tmp/output && echo 'done' +hello +mr +potato +EOF`, + expected: "cat < /tmp/output && echo 'done'\nhello\nmr\npotato\nEOF", + }, + { + name: "redirect to file", + src: `RUN < /etc/config.yaml +key1: value1 +key2: value2 +EOF`, + expected: "< /etc/config.yaml\nkey1: value1\nkey2: value2\nEOF", + }, + { + name: "with a shebang", + src: `RUN < 2 { - return cty.UnknownVal(cty.String), fmt.Errorf("bcrypt() takes no more than two arguments") + return cty.UnknownVal(cty.String), errors.New("bcrypt() takes no more than two arguments") } input := args[0].AsString() diff --git a/pkg/iac/scanners/terraform/parser/funcs/datetime.go b/pkg/iac/scanners/terraform/parser/funcs/datetime.go index 11ed3c8a2214..12d73d58ba1c 100644 --- a/pkg/iac/scanners/terraform/parser/funcs/datetime.go +++ b/pkg/iac/scanners/terraform/parser/funcs/datetime.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "golang.org/x/xerrors" + "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/function" ) @@ -132,7 +134,7 @@ func parseTimestamp(ts string) (time.Time, error) { case "Z07:00": what = "UTC offset" case "T": - return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: missing required time introducer 'T'") + return time.Time{}, xerrors.New("not a valid RFC3339 timestamp: missing required time introducer 'T'") case ":", "-": if err.ValueElem == "" { return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: end of string where %q is expected", err.LayoutElem) diff --git a/pkg/iac/scanners/terraform/parser/funcs/encoding.go b/pkg/iac/scanners/terraform/parser/funcs/encoding.go index e5fb8490818f..75876dfd33f7 100644 --- a/pkg/iac/scanners/terraform/parser/funcs/encoding.go +++ b/pkg/iac/scanners/terraform/parser/funcs/encoding.go @@ -5,6 +5,7 @@ import ( "bytes" "compress/gzip" "encoding/base64" + "errors" "fmt" "log" "net/url" @@ -35,7 +36,7 @@ var Base64DecodeFunc = function.New(&function.Spec{ } if !utf8.Valid([]byte(sDec)) { log.Printf("[DEBUG] the result of decoding the provided string is not valid UTF-8: %s", redactIfSensitive(sDec, strMarks)) - return cty.UnknownVal(cty.String), fmt.Errorf("the result of decoding the provided string is not valid UTF-8") + return cty.UnknownVal(cty.String), errors.New("the result of decoding the provided string is not valid UTF-8") } return cty.StringVal(string(sDec)).WithMarks(strMarks), nil }, diff --git a/pkg/iac/scanners/terraform/parser/funcs/filesystem.go b/pkg/iac/scanners/terraform/parser/funcs/filesystem.go index a2b9bd0b57c9..84bb6c021584 100644 --- a/pkg/iac/scanners/terraform/parser/funcs/filesystem.go +++ b/pkg/iac/scanners/terraform/parser/funcs/filesystem.go @@ -137,7 +137,7 @@ func MakeTemplateFileFunc(target fs.FS, baseDir string, funcsCb func() map[strin funcs[name] = function.New(&function.Spec{ Params: params, Type: func(args []cty.Value) (cty.Type, error) { - return cty.NilType, fmt.Errorf("cannot recursively call templatefile from inside templatefile call") + return cty.NilType, errors.New("cannot recursively call templatefile from inside templatefile call") }, }) continue diff --git a/pkg/iac/scanners/terraform/parser/load_module.go b/pkg/iac/scanners/terraform/parser/load_module.go index 968f73df0673..878bf075baec 100644 --- a/pkg/iac/scanners/terraform/parser/load_module.go +++ b/pkg/iac/scanners/terraform/parser/load_module.go @@ -2,6 +2,7 @@ package parser import ( "context" + "errors" "fmt" "io/fs" "path" @@ -24,7 +25,7 @@ type ModuleDefinition struct { } func (d *ModuleDefinition) inputVars() map[string]cty.Value { - inputs := d.Definition.Values().AsValueMap() + inputs := d.Definition.NullableValues().AsValueMap() if inputs == nil { return make(map[string]cty.Value) } @@ -99,7 +100,7 @@ func (e *evaluator) loadModuleFromTerraformCache(ctx context.Context, b *terrafo } } if modulePath == "" { - return nil, fmt.Errorf("failed to load module from .terraform/modules") + return nil, errors.New("failed to load module from .terraform/modules") } if strings.HasPrefix(source, ".") { source = "" diff --git a/pkg/iac/scanners/terraform/parser/parser.go b/pkg/iac/scanners/terraform/parser/parser.go index 48ed799155ea..3427fa08f72f 100644 --- a/pkg/iac/scanners/terraform/parser/parser.go +++ b/pkg/iac/scanners/terraform/parser/parser.go @@ -90,6 +90,10 @@ func (p *Parser) newModuleParser(moduleFS fs.FS, moduleSource, modulePath, modul return mp } +func (p *Parser) Files() map[string]*hcl.File { + return p.underlying.Files() +} + func (p *Parser) ParseFile(_ context.Context, fullPath string) error { isJSON := strings.HasSuffix(fullPath, ".tf.json") diff --git a/pkg/iac/scanners/terraform/parser/parser_test.go b/pkg/iac/scanners/terraform/parser/parser_test.go index 82d7a42d2f63..e7e51a9598fd 100644 --- a/pkg/iac/scanners/terraform/parser/parser_test.go +++ b/pkg/iac/scanners/terraform/parser/parser_test.go @@ -2258,3 +2258,29 @@ resource "foo" "this" { }) } } + +func TestAttrRefToNullVariable(t *testing.T) { + fsys := fstest.MapFS{ + "main.tf": &fstest.MapFile{Data: []byte(`variable "name" { + type = string + default = null +} + +resource "aws_s3_bucket" "example" { + bucket = var.name +}`)}, + } + + parser := New(fsys, "", OptionStopOnHCLError(true)) + + require.NoError(t, parser.ParseFS(context.TODO(), ".")) + + _, err := parser.Load(context.TODO()) + require.NoError(t, err) + + modules, _, err := parser.EvaluateAll(context.TODO()) + require.NoError(t, err) + + val := modules.GetResourcesByType("aws_s3_bucket")[0].GetAttribute("bucket").GetRawValue() + assert.Nil(t, val) +} diff --git a/pkg/iac/scanners/terraform/parser/resolvers/cache.go b/pkg/iac/scanners/terraform/parser/resolvers/cache.go index 24f803f60139..5e7641af3333 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/cache.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/cache.go @@ -4,7 +4,7 @@ import ( "context" "crypto/md5" // #nosec "encoding/hex" - "fmt" + "errors" "io/fs" "os" "path/filepath" @@ -37,7 +37,7 @@ func locateCacheDir(cacheDir string) (string, error) { return "", err } if !isWritable(cacheDir) { - return "", fmt.Errorf("cache directory is not writable") + return "", errors.New("cache directory is not writable") } return cacheDir, nil } diff --git a/pkg/iac/scanners/terraform/parser/resolvers/registry.go b/pkg/iac/scanners/terraform/parser/resolvers/registry.go index 1af19f753209..3b37134b307a 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/registry.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/registry.go @@ -3,6 +3,7 @@ package resolvers import ( "context" "encoding/json" + "errors" "fmt" "io/fs" "net/http" @@ -193,7 +194,7 @@ func resolveVersion(input string, versions moduleVersions) (string, error) { return "", fmt.Errorf("1 module expected, found %d", len(versions.Modules)) } if len(versions.Modules[0].Versions) == 0 { - return "", fmt.Errorf("no available versions for module") + return "", errors.New("no available versions for module") } constraints, err := version.NewConstraints(input) diff --git a/pkg/iac/scanners/terraform/parser/resolvers/remote.go b/pkg/iac/scanners/terraform/parser/resolvers/remote.go index d70edde8c3b7..f23483b413bd 100644 --- a/pkg/iac/scanners/terraform/parser/resolvers/remote.go +++ b/pkg/iac/scanners/terraform/parser/resolvers/remote.go @@ -72,8 +72,6 @@ func (r *remoteResolver) download(ctx context.Context, opt Options, dst string) return err } - var opts []getter.ClientOption - // Overwrite the file getter so that a file will be copied getter.Getters["file"] = &getter.FileGetter{Copy: true} @@ -87,7 +85,13 @@ func (r *remoteResolver) download(ctx context.Context, opt Options, dst string) Pwd: opt.WorkingDir, Getters: getter.Getters, Mode: getter.ClientModeAny, - Options: opts, + } + + terminalPrompt := os.Getenv("GIT_TERMINAL_PROMPT") + if err := os.Setenv("GIT_TERMINAL_PROMPT", "0"); err != nil { + opt.Logger.Error("Failed to set env", log.String("name", "GIT_TERMINAL_PROMPT"), log.Err(err)) + } else { + defer os.Setenv("GIT_TERMINAL_PROMPT", terminalPrompt) } if err := client.Get(); err != nil { diff --git a/pkg/iac/scanners/terraform/scanner.go b/pkg/iac/scanners/terraform/scanner.go index 9ddb2f3ef861..c9aed6f76b73 100644 --- a/pkg/iac/scanners/terraform/scanner.go +++ b/pkg/iac/scanners/terraform/scanner.go @@ -19,6 +19,7 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/terraform" "github.com/aquasecurity/trivy/pkg/iac/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) var _ scanners.FSScanner = (*Scanner)(nil) @@ -31,7 +32,7 @@ type Scanner struct { options []options.ScannerOption parserOpt []parser.Option executorOpt []executor.Option - dirs map[string]struct{} + dirs set.Set[string] forceAllDirs bool regoScanner *rego.Scanner execLock sync.RWMutex @@ -55,7 +56,7 @@ func (s *Scanner) AddExecutorOptions(opts ...executor.Option) { func New(opts ...options.ScannerOption) *Scanner { s := &Scanner{ - dirs: make(map[string]struct{}), + dirs: set.New[string](), options: opts, logger: log.WithPrefix("terraform scanner"), } diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index 215ec796b45d..286a6920ce93 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" "testing" + "testing/fstest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -951,3 +952,46 @@ resource "aws_s3_bucket" "test" {} assert.Len(t, results, 2) }) } + +func TestUseRandomProvider(t *testing.T) { + fsys := fstest.MapFS{ + "main.tf": &fstest.MapFile{Data: []byte(`resource "random_id" "suffix" {} + +locals { + bucket = "test-${random_id.suffix.hex}" +} + +resource "aws_s3_bucket" "test" { + bucket = local.bucket +} + +resource "aws_s3_bucket_versioning" "test" { + bucket = local.bucket + versioning_configuration { + status = "Enabled" + } +} +`)}, + } + + check := `package test +import rego.v1 + +deny contains res if { + some bucket in input.aws.s3.buckets + bucket.versioning.enabled.value + res := result.new("Bucket versioning is enabled", bucket) +} +` + + scanner := New( + ScannerWithAllDirectories(true), + rego.WithPolicyReader(strings.NewReader(check)), + rego.WithPolicyNamespaces("test"), + ) + + results, err := scanner.ScanFS(context.TODO(), fsys, ".") + require.NoError(t, err) + + assert.Len(t, results.GetFailed(), 1) +} diff --git a/pkg/iac/scanners/terraformplan/snapshot/plan.go b/pkg/iac/scanners/terraformplan/snapshot/plan.go index 3f0c3adcd791..71cafb6e0ea0 100644 --- a/pkg/iac/scanners/terraformplan/snapshot/plan.go +++ b/pkg/iac/scanners/terraformplan/snapshot/plan.go @@ -1,6 +1,7 @@ package snapshot import ( + "errors" "fmt" "io" @@ -54,7 +55,7 @@ func readTfPlan(r io.Reader) (*Plan, error) { for k, v := range rawPlan.Variables { if len(v.Msgpack) == 0 { // len(0) because that's the default value for a "bytes" in protobuf - return nil, fmt.Errorf("dynamic value does not have msgpack serialization") + return nil, errors.New("dynamic value does not have msgpack serialization") } plan.variableValues[k] = DynamicValue(v.Msgpack) diff --git a/pkg/iac/terraform/attribute.go b/pkg/iac/terraform/attribute.go index f0bb426e99a8..1c7774084afd 100644 --- a/pkg/iac/terraform/attribute.go +++ b/pkg/iac/terraform/attribute.go @@ -82,6 +82,10 @@ func NewAttribute(attr *hcl.Attribute, ctx *context.Context, module string, pare } } +func (a *Attribute) HCLAttribute() *hcl.Attribute { + return a.hclAttribute +} + func (a *Attribute) GetMetadata() iacTypes.Metadata { return a.metadata } diff --git a/pkg/iac/terraform/block.go b/pkg/iac/terraform/block.go index a6cd6ab1bbc4..e88cf14de4fe 100644 --- a/pkg/iac/terraform/block.go +++ b/pkg/iac/terraform/block.go @@ -123,6 +123,10 @@ func NewBlock(hclBlock *hcl.Block, ctx *context.Context, moduleBlock *Block, par return &b } +func (b *Block) HCLBlock() *hcl.Block { + return b.hclBlock +} + func (b *Block) ID() string { return b.id } @@ -569,13 +573,25 @@ func (b *Block) Attributes() map[string]*Attribute { return attributes } +func (b *Block) NullableValues() cty.Value { + return b.values(true) +} + func (b *Block) Values() cty.Value { + return b.values(false) +} + +func (b *Block) values(allowNull bool) cty.Value { values := createPresetValues(b) for _, attribute := range b.GetAttributes() { if attribute.Name() == "for_each" { continue } - values[attribute.Name()] = attribute.NullableValue() + if allowNull { + values[attribute.Name()] = attribute.NullableValue() + } else { + values[attribute.Name()] = attribute.Value() + } } return cty.ObjectVal(postProcessValues(b, values)) } @@ -697,7 +713,7 @@ func (b *Block) iteratorName(blockType string) (string, error) { } if len(traversal) != 1 { - return "", fmt.Errorf("dynamic iterator must be a single variable name") + return "", errors.New("dynamic iterator must be a single variable name") } return traversal.RootName(), nil diff --git a/pkg/iac/terraform/modules.go b/pkg/iac/terraform/modules.go index 515d3dc8007d..24c67e6f161b 100644 --- a/pkg/iac/terraform/modules.go +++ b/pkg/iac/terraform/modules.go @@ -1,7 +1,7 @@ package terraform import ( - "fmt" + "errors" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -65,7 +65,7 @@ func (m Modules) GetReferencedBlock(referringAttr *Attribute, parentBlock *Block if bestMatch != nil { return bestMatch, nil } - return nil, fmt.Errorf("block not found") + return nil, errors.New("block not found") } func (m Modules) GetReferencingResources(originalBlock *Block, referencingLabel, referencingAttributeName string) Blocks { @@ -92,7 +92,7 @@ func (m Modules) GetBlockById(id string) (*Block, error) { } } - return nil, fmt.Errorf("block not found") + return nil, errors.New("block not found") } func (m Modules) GetResourceByIDs(id ...string) Blocks { diff --git a/pkg/iac/terraform/presets.go b/pkg/iac/terraform/presets.go index b29a5fc9c181..61ac78bccd2e 100644 --- a/pkg/iac/terraform/presets.go +++ b/pkg/iac/terraform/presets.go @@ -2,12 +2,23 @@ package terraform import ( "fmt" + "math/rand/v2" "strings" "github.com/google/uuid" "github.com/zclconf/go-cty/cty" ) +var resourceRandomAttributes = map[string][]string{ + // If the user leaves the name blank, Terraform will automatically generate a unique name + "aws_launch_template": {"name"}, + "random_id": {"hex", "dec", "b64_url", "b64_std"}, + "random_password": {"result", "bcrypt_hash"}, + "random_string": {"result"}, + "random_bytes": {"base64", "hex"}, + "random_uuid": {"result"}, +} + func createPresetValues(b *Block) map[string]cty.Value { presets := make(map[string]cty.Value) @@ -23,16 +34,21 @@ func createPresetValues(b *Block) map[string]cty.Value { // 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") + case "random_integer": + //nolint:gosec + presets["result"] = cty.NumberIntVal(rand.Int64()) } - return presets + if attrs, exists := resourceRandomAttributes[b.TypeLabel()]; exists { + for _, attr := range attrs { + presets[attr] = cty.StringVal(uuid.New().String()) + } + } + return presets } func postProcessValues(b *Block, input map[string]cty.Value) map[string]cty.Value { diff --git a/pkg/iac/terraform/reference.go b/pkg/iac/terraform/reference.go index a84fb6175180..de601d7433a0 100644 --- a/pkg/iac/terraform/reference.go +++ b/pkg/iac/terraform/reference.go @@ -1,6 +1,7 @@ package terraform import ( + "errors" "fmt" "github.com/zclconf/go-cty/cty" @@ -30,7 +31,7 @@ func newReference(parts []string, parentKey string) (*Reference, error) { var ref Reference if len(parts) == 0 { - return nil, fmt.Errorf("cannot create empty reference") + return nil, errors.New("cannot create empty reference") } blockType, err := TypeFromRefName(parts[0]) diff --git a/pkg/iac/terraform/type.go b/pkg/iac/terraform/type.go index e7c6cab76f15..5a91fee61a5f 100644 --- a/pkg/iac/terraform/type.go +++ b/pkg/iac/terraform/type.go @@ -1,6 +1,6 @@ package terraform -import "fmt" +import "errors" type Type struct { name string @@ -104,5 +104,5 @@ func TypeFromRefName(name string) (*Type, error) { return &valid, nil } } - return nil, fmt.Errorf("block type not found") + return nil, errors.New("block type not found") } diff --git a/pkg/iac/types/fskey_test.go b/pkg/iac/types/fskey_test.go index 37be8fce4f0d..de91b32a0405 100644 --- a/pkg/iac/types/fskey_test.go +++ b/pkg/iac/types/fskey_test.go @@ -7,6 +7,8 @@ import ( "github.com/liamg/memoryfs" "github.com/stretchr/testify/assert" + + "github.com/aquasecurity/trivy/pkg/set" ) func Test_FSKey(t *testing.T) { @@ -18,22 +20,20 @@ func Test_FSKey(t *testing.T) { memoryfs.New(), } - keys := make(map[string]struct{}) + keys := set.New[string]() t.Run("uniqueness", func(t *testing.T) { for _, system := range systems { key := CreateFSKey(system) - _, ok := keys[key] - assert.False(t, ok, "filesystem keys should be unique") - keys[key] = struct{}{} + assert.False(t, keys.Contains(key), "filesystem keys should be unique") + keys.Append(key) } }) t.Run("reproducible", func(t *testing.T) { for _, system := range systems { key := CreateFSKey(system) - _, ok := keys[key] - assert.True(t, ok, "filesystem keys should be reproducible") + assert.True(t, keys.Contains(key), "filesystem keys should be reproducible") } }) } diff --git a/pkg/k8s/scanner/scanner.go b/pkg/k8s/scanner/scanner.go index 0fdb48b9afe7..6ce3fd6ca488 100644 --- a/pkg/k8s/scanner/scanner.go +++ b/pkg/k8s/scanner/scanner.go @@ -3,6 +3,7 @@ package scanner import ( "bytes" "context" + "errors" "fmt" "sort" "strings" @@ -375,7 +376,7 @@ func (s *Scanner) clusterInfoToReportResources(allArtifact []*artifacts.Artifact // Find the first node name to identify AKS cluster var nodeName string if nodeName = s.findNodeName(allArtifact); nodeName == "" { - return nil, fmt.Errorf("failed to find node name") + return nil, errors.New("failed to find node name") } kbom := core.NewBOM(core.Options{ diff --git a/pkg/licensing/classifier.go b/pkg/licensing/classifier.go index 74f825f303a7..5f230624bcc9 100644 --- a/pkg/licensing/classifier.go +++ b/pkg/licensing/classifier.go @@ -12,6 +12,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" ) var ( @@ -43,7 +44,7 @@ func Classify(filePath string, r io.Reader, confidenceLevel float64) (*types.Lic var findings types.LicenseFindings var matchType types.LicenseType - seen := make(map[string]struct{}) + seen := set.New[string]() // cf.Match is not thread safe m.Lock() @@ -57,11 +58,11 @@ func Classify(filePath string, r io.Reader, confidenceLevel float64) (*types.Lic if match.Confidence <= confidenceLevel { continue } - if _, ok := seen[match.Name]; ok { + if seen.Contains(match.Name) { continue } - seen[match.Name] = struct{}{} + seen.Append(match.Name) switch match.MatchType { case "Header": diff --git a/pkg/licensing/expression/category.go b/pkg/licensing/expression/category.go index c32f228c07d8..d9655516b397 100644 --- a/pkg/licensing/expression/category.go +++ b/pkg/licensing/expression/category.go @@ -1,5 +1,18 @@ package expression +import ( + "encoding/json" + "strings" + "sync" + + "github.com/samber/lo" + + "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" + + _ "embed" +) + // Canonical names of the licenses. // ported from https://github.com/google/licenseclassifier/blob/7c62d6fe8d3aa2f39c4affb58c9781d9dc951a2d/license_type.go#L24-L177 const ( @@ -359,3 +372,70 @@ var ( ZeroBSD, } ) + +var spdxLicenses = set.New[string]() + +var initSpdxLicenses = sync.OnceFunc(func() { + if spdxLicenses.Size() > 0 { + return + } + + licenseSlices := [][]string{ + ForbiddenLicenses, + RestrictedLicenses, + ReciprocalLicenses, + NoticeLicenses, + PermissiveLicenses, + UnencumberedLicenses, + } + + for _, licenseSlice := range licenseSlices { + spdxLicenses.Append(licenseSlice...) + } + + // Save GNU licenses with "-or-later" and `"-only" suffixes + for _, l := range GnuLicenses { + license := SimpleExpr{ + License: l, + } + spdxLicenses.Append(license.String()) + + license.HasPlus = true + spdxLicenses.Append(license.String()) + } +}) + +//go:embed exceptions.json +var exceptions []byte + +var spdxExceptions map[string]SimpleExpr + +var initSpdxExceptions = sync.OnceFunc(func() { + if len(spdxExceptions) > 0 { + return + } + + var exs []string + if err := json.Unmarshal(exceptions, &exs); err != nil { + log.WithPrefix(log.PrefixSPDX).Warn("Unable to parse SPDX exception file", log.Err(err)) + return + } + spdxExceptions = lo.SliceToMap(exs, func(exception string) (string, SimpleExpr) { + return strings.ToUpper(exception), SimpleExpr{License: exception} + }) +}) + +// ValidateSPDXLicense returns true if SPDX license list contain licenseID +func ValidateSPDXLicense(license string) bool { + initSpdxLicenses() + + return spdxLicenses.Contains(license) +} + +// ValidateSPDXException returns true if SPDX exception list contain exceptionID +func ValidateSPDXException(exception string) bool { + initSpdxExceptions() + + _, ok := spdxExceptions[strings.ToUpper(exception)] + return ok +} diff --git a/pkg/licensing/expression/exceptions.json b/pkg/licensing/expression/exceptions.json new file mode 100644 index 000000000000..3fb5cc14d958 --- /dev/null +++ b/pkg/licensing/expression/exceptions.json @@ -0,0 +1 @@ +["389-exception","Asterisk-exception","Asterisk-linking-protocols-exception","Autoconf-exception-2.0","Autoconf-exception-3.0","Autoconf-exception-generic","Autoconf-exception-generic-3.0","Autoconf-exception-macro","Bison-exception-1.24","Bison-exception-2.2","Bootloader-exception","CGAL-linking-exception","CLISP-exception-2.0","Classpath-exception-2.0","DigiRule-FOSS-exception","FLTK-exception","Fawkes-Runtime-exception","Font-exception-2.0","GCC-exception-2.0","GCC-exception-2.0-note","GCC-exception-3.1","GNAT-exception","GNOME-examples-exception","GNU-compiler-exception","GPL-3.0-389-ds-base-exception","GPL-3.0-interface-exception","GPL-3.0-linking-exception","GPL-3.0-linking-source-exception","GPL-CC-1.0","GStreamer-exception-2005","GStreamer-exception-2008","Gmsh-exception","Independent-modules-exception","KiCad-libraries-exception","LGPL-3.0-linking-exception","LLGPL","LLVM-exception","LZMA-exception","Libtool-exception","Linux-syscall-note","Nokia-Qt-exception-1.1","OCCT-exception-1.0","OCaml-LGPL-linking-exception","OpenJDK-assembly-exception-1.0","PCRE2-exception","PS-or-PDF-font-exception-20170817","QPL-1.0-INRIA-2004-exception","Qt-GPL-exception-1.0","Qt-LGPL-exception-1.1","Qwt-exception-1.0","RRDtool-FLOSS-exception-2.0","SANE-exception","SHL-2.0","SHL-2.1","SWI-exception","Swift-exception","Texinfo-exception","UBDL-exception","Universal-FOSS-exception-1.0","WxWindows-exception-3.1","cryptsetup-OpenSSL-exception","eCos-exception-2.0","erlang-otp-linking-exception","fmt-exception","freertos-exception-2.0","gnu-javamail-exception","harbour-exception","i2p-gpl-java-exception","libpri-OpenH323-exception","mif-exception","mxml-exception","openvpn-openssl-exception","romic-exception","stunnel-exception","u-boot-exception-2.0","vsftpd-openssl-exception","x11vnc-openssl-exception"] \ No newline at end of file diff --git a/pkg/licensing/expression/expression.go b/pkg/licensing/expression/expression.go index 6f3c0054f929..3758408da72c 100644 --- a/pkg/licensing/expression/expression.go +++ b/pkg/licensing/expression/expression.go @@ -11,7 +11,7 @@ var ( ErrInvalidExpression = xerrors.New("invalid expression error") ) -type NormalizeFunc func(license string) SimpleExpr +type NormalizeFunc func(license Expression) Expression func parse(license string) (Expression, error) { l := NewLexer(strings.NewReader(license)) @@ -24,55 +24,68 @@ func parse(license string) (Expression, error) { return l.result, nil } -func Normalize(license string, fn ...NormalizeFunc) (string, error) { +func Normalize(license string, funcs ...NormalizeFunc) (string, error) { expr, err := parse(license) if err != nil { return "", xerrors.Errorf("license (%s) parse error: %w", license, err) } - expr = normalize(expr, fn...) + for _, fn := range funcs { + expr = normalize(expr, fn) + } return expr.String(), nil } -func normalize(expr Expression, fn ...NormalizeFunc) Expression { - switch e := expr.(type) { +func normalize(expr Expression, fn NormalizeFunc) Expression { + // Apply normalization function first + normalized := fn(expr) + + switch e := normalized.(type) { case SimpleExpr: - for _, f := range fn { - normalized := f(e.License) - e.License = normalized.License - e.HasPlus = e.HasPlus || normalized.HasPlus - } - return e + // No further normalization for SimpleExpr case CompoundExpr: - e.left = normalize(e.left, fn...) - e.right = normalize(e.right, fn...) + // Only recursively process if the result is a CompoundExpr + e.left = normalize(e.left, fn) + e.right = normalize(e.right, fn) e.conjunction.literal = strings.ToUpper(e.conjunction.literal) // e.g. "and" => "AND" return e } - return expr + return normalized } // NormalizeForSPDX replaces ' ' to '-' in license-id. // SPDX license MUST NOT have white space between a license-id. // There MUST be white space on either side of the operator "WITH". // ref: https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions -func NormalizeForSPDX(s string) SimpleExpr { - var b strings.Builder - for _, c := range s { - switch { - // spec: idstring = 1*(ALPHA / DIGIT / "-" / "." ) - case isAlphabet(c) || unicode.IsNumber(c) || c == '-' || c == '.': - _, _ = b.WriteRune(c) - case c == ':': - // TODO: Support DocumentRef - _, _ = b.WriteRune(c) - default: - // Replace invalid characters with '-' - _, _ = b.WriteRune('-') +func NormalizeForSPDX(expr Expression) Expression { + switch e := expr.(type) { + case SimpleExpr: + var b strings.Builder + for _, c := range e.License { + switch { + // spec: idstring = 1*(ALPHA / DIGIT / "-" / "." ) + case isAlphabet(c) || unicode.IsNumber(c) || c == '-' || c == '.': + _, _ = b.WriteRune(c) + case c == ':': + // TODO: Support DocumentRef + _, _ = b.WriteRune(c) + default: + // Replace invalid characters with '-' + _, _ = b.WriteRune('-') + } + } + return SimpleExpr{License: b.String(), HasPlus: e.HasPlus} + case CompoundExpr: + if e.Conjunction() == TokenWith { + initSpdxExceptions() + // Use correct SPDX exceptionID + if exc, ok := spdxExceptions[strings.ToUpper(e.Right().String())]; ok { + return NewCompoundExpr(e.Left(), e.Conjunction(), exc) + } } } - return SimpleExpr{License: b.String(), HasPlus: false} + return expr } func isAlphabet(r rune) bool { diff --git a/pkg/licensing/expression/expression_test.go b/pkg/licensing/expression/expression_test.go index 12b715e7ad30..e476d6be0fcc 100644 --- a/pkg/licensing/expression/expression_test.go +++ b/pkg/licensing/expression/expression_test.go @@ -37,7 +37,7 @@ func TestNormalize(t *testing.T) { { name: "upper", license: "LGPL-2.1-only OR MIT", - fn: func(license string) SimpleExpr { return SimpleExpr{strings.ToUpper(license), false} }, + fn: func(license Expression) Expression { return SimpleExpr{strings.ToUpper(license.String()), false} }, want: "LGPL-2.1-ONLY OR MIT", }, } diff --git a/pkg/licensing/expression/types.go b/pkg/licensing/expression/types.go index acf2473ed4e8..7399f74624c7 100644 --- a/pkg/licensing/expression/types.go +++ b/pkg/licensing/expression/types.go @@ -5,6 +5,13 @@ import ( "slices" ) +var ( + TokenIdent = Token{token: IDENT, literal: "IDENT"} + TokenAnd = Token{token: AND, literal: "AND"} + TokenOR = Token{token: OR, literal: "OR"} + TokenWith = Token{token: WITH, literal: "WITH"} +) + type Expression interface { String() string } @@ -41,6 +48,22 @@ type CompoundExpr struct { right Expression } +func NewCompoundExpr(left Expression, conjunction Token, right Expression) CompoundExpr { + return CompoundExpr{left: left, conjunction: conjunction, right: right} +} + +func (c CompoundExpr) Conjunction() Token { + return c.conjunction +} + +func (c CompoundExpr) Left() Expression { + return c.left +} + +func (c CompoundExpr) Right() Expression { + return c.right +} + func (c CompoundExpr) String() string { left := c.left.String() if l, ok := c.left.(CompoundExpr); ok { diff --git a/pkg/licensing/normalize.go b/pkg/licensing/normalize.go index bce81e68903d..006a1f27600f 100644 --- a/pkg/licensing/normalize.go +++ b/pkg/licensing/normalize.go @@ -641,7 +641,6 @@ var plusSuffixes = [3]string{"+", "-OR-LATER", " OR LATER"} func standardizeKeyAndSuffix(name string) expr.SimpleExpr { // Standardize space, including newline name = strings.Join(strings.Fields(name), " ") - name = strings.TrimSpace(name) name = strings.ToUpper(name) // Do not perform any further normalization for URLs if strings.HasPrefix(name, "HTTP") { @@ -675,15 +674,38 @@ func standardizeKeyAndSuffix(name string) expr.SimpleExpr { } func Normalize(name string) string { - return NormalizeLicense(name).String() + return NormalizeLicense(expr.SimpleExpr{License: name}).String() } -func NormalizeLicense(name string) expr.SimpleExpr { +func NormalizeLicense(exp expr.Expression) expr.Expression { + switch e := exp.(type) { + case expr.SimpleExpr: + return normalizeSimpleExpr(e) + case expr.CompoundExpr: + return normalizeCompoundExpr(e) + } + return exp +} + +func normalizeSimpleExpr(e expr.SimpleExpr) expr.Expression { + // Always trim leading and trailing spaces, even if we don't find this license in `mapping`. + name := strings.TrimSpace(e.License) normalized := standardizeKeyAndSuffix(name) + if found, ok := mapping[normalized.License]; ok { + return expr.SimpleExpr{License: found.License, HasPlus: e.HasPlus || found.HasPlus || normalized.HasPlus} + } + return expr.SimpleExpr{License: name, HasPlus: e.HasPlus} +} + +func normalizeCompoundExpr(e expr.CompoundExpr) expr.Expression { + if e.Conjunction() != expr.TokenWith { + return e // Do not normalize compound expressions other than "WITH" + } + normalized := standardizeKeyAndSuffix(e.String()) if found, ok := mapping[normalized.License]; ok { return expr.SimpleExpr{License: found.License, HasPlus: found.HasPlus || normalized.HasPlus} } - return expr.SimpleExpr{License: name, HasPlus: false} + return e // Do not normalize compound expressions that are not found in `mapping` } func SplitLicenses(str string) []string { diff --git a/pkg/licensing/normalize_test.go b/pkg/licensing/normalize_test.go index 7daf7b57d783..1b54603b0279 100644 --- a/pkg/licensing/normalize_test.go +++ b/pkg/licensing/normalize_test.go @@ -6,224 +6,237 @@ import ( "github.com/stretchr/testify/assert" "github.com/aquasecurity/trivy/pkg/licensing" + "github.com/aquasecurity/trivy/pkg/licensing/expression" ) func TestNormalize(t *testing.T) { tests := []struct { - licenses []string - normalized string - normalizedKey string + licenses []expression.Expression + want string + wantLicense expression.Expression }{ { - licenses: []string{ - " the apache license ", - " the\tapache \r\nlicense \r\n ", - " apache ", - "ApacheLicence", - "ApacheLicense", - "al-2", - "al-v2", - "al2", - "alv2", - "apache - v 2.0", - "apache - v. 2.0", - "apache - ver 2.0", - "apache - version 2.0", - "apache 2", - "apache 2.0", - "apache license (2.0)", - "apache license (v. 2)", - "apache license (v. 2.0)", - "apache license (v2)", - "apache license (v2.0)", - "apache license (version 2.0)", - "apache license 2", - "apache license 2.0", - "apache license v2", - "apache license v2.0", - "apache license version 2", - "apache license version 2.0", - "apache license", - "apache license, 2.0", - "apache license, asl version 2.0", - "apache license, version 2", - "apache license, version 2.0 (http://www.apache.org/licenses/license-2.0)", - "apache license, version 2.0", - "apache license,version 2.0", - "apache license,version-2.0", - "apache license-2.0", - "apache public 2.0", - "apache public license 2.0", - "apache public license-2.0", - "apache public-2", - "apache public-2.0", - "apache software license (apache-2.0)", - "apache software license - version 2.0", - "apache software license 2.0", - "apache software license, version 2", - "apache software license, version 2.0", - "apache software-2.0", - "apache v 2.0", - "apache v. 2.0", - "apache v2", - "apache v2.0", - "apache ver 2.0", - "apache ver. 2.0", - "apache version 2.0", - "apache version 2.0, january 2004", - "apache version-2", - "apache version-2.0", - "apache", - "apache, 2", - "apache, v2.0", - "apache, version 2", - "apache, version 2.0", - "apache-2", - "apache-2.0", - "apache-licence", - "apache-license", - "apache-licensed", - "apache-licensed", - "asf 2.0", - "asl 2", - "asl, version 2", - "asl2.0", - "the apache license", - "the apache license", + licenses: []expression.Expression{ + expression.SimpleExpr{License: " the apache license "}, + expression.SimpleExpr{License: " the\tapache \r\nlicense \r\n "}, + expression.SimpleExpr{License: " apache "}, + expression.SimpleExpr{License: "ApacheLicence"}, + expression.SimpleExpr{License: "ApacheLicense"}, + expression.SimpleExpr{License: "al-2"}, + expression.SimpleExpr{License: "al-v2"}, + expression.SimpleExpr{License: "al2"}, + expression.SimpleExpr{License: "alv2"}, + expression.SimpleExpr{License: "apache - v 2.0"}, + expression.SimpleExpr{License: "apache - v. 2.0"}, + expression.SimpleExpr{License: "apache - ver 2.0"}, + expression.SimpleExpr{License: "apache - version 2.0"}, + expression.SimpleExpr{License: "apache 2"}, + expression.SimpleExpr{License: "apache 2.0"}, + expression.SimpleExpr{License: "apache license (2.0)"}, + expression.SimpleExpr{License: "apache license (v. 2)"}, + expression.SimpleExpr{License: "apache license (v. 2.0)"}, + expression.SimpleExpr{License: "apache license (v2)"}, + expression.SimpleExpr{License: "apache license (v2.0)"}, + expression.SimpleExpr{License: "apache license (version 2.0)"}, + expression.SimpleExpr{License: "apache license 2"}, + expression.SimpleExpr{License: "apache license 2.0"}, + expression.SimpleExpr{License: "apache license v2"}, + expression.SimpleExpr{License: "apache license v2.0"}, + expression.SimpleExpr{License: "apache license version 2"}, + expression.SimpleExpr{License: "apache license version 2.0"}, + expression.SimpleExpr{License: "apache license"}, + expression.SimpleExpr{License: "apache license, 2.0"}, + expression.SimpleExpr{License: "apache license, asl version 2.0"}, + expression.SimpleExpr{License: "apache license, version 2"}, + expression.SimpleExpr{License: "apache license, version 2.0 (http://www.apache.org/licenses/license-2.0)"}, + expression.SimpleExpr{License: "apache license, version 2.0"}, + expression.SimpleExpr{License: "apache license,version 2.0"}, + expression.SimpleExpr{License: "apache license,version-2.0"}, + expression.SimpleExpr{License: "apache license-2.0"}, + expression.SimpleExpr{License: "apache public 2.0"}, + expression.SimpleExpr{License: "apache public license 2.0"}, + expression.SimpleExpr{License: "apache public license-2.0"}, + expression.SimpleExpr{License: "apache public-2"}, + expression.SimpleExpr{License: "apache public-2.0"}, + expression.SimpleExpr{License: "apache software license (apache-2.0)"}, + expression.SimpleExpr{License: "apache software license - version 2.0"}, + expression.SimpleExpr{License: "apache software license 2.0"}, + expression.SimpleExpr{License: "apache software license, version 2"}, + expression.SimpleExpr{License: "apache software license, version 2.0"}, + expression.SimpleExpr{License: "apache software-2.0"}, + expression.SimpleExpr{License: "apache v 2.0"}, + expression.SimpleExpr{License: "apache v. 2.0"}, + expression.SimpleExpr{License: "apache v2"}, + expression.SimpleExpr{License: "apache v2.0"}, + expression.SimpleExpr{License: "apache ver 2.0"}, + expression.SimpleExpr{License: "apache ver. 2.0"}, + expression.SimpleExpr{License: "apache version 2.0"}, + expression.SimpleExpr{License: "apache version 2.0, january 2004"}, + expression.SimpleExpr{License: "apache version-2"}, + expression.SimpleExpr{License: "apache version-2.0"}, + expression.SimpleExpr{License: "apache"}, + expression.SimpleExpr{License: "apache, 2"}, + expression.SimpleExpr{License: "apache, v2.0"}, + expression.SimpleExpr{License: "apache, version 2"}, + expression.SimpleExpr{License: "apache, version 2.0"}, + expression.SimpleExpr{License: "apache-2"}, + expression.SimpleExpr{License: "apache-2.0"}, + expression.SimpleExpr{License: "apache-licence"}, + expression.SimpleExpr{License: "apache-license"}, + expression.SimpleExpr{License: "apache-licensed"}, + expression.SimpleExpr{License: "apache-licensed"}, + expression.SimpleExpr{License: "asf 2.0"}, + expression.SimpleExpr{License: "asl 2"}, + expression.SimpleExpr{License: "asl, version 2"}, + expression.SimpleExpr{License: "asl2.0"}, + expression.SimpleExpr{License: "the apache license"}, + expression.SimpleExpr{License: "the apache license"}, }, - normalized: "Apache-2.0", - normalizedKey: "Apache-2.0", + want: "Apache-2.0", + wantLicense: expression.SimpleExpr{License: "Apache-2.0"}, }, { - licenses: []string{ - "Apache+", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "Apache+"}, }, - normalized: "Apache-2.0+", - normalizedKey: "Apache-2.0", + want: "Apache-2.0+", + wantLicense: expression.SimpleExpr{License: "Apache-2.0", HasPlus: true}, }, { - licenses: []string{ - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) V1.1", - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) VERSION 1.1", - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL), VERSION 1.1", - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 1.1 (CDDL-1.1)", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) V1.1"}, + expression.SimpleExpr{License: "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) VERSION 1.1"}, + expression.SimpleExpr{License: "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL), VERSION 1.1"}, + expression.SimpleExpr{License: "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 1.1 (CDDL-1.1)"}, }, - normalized: "CDDL-1.1", - normalizedKey: "CDDL-1.1", + want: "CDDL-1.1", + wantLicense: expression.SimpleExpr{License: "CDDL-1.1"}, }, { - licenses: []string{ - "ECLIPSE PUBLIC LICENSE (EPL) 1.0", - "ECLIPSE PUBLIC LICENSE (EPL), VERSION 1.0", - "ECLIPSE PUBLIC LICENSE - V 1.0", - "ECLIPSE PUBLIC LICENSE - V1.0", - "ECLIPSE PUBLIC LICENSE - VERSION 1.0", - "ECLIPSE PUBLIC LICENSE 1.0 (EPL-1.0)", - "ECLIPSE PUBLIC LICENSE 1.0", - "ECLIPSE PUBLIC LICENSE V. 1.0", - "ECLIPSE PUBLIC LICENSE V1.0", - "ECLIPSE PUBLIC LICENSE VERSION 1.0", - "ECLIPSE PUBLIC LICENSE, VERSION 1.0", - "ECLIPSE PUBLIC", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE (EPL) 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE (EPL), VERSION 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE - V 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE - V1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE - VERSION 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE 1.0 (EPL-1.0)"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE V. 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE V1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE VERSION 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC LICENSE, VERSION 1.0"}, + expression.SimpleExpr{License: "ECLIPSE PUBLIC"}, }, - normalized: "EPL-1.0", - normalizedKey: "EPL-1.0", + want: "EPL-1.0", + wantLicense: expression.SimpleExpr{License: "EPL-1.0"}, }, { - licenses: []string{ - "EUROPEAN UNION PUBLIC LICENSE (EUPL V.1.1)", - "EUROPEAN UNION PUBLIC LICENSE 1.1 (EUPL 1.1)", - "EUROPEAN UNION PUBLIC LICENSE 1.1", - "EUROPEAN UNION PUBLIC LICENSE, VERSION 1.1", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "EUROPEAN UNION PUBLIC LICENSE (EUPL V.1.1)"}, + expression.SimpleExpr{License: "EUROPEAN UNION PUBLIC LICENSE 1.1 (EUPL 1.1)"}, + expression.SimpleExpr{License: "EUROPEAN UNION PUBLIC LICENSE 1.1"}, + expression.SimpleExpr{License: "EUROPEAN UNION PUBLIC LICENSE, VERSION 1.1"}, }, - normalized: "EUPL-1.1", - normalizedKey: "EUPL-1.1", + want: "EUPL-1.1", + wantLicense: expression.SimpleExpr{License: "EUPL-1.1"}, }, { - licenses: []string{ - "GPL-or-later", - "GPL+", - "GPL-2.0-only+", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "GPL-or-later"}, + expression.SimpleExpr{License: "GPL+"}, + expression.SimpleExpr{License: "GPL-2.0-only+"}, }, - normalized: "GPL-2.0-or-later", - normalizedKey: "GPL-2.0", + want: "GPL-2.0-or-later", + wantLicense: expression.SimpleExpr{License: "GPL-2.0", HasPlus: true}, }, { - licenses: []string{ - "GPL (≥ 3)", - "GPL3+", - "GPL3-or-later", - "GPL3 or later licence", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "GPL (≥ 3)"}, + expression.SimpleExpr{License: "GPL3+"}, + expression.SimpleExpr{License: "GPL3-or-later"}, + expression.SimpleExpr{License: "GPL3 or later licence"}, }, - normalized: "GPL-3.0-or-later", - normalizedKey: "GPL-3.0", + want: "GPL-3.0-or-later", + wantLicense: expression.SimpleExpr{License: "GPL-3.0", HasPlus: true}, }, { - licenses: []string{ - "GNU GENERAL PUBLIC LICENSE 3", - "GNU GENERAL PUBLIC LICENSE (GPL) V. 3", - "GNU GENERAL PUBLIC LICENSE VERSION 3 (GPL V3)", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "GNU GENERAL PUBLIC LICENSE 3"}, + expression.SimpleExpr{License: "GNU GENERAL PUBLIC LICENSE (GPL) V. 3"}, + expression.SimpleExpr{License: "GNU GENERAL PUBLIC LICENSE VERSION 3 (GPL V3)"}, }, - normalized: "GPL-3.0-only", - normalizedKey: "GPL-3.0", + want: "GPL-3.0-only", + wantLicense: expression.SimpleExpr{License: "GPL-3.0"}, }, { - licenses: []string{ - "LGPL LICENSE-3", - "GNU LESSER GENERAL PUBLIC LICENSE V3", - "GNU LESSER GENERAL PUBLIC LICENSE V3.0", - "GNU LESSER GENERAL PUBLIC LICENSE VERSION 3", - "GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0", - "GNU LESSER GENERAL PUBLIC LICENSE, VERSION 3.0", - "GNU LIBRARY OR LESSER GENERAL PUBLIC LICENSE VERSION 3.0 (LGPLV3)", - "GNU GENERAL LESSER PUBLIC LICENSE (LGPL) VERSION 3.0", - "GNU LESSER GENERAL PUBLIC LICENSE (LGPL), VERSION 3", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "LGPL LICENSE-3"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE V3"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE V3.0"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE VERSION 3"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE, VERSION 3.0"}, + expression.SimpleExpr{License: "GNU LIBRARY OR LESSER GENERAL PUBLIC LICENSE VERSION 3.0 (LGPLV3)"}, + expression.SimpleExpr{License: "GNU GENERAL LESSER PUBLIC LICENSE (LGPL) VERSION 3.0"}, + expression.SimpleExpr{License: "GNU LESSER GENERAL PUBLIC LICENSE (LGPL), VERSION 3"}, }, - normalized: "LGPL-3.0-only", - normalizedKey: "LGPL-3.0", + want: "LGPL-3.0-only", + wantLicense: expression.SimpleExpr{License: "LGPL-3.0"}, }, { - licenses: []string{ - "The Unlicense", - "Unlicense", - "Unlicensed", - "UNLICENSE", - "UNLICENSED", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "The Unlicense"}, + expression.SimpleExpr{License: "Unlicense"}, + expression.SimpleExpr{License: "Unlicensed"}, + expression.SimpleExpr{License: "UNLICENSE"}, + expression.SimpleExpr{License: "UNLICENSED"}, }, - normalized: "Unlicense", - normalizedKey: "Unlicense", + want: "Unlicense", + wantLicense: expression.SimpleExpr{License: "Unlicense"}, }, { - licenses: []string{ - "MIT License", - "http://json.codeplex.com/license", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "MIT License"}, + expression.SimpleExpr{License: "http://json.codeplex.com/license"}, }, - normalized: "MIT", - normalizedKey: "MIT", + want: "MIT", + wantLicense: expression.SimpleExpr{License: "MIT"}, }, { - licenses: []string{ - " The unmapped license ", + licenses: []expression.Expression{ + expression.SimpleExpr{License: " The unmapped license "}, }, - normalized: " The unmapped license ", - normalizedKey: " The unmapped license ", + want: "The unmapped license", + wantLicense: expression.SimpleExpr{License: "The unmapped license"}, }, { - licenses: []string{ - "Universal Permissive License, Version 1.0", + licenses: []expression.Expression{ + expression.SimpleExpr{License: "Universal Permissive License, Version 1.0"}, + }, + want: "UPL-1.0", + wantLicense: expression.SimpleExpr{License: "UPL-1.0"}, + }, + { + licenses: []expression.Expression{ + expression.SimpleExpr{License: "GPLv2 WITH EXCEPTIONS"}, + expression.NewCompoundExpr( // "GPLv2 WITH EXCEPTIONS" + expression.SimpleExpr{License: "GPLv2"}, + expression.TokenWith, + expression.SimpleExpr{License: "EXCEPTIONS"}, + ), }, - normalized: "UPL-1.0", - normalizedKey: "UPL-1.0", + want: "GPL-2.0-with-classpath-exception", + wantLicense: expression.SimpleExpr{License: "GPL-2.0-with-classpath-exception"}, }, } for _, tt := range tests { - t.Run(tt.normalized, func(t *testing.T) { + t.Run(tt.want, func(t *testing.T) { for _, ll := range tt.licenses { - normalized := licensing.Normalize(ll) - normalizedKey := licensing.NormalizeLicense(ll).License - assert.Equal(t, tt.normalized, normalized) - assert.Equal(t, tt.normalizedKey, normalizedKey) + got := licensing.Normalize(ll.String()) + gotLicense := licensing.NormalizeLicense(ll) + assert.Equal(t, tt.want, got) + assert.Equal(t, tt.wantLicense, gotLicense) } }) } diff --git a/pkg/licensing/scanner.go b/pkg/licensing/scanner.go index 1a8ed8e1d9f0..70747d8ceb76 100644 --- a/pkg/licensing/scanner.go +++ b/pkg/licensing/scanner.go @@ -5,6 +5,7 @@ import ( dbTypes "github.com/aquasecurity/trivy-db/pkg/types" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/licensing/expression" ) type ScannerOption struct { @@ -21,9 +22,17 @@ func NewScanner(categories map[types.LicenseCategory][]string) Scanner { } func (s *Scanner) Scan(licenseName string) (types.LicenseCategory, string) { - license := NormalizeLicense(licenseName) + normalized := NormalizeLicense(expression.SimpleExpr{License: licenseName}) + var normalizedName string + switch normalized := normalized.(type) { + case expression.SimpleExpr: + normalizedName = normalized.License + case expression.CompoundExpr: + normalizedName = normalized.String() + } + for category, names := range s.categories { - if slices.Contains(names, license.License) { + if slices.Contains(names, normalizedName) { return category, categoryToSeverity(category).String() } } diff --git a/pkg/licensing/scanner_test.go b/pkg/licensing/scanner_test.go index 992992e48f9a..2cce9d1d13e6 100644 --- a/pkg/licensing/scanner_test.go +++ b/pkg/licensing/scanner_test.go @@ -30,6 +30,18 @@ func TestScanner_Scan(t *testing.T) { wantCategory: types.CategoryForbidden, wantSeverity: "CRITICAL", }, + { + name: "has plus", + categories: map[types.LicenseCategory][]string{ + types.CategoryForbidden: { + expression.BSD3Clause, + expression.Apache20, + }, + }, + licenseName: "Apache-2.0+", + wantCategory: types.CategoryForbidden, + wantSeverity: "CRITICAL", + }, { name: "restricted", categories: map[types.LicenseCategory][]string{ diff --git a/pkg/log/handler.go b/pkg/log/handler.go index d5e75a77049c..9bbfd8060e3f 100644 --- a/pkg/log/handler.go +++ b/pkg/log/handler.go @@ -264,6 +264,7 @@ var ( Duration = slog.Duration Group = slog.Group Any = slog.Any + Nil = slog.Attr{Key: "", Value: slog.AnyValue(nil)} // Nil will not be logged ) // Err returns an Attr that represents an error. diff --git a/pkg/log/logger.go b/pkg/log/logger.go index 2948886b9559..5600c0d6b3ae 100644 --- a/pkg/log/logger.go +++ b/pkg/log/logger.go @@ -25,6 +25,7 @@ const ( PrefixLicense = "license" PrefixVulnerabilityDB = "vulndb" PrefixJavaDB = "javadb" + PrefixSPDX = "spdx" ) // Logger is an alias of slog.Logger diff --git a/pkg/module/wasm/sdk.go b/pkg/module/wasm/sdk.go index 25b9f1e777c3..21d6df16179f 100644 --- a/pkg/module/wasm/sdk.go +++ b/pkg/module/wasm/sdk.go @@ -8,7 +8,6 @@ package wasm import ( "encoding/json" "fmt" - "reflect" "unsafe" "github.com/aquasecurity/trivy/pkg/module/api" @@ -141,28 +140,17 @@ func marshal(v any) uint64 { } func unmarshal(ptr, size uint32, v any) error { - var b []byte - s := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - s.Len = uintptr(size) - s.Cap = uintptr(size) - s.Data = uintptr(ptr) - - if err := json.Unmarshal(b, v); err != nil { + s := ptrToString(ptr, size) + if err := json.Unmarshal([]byte(s), v); err != nil { return fmt.Errorf("unmarshal error: %s", err) } - return nil } // ptrToString returns a string from WebAssembly compatible numeric types representing its pointer and length. func ptrToString(ptr uint32, size uint32) string { - // Get a slice view of the underlying bytes in the stream. We use SliceHeader, not StringHeader - // as it allows us to fix the capacity to what was allocated. - return *(*string)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(ptr), - Len: uintptr(size), // Tinygo requires these as uintptrs even if they are int fields. - Cap: uintptr(size), // ^^ See https://github.com/tinygo-org/tinygo/issues/1284 - })) + b := unsafe.Slice((*byte)(unsafe.Pointer(uintptr(ptr))), size) + return *(*string)(unsafe.Pointer(&b)) } // stringToPtr returns a pointer and size pair for the given string in a way compatible with WebAssembly numeric types. diff --git a/pkg/oci/artifact.go b/pkg/oci/artifact.go index 8ed7dcdad03d..440cbebc0979 100644 --- a/pkg/oci/artifact.go +++ b/pkg/oci/artifact.go @@ -262,6 +262,19 @@ func shouldTryOtherRepo(err error) bool { } } - // try the following artifact only if a temporary error occurs - return terr.Temporary() + // try the following artifact if a temporary error occurs + if terr.Temporary() { + return true + } + + // `GCR` periodically returns `BLOB_UNKNOWN` error. + // cf. https://github.com/aquasecurity/trivy/discussions/8020 + // In this case we need to check other repositories. + for _, e := range terr.Errors { + if e.Code == transport.BlobUnknownErrorCode { + return true + } + } + + return false } diff --git a/pkg/oci/artifact_test.go b/pkg/oci/artifact_test.go index a8ce6e542641..6bdbce11f72a 100644 --- a/pkg/oci/artifact_test.go +++ b/pkg/oci/artifact_test.go @@ -2,7 +2,7 @@ package oci_test import ( "context" - "fmt" + "errors" "os" "path/filepath" "testing" @@ -71,7 +71,7 @@ func TestArtifact_Download(t *testing.T) { name: "sad: Layers returns an error", mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", layersReturns: layersReturns{ - err: fmt.Errorf("error"), + err: errors.New("error"), }, wantErr: "OCI layer error", }, diff --git a/pkg/parallel/pipeline_test.go b/pkg/parallel/pipeline_test.go index 4fb008c9e00e..dd2cf9641494 100644 --- a/pkg/parallel/pipeline_test.go +++ b/pkg/parallel/pipeline_test.go @@ -2,7 +2,7 @@ package parallel_test import ( "context" - "fmt" + "errors" "testing" "github.com/stretchr/testify/assert" @@ -78,7 +78,7 @@ func TestPipeline_Do(t *testing.T) { 3, }, onItem: func(_ context.Context, _ int) (int, error) { - return 0, fmt.Errorf("error") + return 0, errors.New("error") }, }, wantErr: require.Error, @@ -92,7 +92,7 @@ func TestPipeline_Do(t *testing.T) { 2, }, onItem: func(_ context.Context, _ int) (int, error) { - return 0, fmt.Errorf("error") + return 0, errors.New("error") }, }, wantErr: require.Error, diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index 4752fa4ce7fc..c31de3172cc9 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -3,7 +3,7 @@ package policy_test import ( "context" "encoding/json" - "fmt" + "errors" "io" "os" "path/filepath" @@ -49,7 +49,7 @@ func (b brokenLayer) MediaType() (types.MediaType, error) { } func (b brokenLayer) Compressed() (io.ReadCloser, error) { - return nil, fmt.Errorf("compressed error") + return nil, errors.New("compressed error") } func newBrokenLayer(t *testing.T) v1.Layer { @@ -122,8 +122,7 @@ func TestClient_LoadBuiltinPolicies(t *testing.T) { got, err := c.LoadBuiltinChecks() if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) @@ -194,7 +193,7 @@ func TestClient_NeedsUpdate(t *testing.T) { name: "sad: Digest returns an error", clock: fake.NewFakeClock(time.Date(2021, 1, 2, 1, 0, 0, 0, time.UTC)), digestReturns: digestReturns{ - err: fmt.Errorf("error"), + err: errors.New("error"), }, metadata: policy.Metadata{ Digest: `sha256:922e50f14ab484f11ae65540c3d2d76009020213f1027d4331d31141575e5414`, @@ -322,7 +321,7 @@ func TestClient_DownloadBuiltinPolicies(t *testing.T) { layers: []v1.Layer{newFakeLayer(t)}, }, digestReturns: digestReturns{ - err: fmt.Errorf("error"), + err: errors.New("error"), }, want: &policy.Metadata{ Digest: "sha256:01e033e78bd8a59fa4f4577215e7da06c05e1152526094d8d79d2aa06e98cb9d", @@ -363,8 +362,7 @@ func TestClient_DownloadBuiltinPolicies(t *testing.T) { err = c.DownloadBuiltinChecks(context.Background(), ftypes.RegistryOptions{}) if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) + require.ErrorContains(t, err, tt.wantErr) return } require.NoError(t, err) diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go index a7b1cb9181f0..74c7c348f58d 100644 --- a/pkg/purl/purl.go +++ b/pkg/purl/purl.go @@ -455,7 +455,7 @@ func purlType(t ftypes.TargetType) string { return packageurl.TypeComposer case ftypes.CondaPkg, ftypes.CondaEnv: return packageurl.TypeConda - case ftypes.PythonPkg, ftypes.Pip, ftypes.Pipenv, ftypes.Poetry: + case ftypes.PythonPkg, ftypes.Pip, ftypes.Pipenv, ftypes.Poetry, ftypes.Uv: return packageurl.TypePyPi case ftypes.GoBinary, ftypes.GoModule: return packageurl.TypeGolang diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go index d5ba15300393..5607551da77c 100644 --- a/pkg/purl/purl_test.go +++ b/pkg/purl/purl_test.go @@ -446,8 +446,7 @@ func TestNewPackageURL(t *testing.T) { t.Run(tc.name, func(t *testing.T) { packageURL, err := purl.New(tc.typ, tc.metadata, tc.pkg) if tc.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tc.wantErr) + require.ErrorContains(t, err, tc.wantErr) return } require.NoError(t, err) diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 9e49e2e4f24f..c9f75e834991 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -3,12 +3,15 @@ package remote import ( "context" "crypto/tls" + "errors" "fmt" "net" "net/http" + "strings" "time" "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/authn/github" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/remote" @@ -34,8 +37,14 @@ func Get(ctx context.Context, ref name.Reference, option types.RegistryOptions) return nil, xerrors.Errorf("failed to create http transport: %w", err) } + return tryWithMirrors(ref, option, func(r name.Reference) (*Descriptor, error) { + return tryGet(ctx, tr, r, option) + }) +} + +// tryGet checks all auth options and tries to get Descriptor. +func tryGet(ctx context.Context, tr http.RoundTripper, ref name.Reference, option types.RegistryOptions) (*Descriptor, error) { var errs error - // Try each authentication method until it succeeds for _, authOpt := range authOptions(ctx, ref, option) { remoteOpts := []remote.Option{ remote.WithTransport(tr), @@ -66,8 +75,6 @@ func Get(ctx context.Context, ref name.Reference, option types.RegistryOptions) } return desc, nil } - - // No authentication succeeded return nil, errs } @@ -79,8 +86,49 @@ func Image(ctx context.Context, ref name.Reference, option types.RegistryOptions return nil, xerrors.Errorf("failed to create http transport: %w", err) } + return tryWithMirrors(ref, option, func(r name.Reference) (v1.Image, error) { + return tryImage(ctx, tr, r, option) + }) +} + +// tryWithMirrors handles common mirror logic for Get and Image functions +func tryWithMirrors[T any](ref name.Reference, option types.RegistryOptions, fn func(name.Reference) (T, error)) (T, error) { + var zero T + mirrors, err := registryMirrors(ref, option) + if err != nil { + return zero, xerrors.Errorf("unable to parse mirrors: %w", err) + } + + // Try each mirrors/host until it succeeds + var errs error + for _, r := range append(mirrors, ref) { + result, err := fn(r) + if err != nil { + var multiErr *multierror.Error + // All auth options failed, try the next mirror/host + if errors.As(err, &multiErr) { + errs = multierror.Append(errs, multiErr.Errors...) + continue + } + // Other errors + return zero, err + } + + if ref.Context().RegistryStr() != r.Context().RegistryStr() { + log.WithPrefix("remote").Info("Using the mirror registry to get the image", + log.String("image", ref.String()), log.String("mirror", r.Context().RegistryStr())) + } + return result, nil + } + + // No authentication for mirrors/host succeeded + return zero, errs +} + +// tryImage checks all auth options and tries to get v1.Image. +// If none of the auth options work - function returns multierrors for each auth option. +func tryImage(ctx context.Context, tr http.RoundTripper, ref name.Reference, option types.RegistryOptions) (v1.Image, error) { var errs error - // Try each authentication method until it succeeds for _, authOpt := range authOptions(ctx, ref, option) { remoteOpts := []remote.Option{ remote.WithTransport(tr), @@ -91,10 +139,9 @@ func Image(ctx context.Context, ref name.Reference, option types.RegistryOptions errs = multierror.Append(errs, err) continue } + return index, nil } - - // No authentication succeeded return nil, errs } @@ -125,6 +172,31 @@ func Referrers(ctx context.Context, d name.Digest, option types.RegistryOptions) return nil, errs } +// registryMirrors returns a list of mirrors for ref, obtained from options.RegistryMirrors +// `go-containerregistry` doesn't support mirrors, so we need to handle them ourselves. +// TODO: use `WithMirror` when `go-containerregistry` will support mirrors. +// cf. https://github.com/google/go-containerregistry/pull/2010 +func registryMirrors(hostRef name.Reference, option types.RegistryOptions) ([]name.Reference, error) { + var mirrors []name.Reference + + reg := hostRef.Context().RegistryStr() + if ms, ok := option.RegistryMirrors[reg]; ok { + for _, m := range ms { + var nameOpts []name.Option + if option.Insecure { + nameOpts = append(nameOpts, name.Insecure) + } + mirrorImageName := strings.Replace(hostRef.Name(), reg, m, 1) + ref, err := name.ParseReference(mirrorImageName, nameOpts...) + if err != nil { + return nil, xerrors.Errorf("unable to parse image from mirror registry: %w", err) + } + mirrors = append(mirrors, ref) + } + } + return mirrors, nil +} + func httpTransport(option types.RegistryOptions) (http.RoundTripper, error) { d := &net.Dialer{ Timeout: 10 * time.Minute, @@ -166,7 +238,7 @@ func authOptions(ctx context.Context, ref name.Reference, option types.RegistryO return []remote.Option{remote.WithAuth(&bearer)} default: // Use the keychain anyway at the end - opts = append(opts, remote.WithAuthFromKeychain(authn.DefaultKeychain)) + opts = append(opts, remote.WithAuthFromKeychain(authn.NewMultiKeychain(authn.DefaultKeychain, github.Keychain))) return opts } } diff --git a/pkg/remote/remote_test.go b/pkg/remote/remote_test.go index fb64deb5d4c4..639a340a112b 100644 --- a/pkg/remote/remote_test.go +++ b/pkg/remote/remote_test.go @@ -20,6 +20,7 @@ import ( "github.com/aquasecurity/testdocker/registry" "github.com/aquasecurity/testdocker/tarfile" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/version/app" ) @@ -92,6 +93,81 @@ func TestGet(t *testing.T) { }, }, }, + { + name: "mirror", + args: args{ + imageName: "foo.bar.io/library/alpine:3.10", + option: types.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "test", + Password: "testpass", + }, + }, + RegistryMirrors: map[string][]string{ + "foo.bar.io": { + serverAddr, + }, + }, + Insecure: true, + }, + }, + }, + { + name: "mirror for dockerhub", + args: args{ + imageName: "alpine:3.10", + option: types.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "test", + Password: "testpass", + }, + }, + RegistryMirrors: map[string][]string{ + "index.docker.io": { + serverAddr, + }, + }, + Insecure: true, + }, + }, + }, + { + name: "non-existent mirror image - use image from host", + args: args{ + imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), + option: types.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "test", + Password: "testpass", + }, + }, + RegistryMirrors: map[string][]string{ + serverAddr: { + "wrong.repository", + }, + }, + Insecure: true, + }, + }, + }, + { + name: "wrong mirror", + args: args{ + imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), + option: types.RegistryOptions{ + RegistryMirrors: map[string][]string{ + serverAddr: { + "wrong.repository:tag@digest", + }, + }, + Insecure: true, + }, + }, + wantErr: "could not parse reference: wrong.repository:tag@digest/library/alpine:3.10", + }, { name: "multiple credential", args: args{ @@ -181,6 +257,28 @@ func TestGet(t *testing.T) { }, wantErr: "invalid username/password", }, + { + name: "bad credential for multiple mirrors", + args: args{ + imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), + option: types.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "foo", + Password: "bar", + }, + }, + Insecure: true, + RegistryMirrors: map[string][]string{ + serverAddr: { + serverAddr, + serverAddr, + }, + }, + }, + }, + wantErr: "6 errors occurred:", // 2 errors for each repository (for 2 mirrors and the original repository) + }, { name: "bad keychain", args: args{ @@ -216,13 +314,13 @@ type userAgentsTrackingHandler struct { hr http.Handler mu sync.Mutex - agents map[string]struct{} + agents set.Set[string] } func newUserAgentsTrackingHandler(hr http.Handler) *userAgentsTrackingHandler { return &userAgentsTrackingHandler{ hr: hr, - agents: make(map[string]struct{}), + agents: set.New[string](), } } @@ -230,7 +328,7 @@ func (uh *userAgentsTrackingHandler) ServeHTTP(rw http.ResponseWriter, r *http.R for _, agent := range r.Header["User-Agent"] { // Skip test framework user agent if agent != "Go-http-client/1.1" { - uh.agents[agent] = struct{}{} + uh.agents.Append(agent) } } uh.hr.ServeHTTP(rw, r) @@ -271,7 +369,7 @@ func TestUserAgents(t *testing.T) { require.NoError(t, err) require.Len(t, tracker.agents, 1) - _, ok := tracker.agents[fmt.Sprintf("trivy/%s go-containerregistry", app.Version())] + ok := tracker.agents.Contains(fmt.Sprintf("trivy/%s go-containerregistry", app.Version())) require.True(t, ok, `user-agent header equals to "trivy/dev go-containerregistry"`) } diff --git a/pkg/report/table/misconfig.go b/pkg/report/table/misconfig.go index 41f111d883c9..604b7db0be67 100644 --- a/pkg/report/table/misconfig.go +++ b/pkg/report/table/misconfig.go @@ -3,6 +3,7 @@ package table import ( "bytes" "fmt" + "strconv" "strings" "github.com/fatih/color" @@ -168,7 +169,7 @@ func (r *misconfigRenderer) renderCode(misconf types.DetectedMisconfiguration) { for i, occ := range misconf.CauseMetadata.Occurrences { lineInfo := fmt.Sprintf("%d-%d", occ.Location.StartLine, occ.Location.EndLine) if occ.Location.StartLine >= occ.Location.EndLine { - lineInfo = fmt.Sprintf("%d", occ.Location.StartLine) + lineInfo = strconv.Itoa(occ.Location.StartLine) } r.printf( @@ -184,7 +185,7 @@ func (r *misconfigRenderer) renderCode(misconf types.DetectedMisconfiguration) { for i, line := range lines { switch { case line.Truncated: - r.printf("%4s ", strings.Repeat(".", len(fmt.Sprintf("%d", line.Number)))) + r.printf("%4s ", strings.Repeat(".", len(strconv.Itoa(line.Number)))) case line.IsCause: r.printf("%4d ", line.Number) switch { diff --git a/pkg/report/table/secret.go b/pkg/report/table/secret.go index cff91a98d9ed..1b1cf78dda21 100644 --- a/pkg/report/table/secret.go +++ b/pkg/report/table/secret.go @@ -3,6 +3,7 @@ package table import ( "bytes" "fmt" + "strconv" "strings" "golang.org/x/term" @@ -141,7 +142,7 @@ func (r *secretRenderer) renderCode(secret types.DetectedSecret) { for i, line := range lines { switch { case line.Truncated: - r.printf("%4s ", strings.Repeat(".", len(fmt.Sprintf("%d", line.Number)))) + r.printf("%4s ", strings.Repeat(".", len(strconv.Itoa(line.Number)))) case line.IsCause: r.printf("%4d ", line.Number) switch { diff --git a/pkg/report/table/vulnerability.go b/pkg/report/table/vulnerability.go index 450349ed5fcb..1c08236a033c 100644 --- a/pkg/report/table/vulnerability.go +++ b/pkg/report/table/vulnerability.go @@ -19,6 +19,7 @@ import ( dbTypes "github.com/aquasecurity/trivy-db/pkg/types" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/version/doc" ) @@ -279,7 +280,7 @@ Dependency Origin Tree (Reversed) topLvlID := tml.Sprintf("%s, (%s)", vulnPkg.ID, strings.Join(summaries, ", ")) branch := root.AddBranch(topLvlID) - addParents(branch, vulnPkg, parents, ancestors, map[string]struct{}{vulnPkg.ID: {}}, 1) + addParents(branch, vulnPkg, parents, ancestors, set.New(vulnPkg.ID), 1) } r.printf(root.String()) @@ -291,17 +292,17 @@ func (r *vulnerabilityRenderer) printf(format string, args ...any) { } func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string]ftypes.Packages, ancestors map[string][]string, - seen map[string]struct{}, depth int) { + seen set.Set[string], depth int) { if pkg.Relationship == ftypes.RelationshipDirect { return } - roots := make(map[string]struct{}) + roots := set.New[string]() for _, parent := range parentMap[pkg.ID] { - if _, ok := seen[parent.ID]; ok { + if seen.Contains(parent.ID) { continue } - seen[parent.ID] = struct{}{} // to avoid infinite loops + seen.Append(parent.ID) // to avoid infinite loops if depth == 1 && parent.Relationship == ftypes.RelationshipDirect { topItem.AddBranch(parent.ID) @@ -309,16 +310,13 @@ func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string // We omit intermediate dependencies and show only direct dependencies // as this could make the dependency tree huge. for _, ancestor := range ancestors[parent.ID] { - roots[ancestor] = struct{}{} + roots.Append(ancestor) } } } // Omitted - rootIDs := lo.Filter(lo.Keys(roots), func(pkgID string, _ int) bool { - _, ok := seen[pkgID] - return !ok - }) + rootIDs := roots.Difference(seen).Items() sort.Strings(rootIDs) if len(rootIDs) > 0 { branch := topItem.AddBranch("...(omitted)...") @@ -331,21 +329,21 @@ func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string func traverseAncestors(pkgs []ftypes.Package, parentMap map[string]ftypes.Packages) map[string][]string { ancestors := make(map[string][]string) for _, pkg := range pkgs { - ancestors[pkg.ID] = findAncestor(pkg.ID, parentMap, make(map[string]struct{})) + ancestors[pkg.ID] = findAncestor(pkg.ID, parentMap, set.New[string]()) } return ancestors } -func findAncestor(pkgID string, parentMap map[string]ftypes.Packages, seen map[string]struct{}) []string { - ancestors := make(map[string]struct{}) - seen[pkgID] = struct{}{} +func findAncestor(pkgID string, parentMap map[string]ftypes.Packages, seen set.Set[string]) []string { + ancestors := set.New[string]() + seen.Append(pkgID) for _, parent := range parentMap[pkgID] { - if _, ok := seen[parent.ID]; ok { + if seen.Contains(parent.ID) { continue } switch { case parent.Relationship == ftypes.RelationshipDirect: - ancestors[parent.ID] = struct{}{} + ancestors.Append(parent.ID) case len(parentMap[parent.ID]) == 0: // Some package managers, such as "package-lock.json" v1, can retrieve package dependencies but not relationships. // We try to guess direct dependencies in this case. A dependency with no parents must be a direct dependency. @@ -358,14 +356,14 @@ func findAncestor(pkgID string, parentMap map[string]ftypes.Packages, seen map[s // // Even if `styled-components` is not marked as a direct dependency, it must be a direct dependency // as it has no parents. Note that it doesn't mean `fbjs` is an indirect dependency. - ancestors[parent.ID] = struct{}{} + ancestors.Append(parent.ID) default: for _, a := range findAncestor(parent.ID, parentMap, seen) { - ancestors[a] = struct{}{} + ancestors.Append(a) } } } - return lo.Keys(ancestors) + return ancestors.Items() } var jarExtensions = []string{ diff --git a/pkg/result/ignore_test.go b/pkg/result/ignore_test.go index 68248d7e17b1..466139cebc77 100644 --- a/pkg/result/ignore_test.go +++ b/pkg/result/ignore_test.go @@ -49,7 +49,7 @@ func TestParseIgnoreFile(t *testing.T) { _, _ = f.WriteString("this file is not a yaml file") got, err := ParseIgnoreFile(context.TODO(), f.Name()) - assert.Contains(t, err.Error(), "yaml decode error") + require.ErrorContains(t, err, "yaml decode error") assert.Empty(t, got) }) diff --git a/pkg/rpc/client/client.go b/pkg/rpc/client/client.go index ed7d130dcb06..dd13b145878f 100644 --- a/pkg/rpc/client/client.go +++ b/pkg/rpc/client/client.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "net/http" + "github.com/samber/lo" "github.com/twitchtv/twirp" "golang.org/x/xerrors" @@ -12,6 +13,7 @@ import ( r "github.com/aquasecurity/trivy/pkg/rpc" "github.com/aquasecurity/trivy/pkg/types" xstrings "github.com/aquasecurity/trivy/pkg/x/strings" + "github.com/aquasecurity/trivy/rpc/common" rpc "github.com/aquasecurity/trivy/rpc/scanner" ) @@ -75,6 +77,14 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys licenseCategories[string(category)] = &rpc.Licenses{Names: names} } + var distro *common.OS + if !lo.IsEmpty(opts.Distro) { + distro = &common.OS{ + Family: string(opts.Distro.Family), + Name: opts.Distro.Name, + } + } + var res *rpc.ScanResponse err := r.Retry(func() error { var err error @@ -88,6 +98,7 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys Scanners: xstrings.ToStringSlice(opts.Scanners), LicenseCategories: licenseCategories, IncludeDevDeps: opts.IncludeDevDeps, + Distro: distro, }, }) return err diff --git a/pkg/rpc/server/listen_test.go b/pkg/rpc/server/listen_test.go index 7f97bdbcb31e..9ec07a66b5e1 100644 --- a/pkg/rpc/server/listen_test.go +++ b/pkg/rpc/server/listen_test.go @@ -101,8 +101,7 @@ func Test_dbWorker_update(t *testing.T) { err = w.update(ctx, "1.2.3", dbDir, tt.skipUpdate, &dbUpdateWg, &requestWg, ftypes.RegistryOptions{}) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } require.NoError(t, err, tt.name) diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index bf4fa2ff5092..0bc7492783d8 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -75,12 +75,19 @@ func (s *ScanServer) ToOptions(in *rpcScanner.ScanOptions) types.ScanOptions { return ftypes.LicenseCategory(k), v.Names }) + var distro ftypes.OS + if in.Distro != nil { + distro.Family = ftypes.OSType(in.Distro.Family) + distro.Name = in.Distro.Name + } + return types.ScanOptions{ PkgTypes: in.PkgTypes, PkgRelationships: pkgRelationships, Scanners: scanners, IncludeDevDeps: in.IncludeDevDeps, LicenseCategories: licenseCategories, + Distro: distro, } } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 78db0c06aac3..7cf1e4adeb7e 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -174,8 +174,7 @@ func TestScanServer_Scan(t *testing.T) { s := NewScanServer(mockDriver) got, err := s.Scan(context.Background(), tt.args.in) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } require.NoError(t, err, tt.name) @@ -273,8 +272,7 @@ func TestCacheServer_PutArtifact(t *testing.T) { got, err := s.PutArtifact(context.Background(), tt.args.in) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -508,8 +506,7 @@ func TestCacheServer_PutBlob(t *testing.T) { got, err := s.PutBlob(context.Background(), tt.args.in) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) @@ -573,8 +570,7 @@ func TestCacheServer_MissingBlobs(t *testing.T) { s := NewCacheServer(mockCache) got, err := s.MissingBlobs(tt.args.ctx, tt.args.in) if tt.wantErr != "" { - require.Error(t, err, tt.name) - assert.Contains(t, err.Error(), tt.wantErr, tt.name) + require.ErrorContains(t, err, tt.wantErr, tt.name) return } else { require.NoError(t, err, tt.name) diff --git a/pkg/sbom/cyclonedx/marshal_test.go b/pkg/sbom/cyclonedx/marshal_test.go index 8b88c4ec762a..d1539bc31630 100644 --- a/pkg/sbom/cyclonedx/marshal_test.go +++ b/pkg/sbom/cyclonedx/marshal_test.go @@ -559,7 +559,6 @@ func TestMarshaler_MarshalReport(t *testing.T) { { Ref: "3ff14136-e09f-4df9-80ea-000000000004", Dependencies: &[]string{ - "3ff14136-e09f-4df9-80ea-000000000005", "pkg:gem/actioncontroller@7.0.0", }, }, @@ -1123,8 +1122,6 @@ func TestMarshaler_MarshalReport(t *testing.T) { Ref: "3ff14136-e09f-4df9-80ea-000000000002", Dependencies: &[]string{ "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1", - // Trivy is unable to identify the direct OS packages as of today. - "pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011", }, }, { diff --git a/pkg/sbom/cyclonedx/testdata/happy/nested-packages-bom.json b/pkg/sbom/cyclonedx/testdata/happy/nested-packages-bom.json new file mode 100644 index 000000000000..fd7623c73028 --- /dev/null +++ b/pkg/sbom/cyclonedx/testdata/happy/nested-packages-bom.json @@ -0,0 +1,172 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "serialNumber": "urn:uuid:12346a7a-5819-43bf-9411-5c146304f023", + "version": 1, + "metadata": { + "timestamp": "2024-12-20T10:57:13+00:00", + "tools": { + "components": [ + { + "type": "application", + "group": "aquasecurity", + "name": "trivy", + "version": "0.38.7-764-g30c7cb137" + } + ] + }, + "component": { + "bom-ref": "1cb40520-a22c-481f-ad77-6bc6960430c5", + "type": "application", + "name": "/test", + "properties": [ + { + "name": "aquasecurity:trivy:SchemaVersion", + "value": "2" + } + ] + } + }, + "components": [ + { + "bom-ref": "4021d631-e242-4e69-8a93-928665810a27", + "type": "application", + "name": "foo/bar/test.elf", + "properties": [ + { + "name": "aquasecurity:trivy:Class", + "value": "lang-pkgs" + }, + { + "name": "aquasecurity:trivy:Type", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + "type": "library", + "name": "github.com/aquasecurity/go-pep440-version", + "version": "v0.0.0-20210121094942-22b2f8951d46", + "purl": "pkg:golang/github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + "type": "library", + "name": "github.com/aquasecurity/go-version", + "version": "v0.0.0-20210121072130-637058cfe492", + "purl": "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/github.com/aquasecurity/test", + "type": "library", + "name": "github.com/aquasecurity/test", + "purl": "pkg:golang/github.com/aquasecurity/test", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "github.com/aquasecurity/test" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + "type": "library", + "name": "golang.org/x/xerrors", + "version": "v0.0.0-20200804184101-5ec99f83aff1", + "purl": "pkg:golang/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/stdlib@v1.15.2", + "type": "library", + "name": "stdlib", + "version": "v1.15.2", + "purl": "pkg:golang/stdlib@v1.15.2", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "stdlib@v1.15.2" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + } + ], + "dependencies": [ + { + "ref": "1cb40520-a22c-481f-ad77-6bc6960430c5", + "dependsOn": [ + "4021d631-e242-4e69-8a93-928665810a27" + ] + }, + { + "ref": "4021d631-e242-4e69-8a93-928665810a27", + "dependsOn": [ + "pkg:golang/github.com/aquasecurity/test" + ] + }, + { + "ref": "pkg:golang/github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + "dependsOn": [] + }, + { + "ref": "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + "dependsOn": [] + }, + { + "ref": "pkg:golang/github.com/aquasecurity/test", + "dependsOn": [ + "pkg:golang/github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + "pkg:golang/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + "pkg:golang/stdlib@v1.15.2" + ] + }, + { + "ref": "pkg:golang/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + "dependsOn": [] + }, + { + "ref": "pkg:golang/stdlib@v1.15.2", + "dependsOn": [] + } + ], + "vulnerabilities": [] +} diff --git a/pkg/sbom/cyclonedx/unmarshal_test.go b/pkg/sbom/cyclonedx/unmarshal_test.go index 7008efb8e9eb..27a116a8e42c 100644 --- a/pkg/sbom/cyclonedx/unmarshal_test.go +++ b/pkg/sbom/cyclonedx/unmarshal_test.go @@ -668,6 +668,93 @@ func TestUnmarshaler_Unmarshal(t *testing.T) { }, }, }, + { + name: "happy path for BOM with nested packages", + inputFile: "testdata/happy/nested-packages-bom.json", + want: types.SBOM{ + Applications: []ftypes.Application{ + { + Type: "gobinary", + FilePath: "foo/bar/test.elf", + Packages: ftypes.Packages{ + { + ID: "github.com/aquasecurity/test", + Name: "github.com/aquasecurity/test", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "test", + }, + BOMRef: "pkg:golang/github.com/aquasecurity/test", + }, + DependsOn: []string{ + "github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + "github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + "stdlib@v1.15.2", + }, + }, + { + ID: "github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + Name: "github.com/aquasecurity/go-pep440-version", + Version: "v0.0.0-20210121094942-22b2f8951d46", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "go-pep440-version", + Version: "v0.0.0-20210121094942-22b2f8951d46", + }, + BOMRef: "pkg:golang/github.com/aquasecurity/go-pep440-version@v0.0.0-20210121094942-22b2f8951d46", + }, + }, + { + ID: "github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + Name: "github.com/aquasecurity/go-version", + Version: "v0.0.0-20210121072130-637058cfe492", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "go-version", + Version: "v0.0.0-20210121072130-637058cfe492", + }, + BOMRef: "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20210121072130-637058cfe492", + }, + }, + { + ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + Name: "golang.org/x/xerrors", + Version: "v0.0.0-20200804184101-5ec99f83aff1", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "golang.org/x", + Name: "xerrors", + Version: "v0.0.0-20200804184101-5ec99f83aff1", + }, + BOMRef: "pkg:golang/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", + }, + }, + { + ID: "stdlib@v1.15.2", + Name: "stdlib", + Version: "v1.15.2", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Name: "stdlib", + Version: "v1.15.2", + }, + BOMRef: "pkg:golang/stdlib@v1.15.2", + }, + }, + }, + }, + }, + }, + }, { name: "happy path only os component", inputFile: "testdata/happy/os-only-bom.json", diff --git a/pkg/sbom/io/decode.go b/pkg/sbom/io/decode.go index 6cfc79a0871c..4920f08b7323 100644 --- a/pkg/sbom/io/decode.go +++ b/pkg/sbom/io/decode.go @@ -330,15 +330,7 @@ func (m *Decoder) parseSrcVersion(ctx context.Context, pkg *ftypes.Package, ver // addOSPkgs traverses relationships and adds OS packages func (m *Decoder) addOSPkgs(sbom *types.SBOM) { - var pkgs []ftypes.Package - for _, rel := range m.bom.Relationships()[m.osID] { - pkg, ok := m.pkgs[rel.Dependency] - if !ok { - continue - } - pkgs = append(pkgs, *pkg) - delete(m.pkgs, rel.Dependency) // Delete the added package - } + pkgs := m.traverseDependencies(m.osID) if len(pkgs) == 0 { return } @@ -348,18 +340,33 @@ func (m *Decoder) addOSPkgs(sbom *types.SBOM) { // addLangPkgs traverses relationships and adds language-specific packages func (m *Decoder) addLangPkgs(sbom *types.SBOM) { for id, app := range m.apps { - for _, rel := range m.bom.Relationships()[id] { - pkg, ok := m.pkgs[rel.Dependency] - if !ok { - continue - } - app.Packages = append(app.Packages, *pkg) - delete(m.pkgs, rel.Dependency) // Delete the added package - } + app.Packages = append(app.Packages, m.traverseDependencies(id)...) sbom.Applications = append(sbom.Applications, *app) } } +// traverseDependencies recursively retrieves all packages that the specified component depends on. +// It starts from the given component ID and traverses the dependency tree, collecting all +// dependent packages. The collected packages are removed from m.pkgs to prevent duplicate +// processing. This ensures that all dependencies, including transitive ones, are properly +// captured and associated with their parent component. +func (m *Decoder) traverseDependencies(id uuid.UUID) ftypes.Packages { + var pkgs ftypes.Packages + for _, rel := range m.bom.Relationships()[id] { + pkg, ok := m.pkgs[rel.Dependency] + if !ok { + continue + } + // Add the current package + pkgs = append(pkgs, *pkg) + delete(m.pkgs, rel.Dependency) // Delete the added package + + // Add the nested packages + pkgs = append(pkgs, m.traverseDependencies(rel.Dependency)...) + } + return pkgs +} + // addOrphanPkgs adds orphan packages. // Orphan packages are packages that are not related to any components. func (m *Decoder) addOrphanPkgs(ctx context.Context, sbom *types.SBOM) error { diff --git a/pkg/sbom/io/encode.go b/pkg/sbom/io/encode.go index 97c1664303c7..f383faf466be 100644 --- a/pkg/sbom/io/encode.go +++ b/pkg/sbom/io/encode.go @@ -417,18 +417,10 @@ func (*Encoder) belongToParent(pkg ftypes.Package, parents map[string]ftypes.Pac // All packages are included in the parent // Case 3: Relationship: known , DependsOn: unknown (e.g., go.mod without $GOPATH) // All packages are included in the parent - // Case 4: Relationship: unknown, DependsOn: known (e.g., OS packages) - // All packages are included in the parent even if they have parents - switch { - // Case 1, 2 and 3 - case len(parents[pkg.ID]) == 0: - return true - // Case 4 - case pkg.Relationship == ftypes.RelationshipUnknown: - return true - default: - return false - } + // Case 4: Relationship: unknown, DependsOn: known (e.g., GoBinaries, OS packages) + // - Packages with parents: false. These packages are included in the packages from `parents` (e.g. GoBinaries deps and root package). + // - Packages without parents: true. These packages are included in the parent (e.g. OS packages without parents). + return len(parents[pkg.ID]) == 0 } func filterProperties(props []core.Property) []core.Property { diff --git a/pkg/sbom/io/encode_test.go b/pkg/sbom/io/encode_test.go index 93cdd2a9410c..99b1010221d5 100644 --- a/pkg/sbom/io/encode_test.go +++ b/pkg/sbom/io/encode_test.go @@ -171,6 +171,61 @@ func TestEncoder_Encode(t *testing.T) { }, }, }, + { + Target: "trivy", + Type: ftypes.GoBinary, + Class: types.ClassLangPkg, + Packages: []ftypes.Package{ + { + ID: "github.com/aquasecurity/trivy@v0.57.1", + Name: "github.com/aquasecurity/trivy", + Version: "v0.57.1", + Identifier: ftypes.PkgIdentifier{ + UID: "106fee7e57f0b952", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "trivy", + Version: "v0.57.1", + }, + }, + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", + "stdlib@v1.22.9", + }, + }, + { + ID: "stdlib@v1.22.9", + Name: "stdlib", + Version: "v1.22.9", + Identifier: ftypes.PkgIdentifier{ + UID: "62e7c8aaebd94b1e", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Name: "stdlib", + Version: "v1.22.9", + }, + }, + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", + Name: "github.com/aquasecurity/go-version", + Version: "v0.0.0-20240603093900-cf8a8d29271d", + Identifier: ftypes.PkgIdentifier{ + UID: "350aed171d8ebed5", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "go-version", + Version: "v0.0.0-20240603093900-cf8a8d29271d", + }, + }, + Relationship: ftypes.RelationshipUnknown, + }, + }, + }, }, }, wantComponents: map[uuid.UUID]*core.Component{ @@ -351,6 +406,100 @@ func TestEncoder_Encode(t *testing.T) { BOMRef: "3ff14136-e09f-4df9-80ea-000000000006", }, }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"): { + Type: core.TypeApplication, + Name: "trivy", + Properties: []core.Property{ + { + Name: core.PropertyClass, + Value: "lang-pkgs", + }, + { + Name: core.PropertyType, + Value: "gobinary", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + BOMRef: "3ff14136-e09f-4df9-80ea-000000000007", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000008"): { + Type: core.TypeLibrary, + Name: "github.com/aquasecurity/trivy", + Version: "v0.57.1", + SrcFile: "trivy", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "github.com/aquasecurity/trivy@v0.57.1", + }, + { + Name: core.PropertyPkgType, + Value: "gobinary", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "106fee7e57f0b952", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "trivy", + Version: "v0.57.1", + }, + BOMRef: "pkg:golang/github.com/aquasecurity/trivy@v0.57.1", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000009"): { + Type: core.TypeLibrary, + Name: "stdlib", + Version: "v1.22.9", + SrcFile: "trivy", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "stdlib@v1.22.9", + }, + { + Name: core.PropertyPkgType, + Value: "gobinary", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "62e7c8aaebd94b1e", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Name: "stdlib", + Version: "v1.22.9", + }, + BOMRef: "pkg:golang/stdlib@v1.22.9", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000010"): { + Type: core.TypeLibrary, + Name: "github.com/aquasecurity/go-version", + Version: "v0.0.0-20240603093900-cf8a8d29271d", + SrcFile: "trivy", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", + }, + { + Name: core.PropertyPkgType, + Value: "gobinary", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "350aed171d8ebed5", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeGolang, + Namespace: "github.com/aquasecurity", + Name: "go-version", + Version: "v0.0.0-20240603093900-cf8a8d29271d", + }, + BOMRef: "pkg:golang/github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", + }, + }, }, wantRels: map[uuid.UUID][]core.Relationship{ uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000001"): { @@ -366,12 +515,12 @@ func TestEncoder_Encode(t *testing.T) { Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"), Type: core.RelationshipContains, }, - }, - uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): { { - Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"), + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"), Type: core.RelationshipContains, }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): { { Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000004"), Type: core.RelationshipContains, @@ -386,6 +535,24 @@ func TestEncoder_Encode(t *testing.T) { }, uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000005"): nil, uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"): nil, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000008"), + Type: core.RelationshipContains, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000008"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000010"), + Type: core.RelationshipDependsOn, + }, + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000009"), + Type: core.RelationshipDependsOn, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000009"): nil, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000010"): nil, }, wantVulns: map[uuid.UUID][]core.Vulnerability{ uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000004"): { diff --git a/pkg/sbom/spdx/marshal.go b/pkg/sbom/spdx/marshal.go index 51f9144f682d..38e2cafc50f6 100644 --- a/pkg/sbom/spdx/marshal.go +++ b/pkg/sbom/spdx/marshal.go @@ -5,6 +5,7 @@ import ( "fmt" "slices" "sort" + "strconv" "strings" "time" @@ -60,6 +61,8 @@ const ( ElementApplication = "Application" ElementPackage = "Package" ElementFile = "File" + + LicenseRefPrefix = "LicenseRef" ) var ( @@ -82,6 +85,7 @@ type Marshaler struct { format spdx.Document hasher Hash appVersion string // Trivy version. It needed for `creator` field + logger *log.Logger } type Hash func(v any, format hashstructure.Format, opts *hashstructure.HashOptions) (uint64, error) @@ -99,6 +103,7 @@ func NewMarshaler(version string, opts ...marshalOption) *Marshaler { format: spdx.Document{}, hasher: hashstructure.Hash, appVersion: version, + logger: log.WithPrefix(log.PrefixSPDX), } for _, opt := range opts { @@ -145,6 +150,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, packageIDs[root.ID()] = rootPkg.PackageSPDXIdentifier var files []*spdx.File + var otherLicenses []*spdx.OtherLicense for _, c := range bom.Components() { if c.Root { continue @@ -165,6 +171,14 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, packages = append(packages, &spdxPackage) packageIDs[c.ID()] = spdxPackage.PackageSPDXIdentifier + // Fill licenses + license, others := m.spdxLicense(c) + // The Declared License is what the authors of a project believe govern the package + spdxPackage.PackageLicenseConcluded = license + // The Concluded License field is the license the SPDX file creator believes governs the package + spdxPackage.PackageLicenseDeclared = license + otherLicenses = append(otherLicenses, others...) + spdxFiles, err := m.spdxFiles(c) if err != nil { return nil, xerrors.Errorf("spdx files error: %w", err) @@ -203,6 +217,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, sortPackages(packages) sortRelationships(relationShips) sortFiles(files) + otherLicenses = sortOtherLicenses(otherLicenses) return &spdx.Document{ SPDXVersion: spdx.Version, @@ -226,6 +241,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, Packages: packages, Relationships: relationShips, Files: files, + OtherLicenses: otherLicenses, }, nil } @@ -249,7 +265,7 @@ func (m *Marshaler) rootSPDXPackage(root *core.Component, timeNow, pkgDownloadLo externalReferences = append(externalReferences, m.purlExternalReference(root.PkgIdentifier.PURL.String())) } - pkgID, err := calcPkgID(m.hasher, fmt.Sprintf("%s-%s", root.Name, root.Type)) + pkgID, err := calcSPDXID(m.hasher, fmt.Sprintf("%s-%s", root.Name, root.Type)) if err != nil { return nil, xerrors.Errorf("failed to get %s package ID: %w", pkgID, err) } @@ -301,12 +317,12 @@ func (m *Marshaler) advisoryExternalReference(primaryURL string) *spdx.PackageEx } func (m *Marshaler) spdxPackage(c *core.Component, timeNow, pkgDownloadLocation string) (spdx.Package, error) { - pkgID, err := calcPkgID(m.hasher, c) + pkgID, err := calcSPDXID(m.hasher, c) if err != nil { return spdx.Package{}, xerrors.Errorf("failed to get os metadata package ID: %w", err) } - var elementType, purpose, license, sourceInfo string + var elementType, purpose, sourceInfo string var supplier *spdx.Supplier switch c.Type { case core.TypeOS: @@ -318,7 +334,9 @@ func (m *Marshaler) spdxPackage(c *core.Component, timeNow, pkgDownloadLocation case core.TypeLibrary: elementType = ElementPackage purpose = PackagePurposeLibrary - license = m.spdxLicense(c) + + // We need to create a new `LicesenRef-*` component for licenses that are not in the SPDX license list + // So we will fill licenses later if c.SrcName != "" { sourceInfo = fmt.Sprintf("%s: %s %s", SourcePackagePrefix, c.SrcName, c.SrcVersion) @@ -360,12 +378,6 @@ func (m *Marshaler) spdxPackage(c *core.Component, timeNow, pkgDownloadLocation PackageSourceInfo: sourceInfo, PackageSupplier: supplier, PackageChecksums: m.spdxChecksums(digests), - - // The Declared License is what the authors of a project believe govern the package - PackageLicenseConcluded: license, - - // The Concluded License field is the license the SPDX file creator believes governs the package - PackageLicenseDeclared: license, }, nil } @@ -389,11 +401,94 @@ func (m *Marshaler) spdxAnnotations(c *core.Component, timeNow string) []spdx.An return annotations } -func (m *Marshaler) spdxLicense(c *core.Component) string { +func (m *Marshaler) spdxLicense(c *core.Component) (string, []*spdx.OtherLicense) { + // Only library components contain licenses + if c.Type != core.TypeLibrary { + return "", nil + } if len(c.Licenses) == 0 { - return noAssertionField + return noAssertionField, nil } - return NormalizeLicense(c.Licenses) + return m.normalizeLicenses(c.Licenses) +} + +func (m *Marshaler) normalizeLicenses(licenses []string) (string, []*spdx.OtherLicense) { + var otherLicenses = make(map[string]*spdx.OtherLicense) // licenseID -> OtherLicense + + license := strings.Join(lo.Map(licenses, func(license string, index int) string { + // e.g. GPL-3.0-with-autoconf-exception + license = strings.ReplaceAll(license, "-with-", " WITH ") + license = strings.ReplaceAll(license, "-WITH-", " WITH ") + return fmt.Sprintf("(%s)", license) + }), " AND ") + + replaceOtherLicenses := func(expr expression.Expression) expression.Expression { + var licenseName string + var textLicense bool + switch e := expr.(type) { + case expression.SimpleExpr: + // Trim `text:--` prefix (expression.NormalizeForSPDX normalized `text://` prefix) + if strings.HasPrefix(e.License, "text:--") { + textLicense = true + e.License = strings.TrimPrefix(e.License, "text:--") + } + + if expression.ValidateSPDXLicense(e.License) || expression.ValidateSPDXException(e.License) { + return e + } + + licenseName = e.License + case expression.CompoundExpr: + // Check only CompoundExpr with `WITH` token as one license + if e.Conjunction() != expression.TokenWith { + return expr + } + + // Check that license and exception are valid + if expression.ValidateSPDXLicense(e.Left().String()) && expression.ValidateSPDXException(e.Right().String()) { + // Use SimpleExpr for a valid SPDX license with an exception, + // to avoid parsing the license and exception separately. + return e + } + + licenseName = e.String() + } + + l := m.newOtherLicense(licenseName, textLicense) + otherLicenses[l.LicenseIdentifier] = l + return expression.SimpleExpr{License: l.LicenseIdentifier} + } + + normalizedLicense, err := expression.Normalize(license, licensing.NormalizeLicense, expression.NormalizeForSPDX, replaceOtherLicenses) + if err != nil { + // Not fail on the invalid license + m.logger.Warn("Unable to marshal SPDX licenses", log.String("license", license)) + return "", nil + } + + return normalizedLicense, lo.Ternary(len(otherLicenses) > 0, lo.Values(otherLicenses), nil) +} + +// newOtherLicense create new OtherLicense for license not included in the SPDX license list +func (m *Marshaler) newOtherLicense(license string, text bool) *spdx.OtherLicense { + otherLicense := spdx.OtherLicense{} + if text { + otherLicense.LicenseName = noAssertionField + otherLicense.ExtractedText = license + otherLicense.LicenseComment = "The license text represents text found in package metadata and may not represent the full text of the license" + } else { + otherLicense.LicenseName = license + otherLicense.ExtractedText = fmt.Sprintf("This component is licensed under %q", license) + } + licenseID, err := calcSPDXID(m.hasher, otherLicense) + if err != nil { + // This must be an unattainable case. + m.logger.Warn("Unable to calculate SPDX licenses ID", log.String("license", license), log.Err(err)) + licenseID = license + } + otherLicense.LicenseIdentifier = LicenseRefPrefix + "-" + licenseID + + return &otherLicense } func (m *Marshaler) spdxChecksums(digests []digest.Digest) []common.Checksum { @@ -435,7 +530,7 @@ func (m *Marshaler) spdxFiles(c *core.Component) ([]*spdx.File, error) { } func (m *Marshaler) spdxFile(filePath string, digests []digest.Digest) (*spdx.File, error) { - pkgID, err := calcPkgID(m.hasher, filePath) + pkgID, err := calcSPDXID(m.hasher, filePath) if err != nil { return nil, xerrors.Errorf("failed to get %s package ID: %w", filePath, err) } @@ -505,6 +600,20 @@ func sortFiles(files []*spdx.File) { }) } +// sortOtherLicenses removes duplicates and sorts result slice +func sortOtherLicenses(licenses []*spdx.OtherLicense) []*spdx.OtherLicense { + if len(licenses) == 0 { + return nil + } + licenses = lo.UniqBy(licenses, func(license *spdx.OtherLicense) string { + return license.LicenseIdentifier + }) + sort.Slice(licenses, func(i, j int) bool { + return licenses[i].LicenseIdentifier < licenses[j].LicenseIdentifier + }) + return licenses +} + func elementID(elementType, pkgID string) spdx.ElementID { return spdx.ElementID(fmt.Sprintf("%s-%s", elementType, pkgID)) } @@ -518,16 +627,16 @@ func getDocumentNamespace(root *core.Component) string { ) } -func calcPkgID(h Hash, v any) (string, error) { +func calcSPDXID(h Hash, v any) (string, error) { f, err := h(v, hashstructure.FormatV2, &hashstructure.HashOptions{ ZeroNil: true, SlicesAsSets: true, }) if err != nil { - return "", xerrors.Errorf("could not build package ID for %+v: %w", v, err) + return "", xerrors.Errorf("could not build component ID for %+v: %w", v, err) } - return fmt.Sprintf("%x", f), nil + return strconv.FormatUint(f, 16), nil } func camelCase(inputUnderScoreStr string) (camelCase string) { @@ -550,20 +659,3 @@ func camelCase(inputUnderScoreStr string) (camelCase string) { } return } - -func NormalizeLicense(licenses []string) string { - license := strings.Join(lo.Map(licenses, func(license string, index int) string { - // e.g. GPL-3.0-with-autoconf-exception - license = strings.ReplaceAll(license, "-with-", " WITH ") - license = strings.ReplaceAll(license, "-WITH-", " WITH ") - - return fmt.Sprintf("(%s)", license) - }), " AND ") - s, err := expression.Normalize(license, licensing.NormalizeLicense, expression.NormalizeForSPDX) - if err != nil { - // Not fail on the invalid license - log.Warn("Unable to marshal SPDX licenses", log.String("license", license)) - return "" - } - return s -} diff --git a/pkg/sbom/spdx/marshal_private_test.go b/pkg/sbom/spdx/marshal_private_test.go new file mode 100644 index 000000000000..3f2161bd40ed --- /dev/null +++ b/pkg/sbom/spdx/marshal_private_test.go @@ -0,0 +1,136 @@ +package spdx + +import ( + "sort" + "testing" + + "github.com/spdx/tools-golang/spdx" + "github.com/stretchr/testify/assert" +) + +func TestMarshaler_normalizeLicenses(t *testing.T) { + tests := []struct { + name string + input []string + wantLicenseName string + wantOtherLicenses []*spdx.OtherLicense + }{ + { + name: "happy path", + input: []string{ + "GPLv2+", + }, + wantLicenseName: "GPL-2.0-or-later", + }, + { + name: "happy path with multi license", + input: []string{ + "GPLv2+", + "GPLv3+", + "BSD-4-Clause", + }, + wantLicenseName: "GPL-2.0-or-later AND GPL-3.0-or-later AND BSD-4-Clause", + }, + { + name: "happy path with OR operator", + input: []string{ + "GPLv2+", + "LGPL 2.0 or GNU LESSER", + }, + wantLicenseName: "GPL-2.0-or-later AND (LGPL-2.0-only OR LGPL-2.1-only)", + }, + { + name: "happy path with OR operator with non-SPDX license", + input: []string{ + "GPLv2+", + "wrong-license or unknown-license", + }, + wantLicenseName: "GPL-2.0-or-later AND (LicenseRef-c581e42fe705aa48 OR LicenseRef-a0bb0951a6dfbdbe)", + wantOtherLicenses: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-a0bb0951a6dfbdbe", + LicenseName: "unknown-license", + ExtractedText: `This component is licensed under "unknown-license"`, + }, + { + LicenseIdentifier: "LicenseRef-c581e42fe705aa48", + LicenseName: "wrong-license", + ExtractedText: `This component is licensed under "wrong-license"`, + }, + }, + }, + { + name: "happy path with AND operator", + input: []string{ + "GPLv2+", + "LGPL 2.0 and GNU LESSER", + }, + wantLicenseName: "GPL-2.0-or-later AND LGPL-2.0-only AND LGPL-2.1-only", + }, + { + name: "happy path with WITH operator", + input: []string{ + "AFL 2.0", + "AFL 3.0 with Autoconf-exception-3.0", + }, + wantLicenseName: "AFL-2.0 AND AFL-3.0 WITH Autoconf-exception-3.0", + }, + { + name: "happy path with non-SPDX exception", + input: []string{ + "AFL 2.0", + "AFL 3.0 with wrong-exceptions", + }, + wantLicenseName: "AFL-2.0 AND LicenseRef-51373b28fab165e9", + wantOtherLicenses: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-51373b28fab165e9", + LicenseName: "AFL-3.0 WITH wrong-exceptions", + ExtractedText: `This component is licensed under "AFL-3.0 WITH wrong-exceptions"`, + }, + }, + }, + { + name: "happy path with incorrect cases for license and exception", + input: []string{ + "afl 3.0 with autoCONF-exception-3.0", + }, + wantLicenseName: "AFL-3.0 WITH Autoconf-exception-3.0", + }, + { + name: "happy path with text of license", + input: []string{ + "text://unknown-license", + "AFL 2.0", + "unknown-license", + }, + wantLicenseName: "LicenseRef-ffca10435cadded4 AND AFL-2.0 AND LicenseRef-a0bb0951a6dfbdbe", + wantOtherLicenses: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-a0bb0951a6dfbdbe", + LicenseName: "unknown-license", + ExtractedText: `This component is licensed under "unknown-license"`, + }, + { + LicenseIdentifier: "LicenseRef-ffca10435cadded4", + LicenseName: "NOASSERTION", + ExtractedText: "unknown-license", + LicenseComment: "The license text represents text found in package metadata and may not represent the full text of the license", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := NewMarshaler("") + gotLicenseName, gotOtherLicenses := m.normalizeLicenses(tt.input) + // We will sort all OtherLicenses for SPDX document + // So we need to sort OtherLicenses for this test + sort.Slice(gotOtherLicenses, func(i, j int) bool { + return gotOtherLicenses[i].LicenseIdentifier < gotOtherLicenses[j].LicenseIdentifier + }) + assert.Equal(t, tt.wantLicenseName, gotLicenseName) + assert.Equal(t, tt.wantOtherLicenses, gotOtherLicenses) + }) + } +} diff --git a/pkg/sbom/spdx/marshal_test.go b/pkg/sbom/spdx/marshal_test.go index 4d9d33c013a7..5c8e3ab4902e 100644 --- a/pkg/sbom/spdx/marshal_test.go +++ b/pkg/sbom/spdx/marshal_test.go @@ -842,6 +842,148 @@ func TestMarshaler_Marshal(t *testing.T) { }, }, }, + { + name: "happy path with various licenses", + inputReport: types.Report{ + SchemaVersion: report.SchemaVersion, + ArtifactName: "pom.xml", + ArtifactType: artifact.TypeFilesystem, + Results: types.Results{ + { + Target: "pom.xml", + Class: types.ClassLangPkg, + Type: ftypes.Pom, + Packages: []ftypes.Package{ + { + ID: "com.example:example:1.0.0", + Name: "com.example:example", + Version: "1.0.0", + Identifier: ftypes.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "example", + Version: "1.0.0", + }, + }, + Licenses: []string{ + "text://BSD-4-clause", + "BSD-4-clause or LGPL-2.0-only", + "AFL 3.0 with wrong-exceptions", + "AFL 3.0 with Autoconf-exception-3.0", + "text://UNKNOWN", + "UNKNOWN", + }, + }, + }, + }, + }, + }, + wantSBOM: &spdx.Document{ + SPDXVersion: spdx.Version, + DataLicense: spdx.DataLicense, + SPDXIdentifier: "DOCUMENT", + DocumentName: "pom.xml", + DocumentNamespace: "http://aquasecurity.github.io/trivy/filesystem/pom.xml-3ff14136-e09f-4df9-80ea-000000000004", + CreationInfo: &spdx.CreationInfo{ + Creators: []common.Creator{ + { + Creator: "aquasecurity", + CreatorType: "Organization", + }, + { + Creator: "trivy-0.56.2", + CreatorType: "Tool", + }, + }, + Created: "2021-08-25T12:20:30Z", + }, + Packages: []*spdx.Package{ + { + PackageSPDXIdentifier: spdx.ElementID("Application-800d9e6e0f88ab3a"), + PackageDownloadLocation: "NONE", + PackageName: "pom.xml", + PrimaryPackagePurpose: tspdx.PackagePurposeApplication, + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: pom"), + }, + }, + { + PackageSPDXIdentifier: spdx.ElementID("Package-69cd7625c68537c7"), + PackageDownloadLocation: "NONE", + PackageName: "com.example:example", + PackageVersion: "1.0.0", + PackageLicenseConcluded: "LicenseRef-14b1606fb243e2b6 AND (BSD-4-Clause OR LGPL-2.0-only) AND LicenseRef-77bdf77d8292ce5b AND AFL-3.0 WITH Autoconf-exception-3.0 AND LicenseRef-229659393343e160 AND LicenseRef-a8d01765900624d3", + PackageLicenseDeclared: "LicenseRef-14b1606fb243e2b6 AND (BSD-4-Clause OR LGPL-2.0-only) AND LicenseRef-77bdf77d8292ce5b AND AFL-3.0 WITH Autoconf-exception-3.0 AND LicenseRef-229659393343e160 AND LicenseRef-a8d01765900624d3", + PackageExternalReferences: []*spdx.PackageExternalReference{ + { + Category: tspdx.CategoryPackageManager, + RefType: tspdx.RefTypePurl, + Locator: "pkg:maven/com.example/example@1.0.0", + }, + }, + PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, + PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, + PackageSourceInfo: "package found in: pom.xml", + Annotations: []spdx.Annotation{ + annotation(t, "PkgID: com.example:example:1.0.0"), + annotation(t, "PkgType: pom"), + }, + }, + { + PackageSPDXIdentifier: spdx.ElementID("Filesystem-340a6f62df359d6a"), + PackageDownloadLocation: "NONE", + PackageName: "pom.xml", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), + }, + PrimaryPackagePurpose: tspdx.PackagePurposeSource, + }, + }, + Relationships: []*spdx.Relationship{ + { + RefA: spdx.DocElementID{ElementRefID: "Application-800d9e6e0f88ab3a"}, + RefB: spdx.DocElementID{ElementRefID: "Package-69cd7625c68537c7"}, + Relationship: "CONTAINS", + }, + { + RefA: spdx.DocElementID{ElementRefID: "DOCUMENT"}, + RefB: spdx.DocElementID{ElementRefID: "Filesystem-340a6f62df359d6a"}, + Relationship: "DESCRIBES", + }, + { + RefA: spdx.DocElementID{ElementRefID: "Filesystem-340a6f62df359d6a"}, + RefB: spdx.DocElementID{ElementRefID: "Application-800d9e6e0f88ab3a"}, + Relationship: "CONTAINS", + }, + }, + OtherLicenses: []*spdx.OtherLicense{ + { + LicenseIdentifier: "LicenseRef-14b1606fb243e2b6", + LicenseName: "NOASSERTION", + ExtractedText: "BSD-4-clause", + LicenseComment: "The license text represents text found in package metadata and may not represent the full text of the license", + }, + { + LicenseIdentifier: "LicenseRef-229659393343e160", + LicenseName: "NOASSERTION", + ExtractedText: "UNKNOWN", + LicenseComment: "The license text represents text found in package metadata and may not represent the full text of the license", + }, + { + LicenseIdentifier: "LicenseRef-77bdf77d8292ce5b", + LicenseName: "AFL-3.0 WITH wrong-exceptions", + ExtractedText: `This component is licensed under "AFL-3.0 WITH wrong-exceptions"`, + }, + { + LicenseIdentifier: "LicenseRef-a8d01765900624d3", + LicenseName: "UNKNOWN", + ExtractedText: `This component is licensed under "UNKNOWN"`, + }, + }, + }, + }, { name: "happy path with vulnerability", inputReport: types.Report{ @@ -1324,6 +1466,8 @@ func TestMarshaler_Marshal(t *testing.T) { for _, f := range vv.Files { str += f.Path } + case spdx.OtherLicense: + str = vv.ExtractedText + vv.LicenseName case string: str = vv default: @@ -1349,56 +1493,3 @@ func TestMarshaler_Marshal(t *testing.T) { }) } } - -func Test_GetLicense(t *testing.T) { - tests := []struct { - name string - input []string - want string - }{ - { - name: "happy path", - input: []string{ - "GPLv2+", - }, - want: "GPL-2.0-or-later", - }, - { - name: "happy path with multi license", - input: []string{ - "GPLv2+", - "GPLv3+", - }, - want: "GPL-2.0-or-later AND GPL-3.0-or-later", - }, - { - name: "happy path with OR operator", - input: []string{ - "GPLv2+", - "LGPL 2.0 or GNU LESSER", - }, - want: "GPL-2.0-or-later AND (LGPL-2.0-only OR LGPL-2.1-only)", - }, - { - name: "happy path with AND operator", - input: []string{ - "GPLv2+", - "LGPL 2.0 and GNU LESSER", - }, - want: "GPL-2.0-or-later AND LGPL-2.0-only AND LGPL-2.1-only", - }, - { - name: "happy path with WITH operator", - input: []string{ - "AFL 2.0", - "AFL 3.0 with distribution exception", - }, - want: "AFL-2.0 AND AFL-3.0 WITH distribution-exception", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, tspdx.NormalizeLicense(tt.input)) - }) - } -} diff --git a/pkg/scanner/langpkg/scan.go b/pkg/scanner/langpkg/scan.go index df6068b3ddd3..565c3b2c07c1 100644 --- a/pkg/scanner/langpkg/scan.go +++ b/pkg/scanner/langpkg/scan.go @@ -9,6 +9,7 @@ import ( "github.com/aquasecurity/trivy/pkg/detector/library" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/types" ) @@ -41,7 +42,7 @@ func (s *scanner) Scan(ctx context.Context, target types.ScanTarget, opts types. } var results types.Results - printedTypes := make(map[ftypes.LangType]struct{}) + printedTypes := set.New[ftypes.LangType]() for _, app := range apps { if len(app.Packages) == 0 { continue @@ -76,13 +77,13 @@ func (s *scanner) Scan(ctx context.Context, target types.ScanTarget, opts types. return results, nil } -func (s *scanner) scanVulnerabilities(ctx context.Context, app ftypes.Application, printedTypes map[ftypes.LangType]struct{}) ( +func (s *scanner) scanVulnerabilities(ctx context.Context, app ftypes.Application, printedTypes set.Set[ftypes.LangType]) ( []types.DetectedVulnerability, error) { // Prevent the same log messages from being displayed many times for the same type. - if _, ok := printedTypes[app.Type]; !ok { + if !printedTypes.Contains(app.Type) { log.InfoContext(ctx, "Detecting vulnerabilities...") - printedTypes[app.Type] = struct{}{} + printedTypes.Append(app.Type) } log.DebugContext(ctx, "Scanning packages for vulnerabilities", log.FilePath(app.FilePath)) diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index 58cd4cc00167..1d117999ede1 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -24,6 +24,7 @@ import ( "github.com/aquasecurity/trivy/pkg/scanner/langpkg" "github.com/aquasecurity/trivy/pkg/scanner/ospkg" "github.com/aquasecurity/trivy/pkg/scanner/post" + "github.com/aquasecurity/trivy/pkg/set" "github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/vulnerability" @@ -90,10 +91,16 @@ func (s Scanner) Scan(ctx context.Context, targetName, artifactKey string, blobK return nil, ftypes.OS{}, xerrors.Errorf("failed to apply layers: %w", err) } + if !lo.IsEmpty(options.Distro) && !lo.IsEmpty(detail.OS) { + log.Info("Overriding detected OS with provided distro", log.String("detected", detail.OS.String()), + log.String("provided", options.Distro.String())) + detail.OS = options.Distro + } + target := types.ScanTarget{ Name: targetName, OS: detail.OS, - Repository: detail.Repository, + Repository: lo.Ternary(lo.IsEmpty(options.Distro), detail.Repository, nil), Packages: mergePkgs(detail.Packages, detail.ImageConfig.Packages, options), Applications: detail.Applications, Misconfigurations: mergeMisconfigurations(targetName, detail), @@ -452,12 +459,12 @@ func mergePkgs(pkgs, pkgsFromCommands []ftypes.Package, options types.ScanOption } // pkg has priority over pkgsFromCommands - uniqPkgs := make(map[string]struct{}) + uniqPkgs := set.New[string]() for _, pkg := range pkgs { - uniqPkgs[pkg.Name] = struct{}{} + uniqPkgs.Append(pkg.Name) } for _, pkg := range pkgsFromCommands { - if _, ok := uniqPkgs[pkg.Name]; ok { + if uniqPkgs.Contains(pkg.Name) { continue } pkgs = append(pkgs, pkg) diff --git a/pkg/scanner/local/scan_test.go b/pkg/scanner/local/scan_test.go index bdeb5166a2fa..0e904806fbd4 100644 --- a/pkg/scanner/local/scan_test.go +++ b/pkg/scanner/local/scan_test.go @@ -221,6 +221,75 @@ func TestScanner_Scan(t *testing.T) { Eosl: true, }, }, + { + name: "happy path with OS rewriting", + args: args{ + target: "alpine:latest", + layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + options: types.ScanOptions{ + PkgTypes: []string{ + types.PkgTypeOS, + types.PkgTypeLibrary, + }, + PkgRelationships: ftypes.Relationships, + Scanners: types.Scanners{types.VulnerabilityScanner}, + Distro: ftypes.OS{ + Family: "alpine", + Name: "3.11", + }, + }, + }, + fixtures: []string{"testdata/fixtures/happy.yaml"}, + applyLayersExpectation: ApplierApplyLayersExpectation{ + Args: ApplierApplyLayersArgs{ + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + }, + Returns: ApplierApplyLayersReturns{ + Detail: ftypes.ArtifactDetail{ + OS: ftypes.OS{ + Family: ftypes.Alpine, + Name: "3.10", + }, + Packages: []ftypes.Package{ + muslPkg, + }, + }, + }, + }, + wantResults: types.Results{ + { + Target: "alpine:latest (alpine 3.11)", + Class: types.ClassOSPkg, + Type: ftypes.Alpine, + Packages: ftypes.Packages{ + muslPkg, + }, + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2020-9999", + PkgName: muslPkg.Name, + InstalledVersion: muslPkg.Version, + FixedVersion: "1.2.4", + Status: dbTypes.StatusFixed, + Layer: ftypes.Layer{ + DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888", + }, + PrimaryURL: "https://avd.aquasec.com/nvd/cve-2020-9999", + Vulnerability: dbTypes.Vulnerability{ + Title: "dos", + Description: "dos vulnerability", + Severity: "HIGH", + }, + }, + }, + }, + }, + wantOS: ftypes.OS{ + Family: "alpine", + Name: "3.11", + Eosl: true, + }, + }, { name: "happy path license scanner", args: args{ diff --git a/pkg/scanner/scan.go b/pkg/scanner/scan.go index f1e4cf68c515..4009ddba8a4d 100644 --- a/pkg/scanner/scan.go +++ b/pkg/scanner/scan.go @@ -178,11 +178,6 @@ func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (t ptros = nil } - // Layer makes sense only when scanning container images - if artifactInfo.Type != artifact.TypeContainerImage { - removeLayer(results) - } - return types.Report{ SchemaVersion: report.SchemaVersion, CreatedAt: clock.Now(ctx), @@ -202,19 +197,3 @@ func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (t BOM: artifactInfo.BOM, }, nil } - -func removeLayer(results types.Results) { - for i := range results { - result := results[i] - - for j := range result.Packages { - result.Packages[j].Layer = ftypes.Layer{} - } - for j := range result.Vulnerabilities { - result.Vulnerabilities[j].Layer = ftypes.Layer{} - } - for j := range result.Misconfigurations { - result.Misconfigurations[j].Layer = ftypes.Layer{} - } - } -} diff --git a/pkg/set/set.go b/pkg/set/set.go new file mode 100644 index 000000000000..7dadcd3b414f --- /dev/null +++ b/pkg/set/set.go @@ -0,0 +1,39 @@ +package set + +import "iter" + +// Set defines the interface for set operations +type Set[T comparable] interface { + // Append adds multiple items to the set and returns the new size + Append(val ...T) int + + // Remove removes an item from the set + Remove(item T) + + // Contains checks if an item exists in the set + Contains(item T) bool + + // Size returns the number of items in the set + Size() int + + // Clear removes all items from the set + Clear() + + // Clone returns a new set with a copy of all items + Clone() Set[T] + + // Items returns all items in the set as a slice + Items() []T + + // Iter returns an iterator over the set + Iter() iter.Seq[T] + + // Union returns a new set containing all items from both sets + Union(other Set[T]) Set[T] + + // Intersection returns a new set containing items present in both sets + Intersection(other Set[T]) Set[T] + + // Difference returns a new set containing items present in this set but not in the other + Difference(other Set[T]) Set[T] +} diff --git a/pkg/set/unsafe.go b/pkg/set/unsafe.go new file mode 100644 index 000000000000..261492045715 --- /dev/null +++ b/pkg/set/unsafe.go @@ -0,0 +1,100 @@ +package set + +import ( + "iter" + "maps" + "slices" +) + +// unsafeSet represents a non-thread-safe set implementation +// WARNING: This implementation is not thread-safe +type unsafeSet[T comparable] map[T]struct{} //nolint: gocritic + +// New creates a new empty non-thread-safe set with optional initial values +func New[T comparable](values ...T) Set[T] { + s := make(unsafeSet[T]) + for _, v := range values { + s[v] = struct{}{} + } + return s +} + +// Append adds multiple items to the set and returns the new size +func (s unsafeSet[T]) Append(val ...T) int { + for _, item := range val { + s[item] = struct{}{} + } + return len(s) +} + +// Remove removes an item from the set +func (s unsafeSet[T]) Remove(item T) { + delete(s, item) +} + +// Contains checks if an item exists in the set +func (s unsafeSet[T]) Contains(item T) bool { + _, exists := s[item] + return exists +} + +// Size returns the number of items in the set +func (s unsafeSet[T]) Size() int { + return len(s) +} + +// Clear removes all items from the set +func (s unsafeSet[T]) Clear() { + for k := range s { + delete(s, k) + } +} + +// Clone returns a new set with a copy of all items +func (s unsafeSet[T]) Clone() Set[T] { + return maps.Clone(s) +} + +// Items returns all items in the set as a slice +func (s unsafeSet[T]) Items() []T { + return slices.Collect(s.Iter()) +} + +// Iter returns an iterator over the set +func (s unsafeSet[T]) Iter() iter.Seq[T] { + return maps.Keys(s) +} + +// Union returns a new set containing all items from both sets +func (s unsafeSet[T]) Union(other Set[T]) Set[T] { + result := make(unsafeSet[T]) + for k := range s { + result[k] = struct{}{} + } + for _, item := range other.Items() { + result[item] = struct{}{} + } + return result +} + +// Intersection returns a new set containing items present in both sets +func (s unsafeSet[T]) Intersection(other Set[T]) Set[T] { + result := make(unsafeSet[T]) + for k := range s { + if other.Contains(k) { + result[k] = struct{}{} + } + } + return result +} + +// Difference returns a new set containing items present in this set but not in the other +func (s unsafeSet[T]) Difference(other Set[T]) Set[T] { + result := make(unsafeSet[T]) + for k := range s { + if !other.Contains(k) { + result[k] = struct{}{} + } + } + return result +} diff --git a/pkg/set/unsafe_test.go b/pkg/set/unsafe_test.go new file mode 100644 index 000000000000..8f42c01666ea --- /dev/null +++ b/pkg/set/unsafe_test.go @@ -0,0 +1,583 @@ +package set_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/aquasecurity/trivy/pkg/set" +) + +func Test_New(t *testing.T) { + tests := []struct { + name string + values []int + wantSize int + wantAll bool + desc string + }{ + { + name: "new empty set", + values: []int{}, + wantSize: 0, + wantAll: true, + desc: "should create empty set when no values provided", + }, + { + name: "new set with single value", + values: []int{1}, + wantSize: 1, + wantAll: true, + desc: "should create set with single value", + }, + { + name: "new set with multiple values", + values: []int{ + 1, + 2, + 3, + }, + wantSize: 3, + wantAll: true, + desc: "should create set with multiple values", + }, + { + name: "new set with duplicate values", + values: []int{ + 1, + 2, + 2, + 3, + 3, + 3, + }, + wantSize: 3, + wantAll: true, + desc: "should create set with unique values only", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New(tt.values...) + assert.Equal(t, tt.wantSize, s.Size(), "unexpected set size") + }) + } +} + +func Test_unsafeSet_Add(t *testing.T) { + // Define custom type for struct test cases + type custom struct { + id int + name string + } + + tests := []struct { + name string + prepare func(s set.Set[any]) + input any + wantSize int + }{ + { + name: "add integer", + prepare: nil, + input: 1, + wantSize: 1, + }, + { + name: "add duplicate integer", + prepare: func(s set.Set[any]) { + s.Append(1) + }, + input: 1, + wantSize: 1, + }, + { + name: "add string", + prepare: nil, + input: "test", + wantSize: 1, + }, + { + name: "add empty string", + prepare: nil, + input: "", + wantSize: 1, + }, + { + name: "add custom struct", + prepare: nil, + input: custom{ + id: 1, + name: "test1", + }, + wantSize: 1, + }, + { + name: "add nil pointer", + prepare: nil, + input: (*int)(nil), + wantSize: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New[any]() + if tt.prepare != nil { + tt.prepare(s) + } + s.Append(tt.input) + + got := s.Size() + assert.Equal(t, tt.wantSize, got, "unexpected set size") + assert.True(t, s.Contains(tt.input), "unexpected contains result for value: %v", tt.input) + }) + } +} + +func Test_unsafeSet_Append(t *testing.T) { + tests := []struct { + name string + prepare func(s set.Set[int]) + input []int + wantSize int + }{ + { + name: "append to empty set", + prepare: nil, + input: []int{ + 1, + 2, + 3, + }, + wantSize: 3, + }, + { + name: "append with duplicates", + prepare: func(s set.Set[int]) { + s.Append(1) + }, + input: []int{ + 1, + 2, + 1, + 3, + 2, + }, + wantSize: 3, + }, + { + name: "append empty slice", + prepare: func(s set.Set[int]) { + s.Append(1) + }, + input: []int{}, + wantSize: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New[int]() + if tt.prepare != nil { + tt.prepare(s) + } + got := s.Append(tt.input...) + + assert.Equal(t, tt.wantSize, got, "unexpected returned size") + assert.Equal(t, tt.wantSize, s.Size(), "unexpected actual size") + + for _, item := range tt.input { + assert.True(t, s.Contains(item), "set should contain appended item: %v", item) + } + }) + } +} + +func Test_unsafeSet_Remove(t *testing.T) { + tests := []struct { + name string + prepare func(s set.Set[int]) + input int + wantSize int + }{ + { + name: "remove existing element", + prepare: func(s set.Set[int]) { + s.Append(1) + }, + input: 1, + wantSize: 0, + }, + { + name: "remove non-existing element", + prepare: func(s set.Set[int]) { + s.Append(1) + }, + input: 2, + wantSize: 1, + }, + { + name: "remove from empty set", + prepare: nil, + input: 1, + wantSize: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New[int]() + if tt.prepare != nil { + tt.prepare(s) + } + s.Remove(tt.input) + + got := s.Size() + assert.Equal(t, tt.wantSize, got, "unexpected set size") + assert.False(t, s.Contains(tt.input), "unexpected contains result for value: %v", tt.input) + }) + } +} + +func Test_unsafeSet_Clear(t *testing.T) { + tests := []struct { + name string + prepare func(s set.Set[int]) + }{ + { + name: "clear non-empty set", + prepare: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + s.Append(3) + }, + }, + { + name: "clear empty set", + prepare: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New[int]() + if tt.prepare != nil { + tt.prepare(s) + } + s.Clear() + + got := s.Size() + assert.Zero(t, got, "unexpected set size") + assert.Empty(t, s.Items(), "items should be empty") + }) + } +} + +func Test_unsafeSet_Clone(t *testing.T) { + t.Run("empty set", func(t *testing.T) { + original := set.New[string]() + cloned := original.Clone() + + assert.Equal(t, 0, cloned.Size(), "cloned set should be empty") + + // Verify independence + original.Append("test") + assert.False(t, cloned.Contains("test"), "cloned set should not be affected by original") + }) + + t.Run("basic types", func(t *testing.T) { + original := set.New[any](1, "test", true) + cloned := original.Clone() + + assert.Equal(t, original.Size(), cloned.Size(), "sizes should match") + assert.True(t, cloned.Contains(1), "should contain integer") + assert.True(t, cloned.Contains("test"), "should contain string") + assert.True(t, cloned.Contains(true), "should contain boolean") + + // Verify independence + original.Append("new") + assert.False(t, cloned.Contains("new"), "cloned set should not be affected by original") + cloned.Append("another") + assert.False(t, original.Contains("another"), "original set should not be affected by clone") + }) + + // Test nil pointer + t.Run("nil pointer", func(t *testing.T) { + original := set.New[*int]() + original.Append(nil) + + cloned := original.Clone() + + assert.Equal(t, original.Size(), cloned.Size(), "sizes should match") + assert.True(t, cloned.Contains((*int)(nil)), "should contain nil pointer") + }) +} + +func Test_unsafeSet_Items(t *testing.T) { + tests := []struct { + name string + prepare func(s set.Set[int]) + want []int + }{ + { + name: "get items from non-empty set", + prepare: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + s.Append(3) + }, + want: []int{ + 1, + 2, + 3, + }, + }, + { + name: "get items from empty set", + prepare: nil, + want: []int{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := set.New[int]() + if tt.prepare != nil { + tt.prepare(s) + } + got := s.Items() + + assert.ElementsMatch(t, tt.want, got, "unexpected items in set") + }) + } +} + +func Test_unsafeSet_Union(t *testing.T) { + tests := []struct { + name string + prepare1 func(s set.Set[int]) + prepare2 func(s set.Set[int]) + want []int + }{ + { + name: "union of non-overlapping sets", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: func(s set.Set[int]) { + s.Append(3) + s.Append(4) + }, + want: []int{ + 1, + 2, + 3, + 4, + }, + }, + { + name: "union of overlapping sets", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + s.Append(3) + }, + prepare2: func(s set.Set[int]) { + s.Append(2) + s.Append(3) + s.Append(4) + }, + want: []int{ + 1, + 2, + 3, + 4, + }, + }, + { + name: "union with empty set", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: nil, + want: []int{ + 1, + 2, + }, + }, + { + name: "union of empty sets", + prepare1: nil, + prepare2: nil, + want: []int{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s1 := set.New[int]() + s2 := set.New[int]() + + if tt.prepare1 != nil { + tt.prepare1(s1) + } + if tt.prepare2 != nil { + tt.prepare2(s2) + } + + result := s1.Union(s2) + got := result.Items() + + assert.ElementsMatch(t, tt.want, got, "unexpected union result") + }) + } +} + +func Test_unsafeSet_Intersection(t *testing.T) { + tests := []struct { + name string + prepare1 func(s set.Set[int]) + prepare2 func(s set.Set[int]) + want []int + }{ + { + name: "intersection of overlapping sets", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + s.Append(3) + }, + prepare2: func(s set.Set[int]) { + s.Append(2) + s.Append(3) + s.Append(4) + }, + want: []int{ + 2, + 3, + }, + }, + { + name: "intersection of non-overlapping sets", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: func(s set.Set[int]) { + s.Append(3) + s.Append(4) + }, + want: []int{}, + }, + { + name: "intersection with empty set", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: nil, + want: []int{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s1 := set.New[int]() + s2 := set.New[int]() + + if tt.prepare1 != nil { + tt.prepare1(s1) + } + if tt.prepare2 != nil { + tt.prepare2(s2) + } + + result := s1.Intersection(s2) + got := result.Items() + + assert.ElementsMatch(t, tt.want, got, "unexpected intersection result") + }) + } +} + +func Test_unsafeSet_Difference(t *testing.T) { + tests := []struct { + name string + prepare1 func(s set.Set[int]) + prepare2 func(s set.Set[int]) + want []int + }{ + { + name: "difference of overlapping sets", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + s.Append(3) + }, + prepare2: func(s set.Set[int]) { + s.Append(2) + s.Append(3) + s.Append(4) + }, + want: []int{1}, + }, + { + name: "difference with non-overlapping set", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: func(s set.Set[int]) { + s.Append(3) + s.Append(4) + }, + want: []int{ + 1, + 2, + }, + }, + { + name: "difference with empty set", + prepare1: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + prepare2: nil, + want: []int{ + 1, + 2, + }, + }, + { + name: "difference of empty set", + prepare1: nil, + prepare2: func(s set.Set[int]) { + s.Append(1) + s.Append(2) + }, + want: []int{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s1 := set.New[int]() + s2 := set.New[int]() + if tt.prepare1 != nil { + tt.prepare1(s1) + } + if tt.prepare2 != nil { + tt.prepare2(s2) + } + + result := s1.Difference(s2) + got := result.Items() + + assert.ElementsMatch(t, tt.want, got, "unexpected difference result") + }) + } +} diff --git a/pkg/types/error.go b/pkg/types/error.go index 5a1614e07dd0..6ea8ced4e34a 100644 --- a/pkg/types/error.go +++ b/pkg/types/error.go @@ -11,3 +11,12 @@ type ExitError struct { func (e *ExitError) Error() string { return fmt.Sprintf("exit status %d", e.Code) } + +// UserError represents an error with a user-friendly message. +type UserError struct { + Message string +} + +func (e *UserError) Error() string { + return e.Message +} diff --git a/pkg/types/scan.go b/pkg/types/scan.go index 0fef0028bef3..4dedbce6fcf1 100644 --- a/pkg/types/scan.go +++ b/pkg/types/scan.go @@ -121,4 +121,5 @@ type ScanOptions struct { LicenseCategories map[types.LicenseCategory][]string FilePatterns []string IncludeDevDeps bool + Distro types.OS // Forced OS } diff --git a/pkg/x/slices/slices.go b/pkg/x/slices/slices.go index 8e256814bbc7..81ba7a02f524 100644 --- a/pkg/x/slices/slices.go +++ b/pkg/x/slices/slices.go @@ -1,5 +1,6 @@ package slices +// ZeroToNil returns nil, if slice is empty func ZeroToNil[T any](t []T) []T { if len(t) == 0 { return nil diff --git a/rpc/common/service.proto b/rpc/common/service.proto index f9ab77df4e47..7be5c0d04bb4 100644 --- a/rpc/common/service.proto +++ b/rpc/common/service.proto @@ -173,10 +173,10 @@ enum Severity { } message CVSS { - string v2_vector = 1; - string v3_vector = 2; - double v2_score = 3; - double v3_score = 4; + string v2_vector = 1; + string v3_vector = 2; + double v2_score = 3; + double v3_score = 4; string v40_vector = 5; double v40_score = 6; } diff --git a/rpc/scanner/service.pb.go b/rpc/scanner/service.pb.go index 1e061d5764e1..00ff3485240c 100644 --- a/rpc/scanner/service.pb.go +++ b/rpc/scanner/service.pb.go @@ -151,6 +151,7 @@ type ScanOptions struct { LicenseCategories map[string]*Licenses `protobuf:"bytes,4,rep,name=license_categories,json=licenseCategories,proto3" json:"license_categories,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` IncludeDevDeps bool `protobuf:"varint,5,opt,name=include_dev_deps,json=includeDevDeps,proto3" json:"include_dev_deps,omitempty"` PkgRelationships []string `protobuf:"bytes,6,rep,name=pkg_relationships,json=pkgRelationships,proto3" json:"pkg_relationships,omitempty"` + Distro *common.OS `protobuf:"bytes,7,opt,name=distro,proto3" json:"distro,omitempty"` } func (x *ScanOptions) Reset() { @@ -220,6 +221,13 @@ func (x *ScanOptions) GetPkgRelationships() []string { return nil } +func (x *ScanOptions) GetDistro() *common.OS { + if x != nil { + return x.Distro + } + return nil +} + type ScanResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -406,7 +414,7 @@ var file_rpc_scanner_service_proto_rawDesc = []byte{ 0x53, 0x63, 0x61, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x20, 0x0a, 0x08, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xea, 0x02, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f, + 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x94, 0x03, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6b, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6b, 0x67, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x18, @@ -422,58 +430,61 @@ var file_rpc_scanner_service_proto_rawDesc = []byte{ 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x65, 0x76, 0x44, 0x65, 0x70, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x6b, 0x67, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6b, 0x67, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x1a, 0x60, 0x0a, 0x16, 0x4c, - 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, - 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, - 0x03, 0x10, 0x04, 0x22, 0x64, 0x0a, 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f, - 0x53, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, - 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0xd5, 0x03, 0x0a, 0x06, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x45, 0x0a, 0x0f, - 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, - 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x61, - 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0f, - 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, - 0x35, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x64, + 0x69, 0x73, 0x74, 0x72, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x72, + 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f, 0x53, 0x52, 0x06, 0x64, + 0x69, 0x73, 0x74, 0x72, 0x6f, 0x1a, 0x60, 0x0a, 0x16, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, + 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x64, 0x0a, + 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, + 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x72, 0x69, 0x76, + 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f, 0x53, 0x52, 0x02, 0x6f, 0x73, 0x12, + 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x22, 0xd5, 0x03, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x45, 0x0a, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, + 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0f, 0x76, 0x75, + 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x54, 0x0a, + 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x04, - 0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, - 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, - 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, + 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, + 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, + 0x12, 0x39, 0x0a, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, + 0x65, 0x52, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, + 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x04, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, + 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, + 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, + 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, + 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -507,22 +518,23 @@ var file_rpc_scanner_service_proto_goTypes = []interface{}{ var file_rpc_scanner_service_proto_depIdxs = []int32{ 2, // 0: trivy.scanner.v1.ScanRequest.options:type_name -> trivy.scanner.v1.ScanOptions 5, // 1: trivy.scanner.v1.ScanOptions.license_categories:type_name -> trivy.scanner.v1.ScanOptions.LicenseCategoriesEntry - 6, // 2: trivy.scanner.v1.ScanResponse.os:type_name -> trivy.common.OS - 4, // 3: trivy.scanner.v1.ScanResponse.results:type_name -> trivy.scanner.v1.Result - 7, // 4: trivy.scanner.v1.Result.vulnerabilities:type_name -> trivy.common.Vulnerability - 8, // 5: trivy.scanner.v1.Result.misconfigurations:type_name -> trivy.common.DetectedMisconfiguration - 9, // 6: trivy.scanner.v1.Result.packages:type_name -> trivy.common.Package - 10, // 7: trivy.scanner.v1.Result.custom_resources:type_name -> trivy.common.CustomResource - 11, // 8: trivy.scanner.v1.Result.secrets:type_name -> trivy.common.SecretFinding - 12, // 9: trivy.scanner.v1.Result.licenses:type_name -> trivy.common.DetectedLicense - 1, // 10: trivy.scanner.v1.ScanOptions.LicenseCategoriesEntry.value:type_name -> trivy.scanner.v1.Licenses - 0, // 11: trivy.scanner.v1.Scanner.Scan:input_type -> trivy.scanner.v1.ScanRequest - 3, // 12: trivy.scanner.v1.Scanner.Scan:output_type -> trivy.scanner.v1.ScanResponse - 12, // [12:13] is the sub-list for method output_type - 11, // [11:12] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 6, // 2: trivy.scanner.v1.ScanOptions.distro:type_name -> trivy.common.OS + 6, // 3: trivy.scanner.v1.ScanResponse.os:type_name -> trivy.common.OS + 4, // 4: trivy.scanner.v1.ScanResponse.results:type_name -> trivy.scanner.v1.Result + 7, // 5: trivy.scanner.v1.Result.vulnerabilities:type_name -> trivy.common.Vulnerability + 8, // 6: trivy.scanner.v1.Result.misconfigurations:type_name -> trivy.common.DetectedMisconfiguration + 9, // 7: trivy.scanner.v1.Result.packages:type_name -> trivy.common.Package + 10, // 8: trivy.scanner.v1.Result.custom_resources:type_name -> trivy.common.CustomResource + 11, // 9: trivy.scanner.v1.Result.secrets:type_name -> trivy.common.SecretFinding + 12, // 10: trivy.scanner.v1.Result.licenses:type_name -> trivy.common.DetectedLicense + 1, // 11: trivy.scanner.v1.ScanOptions.LicenseCategoriesEntry.value:type_name -> trivy.scanner.v1.Licenses + 0, // 12: trivy.scanner.v1.Scanner.Scan:input_type -> trivy.scanner.v1.ScanRequest + 3, // 13: trivy.scanner.v1.Scanner.Scan:output_type -> trivy.scanner.v1.ScanResponse + 13, // [13:14] is the sub-list for method output_type + 12, // [12:13] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_rpc_scanner_service_proto_init() } diff --git a/rpc/scanner/service.proto b/rpc/scanner/service.proto index c7ad3748280b..d809d36610ee 100644 --- a/rpc/scanner/service.proto +++ b/rpc/scanner/service.proto @@ -28,6 +28,7 @@ message ScanOptions { map license_categories = 4; bool include_dev_deps = 5; repeated string pkg_relationships = 6; + common.OS distro = 7; reserved 3; // deleted 'list_all_packages' } diff --git a/rpc/scanner/service.twirp.go b/rpc/scanner/service.twirp.go index 83a834536f35..d7525d23c45e 100644 --- a/rpc/scanner/service.twirp.go +++ b/rpc/scanner/service.twirp.go @@ -1094,47 +1094,48 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) } var twirpFileDescriptor0 = []byte{ - // 671 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xdd, 0x6e, 0xd3, 0x4c, - 0x10, 0x55, 0x7e, 0x9a, 0x38, 0x93, 0x4f, 0x5f, 0xd3, 0x15, 0x54, 0x6e, 0x4a, 0x21, 0xca, 0x05, - 0x8a, 0x84, 0x94, 0xd0, 0x14, 0xc4, 0xdf, 0x1d, 0x6d, 0x41, 0x45, 0xa0, 0x56, 0x9b, 0x8a, 0x0b, - 0x6e, 0xc2, 0x66, 0x3d, 0x75, 0x57, 0x71, 0x6c, 0x77, 0x67, 0x1d, 0x29, 0xaf, 0xc2, 0x7b, 0xf1, - 0x12, 0x3c, 0x05, 0xda, 0xb5, 0x13, 0x35, 0x69, 0xcb, 0x95, 0x77, 0x66, 0xce, 0xcc, 0x39, 0xde, - 0x39, 0x5a, 0xd8, 0xd3, 0xa9, 0x1c, 0x90, 0x14, 0x71, 0x8c, 0x7a, 0x40, 0xa8, 0xe7, 0x4a, 0x62, - 0x3f, 0xd5, 0x89, 0x49, 0x58, 0xcb, 0x68, 0x35, 0x5f, 0xf4, 0x8b, 0x62, 0x7f, 0x7e, 0xd8, 0xf6, - 0x2d, 0x58, 0x26, 0xb3, 0x59, 0x12, 0xaf, 0x63, 0xbb, 0xbf, 0x4a, 0xd0, 0x1c, 0x49, 0x11, 0x73, - 0xbc, 0xc9, 0x90, 0x0c, 0xdb, 0x85, 0x9a, 0x11, 0x3a, 0x44, 0xe3, 0x97, 0x3a, 0xa5, 0x5e, 0x83, - 0x17, 0x11, 0x7b, 0x06, 0x4d, 0xa1, 0x8d, 0xba, 0x12, 0xd2, 0x8c, 0x55, 0xe0, 0x97, 0x5d, 0x11, - 0x96, 0xa9, 0xb3, 0x80, 0xed, 0x81, 0x37, 0x89, 0x92, 0xc9, 0x58, 0x05, 0xe4, 0x57, 0x3a, 0x95, - 0x5e, 0x83, 0xd7, 0x6d, 0x7c, 0x16, 0x10, 0x7b, 0x03, 0xf5, 0x24, 0x35, 0x2a, 0x89, 0xc9, 0xaf, - 0x76, 0x4a, 0xbd, 0xe6, 0xf0, 0xa0, 0xbf, 0xa9, 0xb0, 0x6f, 0x35, 0x9c, 0xe7, 0x20, 0xbe, 0x44, - 0x77, 0x3b, 0xe0, 0x7d, 0x55, 0x12, 0x63, 0x42, 0x62, 0x8f, 0x60, 0x2b, 0x16, 0x33, 0x24, 0xbf, - 0xe4, 0x86, 0xe7, 0x41, 0xf7, 0x4f, 0x39, 0x97, 0x5f, 0xb4, 0xb2, 0x7d, 0x68, 0xa4, 0xd3, 0x70, - 0x6c, 0x16, 0xe9, 0x0a, 0xe9, 0xa5, 0xd3, 0xf0, 0xd2, 0xc6, 0xac, 0x0d, 0x5e, 0xc1, 0x48, 0x7e, - 0x39, 0xaf, 0x2d, 0x63, 0x26, 0x81, 0x45, 0x39, 0xd5, 0x58, 0x0a, 0x83, 0x61, 0xa2, 0x15, 0x5a, - 0xb9, 0x95, 0x5e, 0x73, 0xf8, 0xea, 0x9f, 0x72, 0xfb, 0x85, 0xc4, 0xe3, 0x55, 0xdb, 0x69, 0x6c, - 0xf4, 0x82, 0xef, 0x44, 0x9b, 0x79, 0xd6, 0x83, 0x96, 0x8a, 0x65, 0x94, 0x05, 0x38, 0x0e, 0x70, - 0x3e, 0x0e, 0x30, 0x25, 0x7f, 0xab, 0x53, 0xea, 0x79, 0xfc, 0xff, 0x22, 0x7f, 0x82, 0xf3, 0x13, - 0x4c, 0x89, 0xbd, 0x80, 0x1d, 0xfb, 0x1f, 0x1a, 0x23, 0xe1, 0x48, 0xae, 0x55, 0x4a, 0x7e, 0xcd, - 0x69, 0x6e, 0xa5, 0xd3, 0x90, 0xdf, 0xce, 0xb7, 0x7f, 0xc2, 0xee, 0xfd, 0x1a, 0x58, 0x0b, 0x2a, - 0x53, 0x5c, 0x14, 0xab, 0xb4, 0x47, 0xf6, 0x12, 0xb6, 0xe6, 0x22, 0xca, 0xd0, 0x6d, 0xb0, 0x39, - 0x6c, 0xdf, 0xfd, 0xb5, 0xe5, 0x8d, 0xf3, 0x1c, 0xf8, 0xbe, 0xfc, 0xb6, 0xf4, 0xa5, 0xea, 0x55, - 0x5a, 0xd5, 0x6e, 0x00, 0xff, 0xe5, 0x56, 0xa1, 0x34, 0x89, 0x09, 0x59, 0x07, 0xca, 0x09, 0xb9, - 0xe1, 0xcd, 0x61, 0xab, 0x18, 0x94, 0x9b, 0xac, 0x7f, 0x3e, 0xe2, 0xe5, 0x84, 0xd8, 0x10, 0xea, - 0x1a, 0x29, 0x8b, 0x4c, 0xee, 0x89, 0xe6, 0xd0, 0xbf, 0xcb, 0xc7, 0x1d, 0x80, 0x2f, 0x81, 0xdd, - 0xdf, 0x15, 0xa8, 0xe5, 0xb9, 0x07, 0xcd, 0x78, 0x0a, 0xdb, 0xf3, 0x2c, 0x8a, 0x51, 0x8b, 0x89, - 0x8a, 0x94, 0xb1, 0x9b, 0x2a, 0xbb, 0xf1, 0xfb, 0xeb, 0x2a, 0xbe, 0xdf, 0x02, 0x2d, 0xf8, 0x66, - 0x0f, 0xbb, 0x84, 0x9d, 0x99, 0x22, 0x99, 0xc4, 0x57, 0x2a, 0xcc, 0xb4, 0x58, 0x3a, 0xd4, 0x0e, - 0x7a, 0xbe, 0x3e, 0xe8, 0x04, 0x0d, 0x4a, 0x83, 0xc1, 0xb7, 0x0d, 0x38, 0xbf, 0x3b, 0xc0, 0x1a, - 0x55, 0x46, 0x82, 0xec, 0xba, 0xac, 0xe6, 0x3c, 0x60, 0x0c, 0xaa, 0xd6, 0x94, 0x7e, 0xc5, 0x25, - 0xdd, 0x99, 0x1d, 0x82, 0x97, 0x0a, 0x39, 0x15, 0x21, 0x5a, 0x1b, 0x58, 0xda, 0xc7, 0xeb, 0xb4, - 0x17, 0x79, 0x95, 0xaf, 0x60, 0xec, 0x33, 0xb4, 0x64, 0x46, 0x26, 0x99, 0x8d, 0x35, 0x52, 0x92, - 0x69, 0x89, 0xe4, 0xd7, 0x5d, 0xeb, 0x93, 0xf5, 0xd6, 0x63, 0x87, 0xe2, 0x05, 0x88, 0x6f, 0xcb, - 0xb5, 0x98, 0xd8, 0x6b, 0xa8, 0x13, 0x4a, 0x8d, 0x86, 0x7c, 0xef, 0xbe, 0xab, 0x1b, 0xb9, 0xe2, - 0x27, 0x15, 0x07, 0x2a, 0x0e, 0xf9, 0x12, 0xcb, 0xde, 0x81, 0x57, 0xd8, 0x9a, 0xfc, 0x86, 0xeb, - 0x3b, 0xb8, 0xff, 0xa6, 0x0a, 0x17, 0xf1, 0x15, 0x7c, 0x78, 0x01, 0xf5, 0x51, 0xbe, 0x75, 0x76, - 0x0a, 0x55, 0x7b, 0x64, 0x0f, 0xbc, 0x03, 0xc5, 0x5b, 0xd4, 0x7e, 0xfa, 0x50, 0x39, 0xf7, 0xdf, - 0xc7, 0xa3, 0x1f, 0x87, 0xa1, 0x32, 0xd7, 0xd9, 0xc4, 0x92, 0x0f, 0xc4, 0x4d, 0x26, 0x08, 0x65, - 0xa6, 0x95, 0x59, 0x0c, 0x5c, 0xe3, 0xe0, 0xd6, 0x13, 0xf9, 0xa1, 0xf8, 0x4e, 0x6a, 0xee, 0xdd, - 0x3b, 0xfa, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x66, 0x86, 0x78, 0x40, 0x05, 0x00, 0x00, + // 685 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0x51, 0x6f, 0x1a, 0x47, + 0x10, 0x16, 0x1c, 0x86, 0x63, 0xa8, 0x6a, 0xbc, 0x6a, 0xad, 0x35, 0xae, 0x5b, 0xc4, 0x43, 0x85, + 0x54, 0x09, 0x6a, 0xdc, 0xaa, 0x4d, 0xf2, 0x16, 0xdb, 0x89, 0x1c, 0x25, 0xb2, 0xb5, 0x58, 0x79, + 0xc8, 0x0b, 0x59, 0xf6, 0xc6, 0xe7, 0x15, 0xc7, 0xed, 0x79, 0x77, 0x0f, 0x89, 0xff, 0x91, 0xa7, + 0xfc, 0xaf, 0xfc, 0x9f, 0x68, 0xf7, 0x0e, 0x64, 0x30, 0xce, 0x13, 0x3b, 0x33, 0xdf, 0xcc, 0x7c, + 0xcc, 0x7c, 0x37, 0x70, 0xa4, 0x33, 0x31, 0x34, 0x82, 0xa7, 0x29, 0xea, 0xa1, 0x41, 0xbd, 0x90, + 0x02, 0x07, 0x99, 0x56, 0x56, 0x91, 0xb6, 0xd5, 0x72, 0xb1, 0x1c, 0x94, 0xc1, 0xc1, 0xe2, 0xb4, + 0x43, 0x1d, 0x58, 0xa8, 0xf9, 0x5c, 0xa5, 0x9b, 0xd8, 0xde, 0xd7, 0x0a, 0xb4, 0xc6, 0x82, 0xa7, + 0x0c, 0x1f, 0x72, 0x34, 0x96, 0x1c, 0x42, 0xdd, 0x72, 0x1d, 0xa3, 0xa5, 0x95, 0x6e, 0xa5, 0xdf, + 0x64, 0xa5, 0x45, 0xfe, 0x80, 0x16, 0xd7, 0x56, 0xde, 0x71, 0x61, 0x27, 0x32, 0xa2, 0x55, 0x1f, + 0x84, 0x95, 0xeb, 0x2a, 0x22, 0x47, 0x10, 0x4e, 0x13, 0x35, 0x9d, 0xc8, 0xc8, 0xd0, 0xa0, 0x1b, + 0xf4, 0x9b, 0xac, 0xe1, 0xec, 0xab, 0xc8, 0x90, 0xff, 0xa0, 0xa1, 0x32, 0x2b, 0x55, 0x6a, 0x68, + 0xad, 0x5b, 0xe9, 0xb7, 0x46, 0x27, 0x83, 0x6d, 0x86, 0x03, 0xc7, 0xe1, 0xba, 0x00, 0xb1, 0x15, + 0xba, 0xd7, 0x85, 0xf0, 0xbd, 0x14, 0x98, 0x1a, 0x34, 0xe4, 0x17, 0xd8, 0x4b, 0xf9, 0x1c, 0x0d, + 0xad, 0xf8, 0xe2, 0x85, 0xd1, 0xfb, 0x12, 0x14, 0xf4, 0xcb, 0x54, 0x72, 0x0c, 0xcd, 0x6c, 0x16, + 0x4f, 0xec, 0x32, 0x5b, 0x23, 0xc3, 0x6c, 0x16, 0xdf, 0x3a, 0x9b, 0x74, 0x20, 0x2c, 0x3b, 0x1a, + 0x5a, 0x2d, 0x62, 0x2b, 0x9b, 0x08, 0x20, 0x49, 0xd1, 0x6a, 0x22, 0xb8, 0xc5, 0x58, 0x69, 0x89, + 0x8e, 0x6e, 0xd0, 0x6f, 0x8d, 0xfe, 0xf9, 0x21, 0xdd, 0x41, 0x49, 0xf1, 0x7c, 0x9d, 0x76, 0x99, + 0x5a, 0xbd, 0x64, 0x07, 0xc9, 0xb6, 0x9f, 0xf4, 0xa1, 0x2d, 0x53, 0x91, 0xe4, 0x11, 0x4e, 0x22, + 0x5c, 0x4c, 0x22, 0xcc, 0x0c, 0xdd, 0xeb, 0x56, 0xfa, 0x21, 0xfb, 0xb9, 0xf4, 0x5f, 0xe0, 0xe2, + 0x02, 0x33, 0x43, 0xfe, 0x82, 0x03, 0xf7, 0x3f, 0x34, 0x26, 0xdc, 0x37, 0xb9, 0x97, 0x99, 0xa1, + 0x75, 0xcf, 0xb9, 0x9d, 0xcd, 0x62, 0xf6, 0xd8, 0x4f, 0xfa, 0x50, 0x8f, 0xa4, 0xb1, 0x5a, 0xd1, + 0x86, 0x1f, 0x6f, 0xbb, 0xe4, 0x5b, 0x2c, 0x7c, 0x70, 0x3d, 0x66, 0x65, 0xbc, 0xf3, 0x19, 0x0e, + 0x77, 0xb3, 0x25, 0x6d, 0x08, 0x66, 0xb8, 0x2c, 0x97, 0xee, 0x9e, 0xe4, 0x6f, 0xd8, 0x5b, 0xf0, + 0x24, 0x47, 0xbf, 0xeb, 0xd6, 0xa8, 0xf3, 0x74, 0x08, 0xab, 0xdd, 0xb0, 0x02, 0xf8, 0xb2, 0xfa, + 0x7f, 0xe5, 0x5d, 0x2d, 0x0c, 0xda, 0xb5, 0x5e, 0x04, 0x3f, 0x15, 0xa2, 0x32, 0x99, 0x4a, 0x0d, + 0x92, 0x2e, 0x54, 0x95, 0xf1, 0xc5, 0x77, 0xb1, 0xab, 0x2a, 0x43, 0x46, 0xd0, 0xd0, 0x68, 0xf2, + 0xc4, 0x16, 0xea, 0x69, 0x8d, 0xe8, 0xd3, 0x7e, 0xcc, 0x03, 0xd8, 0x0a, 0xd8, 0xfb, 0x16, 0x40, + 0xbd, 0xf0, 0x3d, 0x2b, 0xdb, 0x4b, 0xd8, 0x5f, 0xe4, 0x49, 0x8a, 0x9a, 0x4f, 0x65, 0x22, 0xad, + 0xdb, 0x69, 0xd5, 0x97, 0x3f, 0xde, 0x64, 0xf1, 0xf1, 0x11, 0x68, 0xc9, 0xb6, 0x73, 0xc8, 0x2d, + 0x1c, 0xcc, 0xa5, 0x11, 0x2a, 0xbd, 0x93, 0x71, 0xae, 0xf9, 0x4a, 0xcb, 0xae, 0xd0, 0x9f, 0x9b, + 0x85, 0x2e, 0xd0, 0xa2, 0xb0, 0x18, 0x7d, 0xd8, 0x82, 0xb3, 0xa7, 0x05, 0x9c, 0xa4, 0x45, 0xc2, + 0x8d, 0x5b, 0xac, 0xe3, 0x5c, 0x18, 0x84, 0x40, 0xcd, 0xc9, 0x97, 0x06, 0xde, 0xe9, 0xdf, 0xe4, + 0x14, 0xc2, 0x8c, 0x8b, 0x19, 0x8f, 0xd1, 0x09, 0xc6, 0xb5, 0xfd, 0x75, 0xb3, 0xed, 0x4d, 0x11, + 0x65, 0x6b, 0x18, 0x79, 0x0b, 0x6d, 0x91, 0x1b, 0xab, 0xe6, 0x13, 0x8d, 0x46, 0xe5, 0x5a, 0xa0, + 0xa1, 0x0d, 0x9f, 0xfa, 0xdb, 0x66, 0xea, 0xb9, 0x47, 0xb1, 0x12, 0xc4, 0xf6, 0xc5, 0x86, 0x6d, + 0xc8, 0xbf, 0xd0, 0x30, 0x28, 0x34, 0x5a, 0x43, 0xc3, 0x5d, 0xa3, 0x1b, 0xfb, 0xe0, 0x1b, 0x99, + 0x46, 0x32, 0x8d, 0xd9, 0x0a, 0x4b, 0x5e, 0x40, 0x58, 0x7e, 0x00, 0x86, 0x36, 0x7d, 0xde, 0xc9, + 0xee, 0x49, 0x95, 0x2a, 0x62, 0x6b, 0xf8, 0xe8, 0x06, 0x1a, 0xe3, 0x62, 0xeb, 0xe4, 0x12, 0x6a, + 0xee, 0x49, 0x9e, 0xb9, 0x18, 0xe5, 0xd5, 0xea, 0xfc, 0xfe, 0x5c, 0xb8, 0xd0, 0xdf, 0xeb, 0xb3, + 0x4f, 0xa7, 0xb1, 0xb4, 0xf7, 0xf9, 0xd4, 0x35, 0x1f, 0xf2, 0x87, 0x9c, 0x1b, 0x14, 0xb9, 0x96, + 0x76, 0x39, 0xf4, 0x89, 0xc3, 0x47, 0xc7, 0xf4, 0x55, 0xf9, 0x3b, 0xad, 0xfb, 0x0b, 0x79, 0xf6, + 0x3d, 0x00, 0x00, 0xff, 0xff, 0x40, 0xd0, 0xe7, 0xda, 0x6a, 0x05, 0x00, 0x00, }