Compare commits

...

54 Commits

Author SHA1 Message Date
Matthias Bertschy
7ae2d3646b override default worker pool size with KUBESCAPE_WORKERS
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-03-07 18:13:29 +01:00
Matthias Bertschy
91b7d8fc2b Merge pull request #1803 from kubescape/dependabot/go_modules/github.com/go-jose/go-jose/v3-3.0.4
Bump github.com/go-jose/go-jose/v3 from 3.0.3 to 3.0.4
2025-03-04 10:38:44 +01:00
dependabot[bot]
2b28911db0 Bump github.com/go-jose/go-jose/v3 from 3.0.3 to 3.0.4
Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.3 to 3.0.4.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v3.0.3...v3.0.4)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-03-04 09:28:14 +01:00
Amir Malka
667e5e8258 fix score calculation for framework with all controls in status irrelevant (#1802)
Signed-off-by: Amir Malka <amirm@armosec.io>
2025-03-03 15:20:14 +02:00
Matthias Bertschy
728b341048 Merge pull request #1797 from kubescape/prereq
update prerequisites command
2025-02-26 11:51:42 +01:00
Matthias Bertschy
75b295d579 update prerequisites command
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-26 11:20:33 +01:00
Matthias Bertschy
75298eabf2 Merge pull request #1796 from kubescape/dependabot/go_modules/httphandler/github.com/go-jose/go-jose/v4-4.0.5
Bump github.com/go-jose/go-jose/v4 from 4.0.2 to 4.0.5 in /httphandler
2025-02-25 08:45:31 +01:00
dependabot[bot]
2458f2ceb9 Bump github.com/go-jose/go-jose/v4 from 4.0.2 to 4.0.5
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.0.2 to 4.0.5.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.0.2...v4.0.5)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-25 07:58:42 +01:00
Amir Malka
f57948ad97 deprecate control name in exception policies (#1795)
* deprecate control name in posture exception policies

Signed-off-by: Amir Malka <amirm@armosec.io>

* deprecate control name in posture exception policies

Signed-off-by: Amir Malka <amirm@armosec.io>

* deprecate control name in posture exception policies

Signed-off-by: Amir Malka <amirm@armosec.io>

* deprecate control name in posture exception policies

Signed-off-by: Amir Malka <amirm@armosec.io>

---------

Signed-off-by: Amir Malka <amirm@armosec.io>
2025-02-20 10:27:27 +02:00
Matthias Bertschy
d0befc5f16 Merge pull request #1792 from kubescape/colors
removing enable/disable colors, as not compatible with all loggers
2025-02-18 12:11:40 +01:00
Matthias Bertschy
5d4bd2e94e removing enable/disable colors, as not compatible with all loggers
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-18 11:38:47 +01:00
Matthias Bertschy
ae37fdc295 fix go tidy
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-14 16:19:42 +01:00
Matthias Bertschy
3dd95ff3a3 Merge pull request #1791 from kubescape/prereq
update prerequisites
2025-02-14 16:12:03 +01:00
Matthias Bertschy
daadb5b804 update prerequisites
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-14 16:10:31 +01:00
Matthias Bertschy
d250017faf Merge pull request #1790 from pixel365/err
fix: add error handling and context propagation
2025-02-12 10:56:03 +01:00
Ruslan Semagin
835bcbeb12 fix: format imports with goimports
Signed-off-by: Ruslan Semagin <pixel.365.24@gmail.com>
2025-02-12 12:15:14 +03:00
Ruslan Semagin
2e4f7c4477 fix: add error handling and context propagation
Signed-off-by: Ruslan Semagin <pixel.365.24@gmail.com>
2025-02-12 09:02:01 +03:00
Matthias Bertschy
66bf93eb0c Merge pull request #1789 from pixel365/ctx
Refactor: propagate context from main to avoid redundant context creation
2025-02-11 21:27:48 +01:00
Matthias Bertschy
3a036ed0e3 remove test resources saved by accident
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-11 21:26:26 +01:00
Ruslan Semagin
fe7dad4560 Refactor: propagate context from main to avoid redundant context creation
- Introduced a single context in main() to handle interrupt signals (os.Interrupt, syscall.SIGTERM).
- Removed repetitive context creation in the program by reusing the propagated context.
- Improved code readability and maintainability by centralizing context management.
- Ensured consistent handling of graceful shutdown across the program.

Signed-off-by: Ruslan Semagin <pixel.365.24@gmail.com>
2025-02-11 19:52:48 +03:00
Matthias Bertschy
fb36b09f3a remove mv kubescape arm64 binary step
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-11 09:49:17 +01:00
Matthias Bertschy
e71b0c75a9 fix downloaded artifacts path
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-11 08:55:43 +01:00
Matthias Bertschy
d615099ce1 try fixing download-artifacts action for release
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-11 07:42:30 +01:00
Matthias Bertschy
f265b91939 Merge pull request #1788 from kubescape/sarif
do not skip on location resolver error
2025-02-10 13:40:59 +01:00
Matthias Bertschy
825694ade1 do not skip on location resolver error
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-10 10:25:44 +01:00
Matthias Bertschy
979a30aea7 Merge pull request #1591 from Sanskarzz/scanapiexception
added support for exception rules in Scan API ( As a HTTP request)
2025-02-07 13:32:42 +01:00
Matthias Bertschy
39c4aa4faa Merge pull request #1568 from VaibhavMalik4187/feature-exceptions
Feature: Added exceptions flag in scan image cmd
2025-02-07 12:40:24 +01:00
Matthias Bertschy
475b672a7a add fixed grypeDB for tests
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-07 12:34:11 +01:00
Matthias Bertschy
815c87b532 implement reviews from DW
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-07 12:16:35 +01:00
Sanskarzz
82120f9d31 added support for exception rules
Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
2025-02-07 12:15:56 +01:00
VaibhavMalik4187
0545818f82 Added tests and improvements for image exceptions
Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2025-02-07 10:26:53 +01:00
VaibhavMalik4187
046da1940c Added support for targets in image exceptions
This commit introduces the ability to specify targets in image
exceptions. Each target will have the following 4 attributes:

1. Registry
2. Organization
3. ImageName
4. ImageTag

These attributes will be used to match against the canonical image name
of the image to be scanned. The vulnerabilites and the severities
specified in the VulnerabilitiesIgnorePolicy object will be considered
only if the image to be scanned matches the targets specified for that
policy. Regular expressions can also be used to specify the image
attributes.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2025-02-07 10:26:53 +01:00
VaibhavMalik4187
a31154897f Added support for severity exceptions in imagescan
This commit add relevant functions to support severity exceptions during
image scan.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2025-02-07 10:26:53 +01:00
VaibhavMalik4187
199c57be30 WIP: Load image exceptions from file
Added initial commit to start loading image exceptions from json files.

Currently, it supports vulnerability exceptions using their CVE-IDs.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2025-02-07 10:26:53 +01:00
VaibhavMalik4187
7d55c79f11 Feature: Added exceptions flag in scan image cmd
This commit introduces the "exceptions" flag in the scan image command.
Users can pass a list of vulnerabilities they ignore while scanning an
image using this flag. Also added tests for the same.

Fixes: https://github.com/kubescape/kubescape/issues/1564

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2025-02-07 10:26:53 +01:00
Matthias Bertschy
ee76364371 fix scorecard-action version
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-07 09:23:28 +01:00
Matthias Bertschy
4f2c7ac1de Merge pull request #1787 from kubescape/bump
bump all CI actions
2025-02-07 09:09:44 +01:00
Matthias Bertschy
00340827be bump all CI actions
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-07 08:00:19 +01:00
Matthias Bertschy
708fe64240 Merge pull request #1786 from Fernando-hub527/refactor/maroto-version-v2
Refactor: maroto version v2
2025-02-07 07:33:34 +01:00
Fernando-hub527
8985bbe3a9 refactor: update Maroto configuration file location
Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-06 18:07:57 -03:00
Matthias Bertschy
1ffca5648e delete TableObject.getSeverityColor to please CI
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-02-06 07:56:07 +01:00
Fernando-hub527
76b1ecb022 refactor: create a method that returns the pdf row
Return a struct with the data for ease of use

Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-05 21:52:50 -03:00
Fernando-hub527
fc69a3692e refactor: remove unused code
Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-05 21:47:28 -03:00
Fernando-hub527
e159458129 test:validate creation of report pdf
Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-05 21:45:01 -03:00
Fernando-hub527
b259f117ff refactor: create a report template with maroto/v2
Separate template creation from application logic

Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-05 21:36:39 -03:00
Fernando-hub527
13cf34bffd refactor: update Maroto version to v2
Signed-off-by: Fernando-hub527 <fernandocoelhosaraivanando@gmail.com>
2025-02-05 21:31:22 -03:00
Matthias Bertschy
0300fee38b bump actions/download-artifact@v4
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-01-31 16:38:01 +01:00
Matthias Bertschy
d61d641e81 bump actions/upload-artifact@v4
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-01-31 16:09:16 +01:00
Matthias Bertschy
2added0f7c use go 1.23, disable cache
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-01-31 16:06:13 +01:00
Matthias Bertschy
b6f6573ed8 Merge pull request #1785 from kubescape/sarif
fix helm detection in sarif printer
2025-01-31 16:04:36 +01:00
Matthias Bertschy
4215771134 fix helm detection in sarif printer
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
2025-01-31 15:23:15 +01:00
Amit Schendel
fd37446e1b Merge pull request #1784 from kubescape/feature/incubating-logo
Changing README of Kubescape from Sandbox to Incubating
2025-01-27 14:01:09 +02:00
Amit Schendel
351498aac5 Changing README of Kubescape from Sandbox to Incubating
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
2025-01-27 13:47:16 +02:00
Eng Zer Jun
2005010568 Replace golang.org/x/exp/slices with slices from stdlib (#1783) 2025-01-17 20:51:08 +02:00
69 changed files with 2239 additions and 701 deletions

View File

@@ -65,7 +65,7 @@ jobs:
COMPONENT_NAME: kubescape
CGO_ENABLED: 0
GO111MODULE: ""
GO_VERSION: "1.21"
GO_VERSION: "1.23"
RELEASE: "latest"
CLIENT: test
secrets: inherit

View File

@@ -37,7 +37,7 @@ jobs:
COMPONENT_NAME: kubescape
CGO_ENABLED: 0
GO111MODULE: ""
GO_VERSION: "1.21"
GO_VERSION: "1.23"
RELEASE: ${{ needs.retag.outputs.NEW_TAG }}
CLIENT: release
secrets: inherit

View File

@@ -39,7 +39,6 @@ jobs:
name: Installing go
with:
go-version: ${{ inputs.GO_VERSION }}
cache: true
- name: Test core pkg
run: ${{ env.DOCKER_CMD }} go test -v ./...
@@ -93,8 +92,7 @@ jobs:
- uses: actions/setup-go@v4
name: Installing go
with:
go-version: '1.21'
cache: true
go-version: "1.23"
- name: Scanning - Forbidden Licenses (go-licenses)
id: licenses-scan
continue-on-error: true
@@ -107,7 +105,7 @@ jobs:
if: ${{ env.GITGUARDIAN_API_KEY }}
continue-on-error: true
id: credentials-scan
uses: GitGuardian/ggshield-action@4ab2994172fadab959240525e6b833d9ae3aca61 # ratchet:GitGuardian/ggshield-action@master
uses: GitGuardian/ggshield-action@master
with:
args: -v --all-policies
env:
@@ -120,7 +118,7 @@ jobs:
if: ${{ env.SNYK_TOKEN }}
id: vulnerabilities-scan
continue-on-error: true
uses: snyk/actions/golang@806182742461562b67788a64410098c9d9b96adb # ratchet:snyk/actions/golang@master
uses: snyk/actions/golang@master
with:
command: test --all-projects
env:
@@ -142,7 +140,7 @@ jobs:
- name: Comment results to PR
continue-on-error: true # Warning: This might break opening PRs from forks
uses: peter-evans/create-or-update-comment@5adcb0bb0f9fb3f95ef05400558bdb3f329ee808 # ratchet:peter-evans/create-or-update-comment@v2.1.0
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ github.event.pull_request.number }}
body: |

View File

@@ -163,7 +163,6 @@ jobs:
name: Installing go
with:
go-version: ${{ inputs.GO_VERSION }}
cache: true
- name: (debug) Step 3 - Check disk space before build
run: df -h
@@ -182,7 +181,7 @@ jobs:
- name: (debug) Step 5 - Check disk space before setting up Syft
run: df -h
- uses: anchore/sbom-action/download-syft@v0.15.2
- uses: anchore/sbom-action/download-syft@v0
name: Setup Syft
- name: (debug) Step 6 - Check disk space before goreleaser
@@ -224,7 +223,7 @@ jobs:
- name: (debug) Step 9 - Check disk space before uploading artifacts
run: df -h
- uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # ratchet:actions/upload-artifact@v3.1.1
- uses: actions/upload-artifact@v4
name: Upload artifacts
with:
name: kubescape
@@ -290,7 +289,7 @@ jobs:
if: ${{ (needs.wf-preparation.outputs.is-secret-set == 'true') && (always() && (contains(needs.*.result, 'success') || contains(needs.*.result, 'skipped')) && !(contains(needs.*.result, 'failure')) && !(contains(needs.*.result, 'cancelled'))) }}
runs-on: ubuntu-latest # This cannot change
steps:
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # ratchet:actions/download-artifact@v3.0.2
- uses: actions/download-artifact@v4
id: download-artifact
with:
name: kubescape
@@ -307,7 +306,7 @@ jobs:
repository: armosec/system-tests
path: .
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # ratchet:actions/setup-python@v4
- uses: actions/setup-python@v4
with:
python-version: '3.8.13'
cache: 'pip'
@@ -352,7 +351,7 @@ jobs:
deactivate
- name: Test Report
uses: mikepenz/action-junit-report@6e9933f4a97f4d2b99acef4d7b97924466037882 # ratchet:mikepenz/action-junit-report@v3.6.1
uses: mikepenz/action-junit-report@v5
if: always() # always run even if the previous step fails
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -33,7 +33,7 @@ jobs:
CGO_ENABLED: 0
GO111MODULE: "on"
BUILD_PLATFORM: ${{ inputs.PLATFORMS && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
GO_VERSION: "1.21"
GO_VERSION: "1.23"
REQUIRED_TESTS: '[]'
COSIGN: ${{ inputs.CO_SIGN }}
HELM_E2E_TEST: false

View File

@@ -27,14 +27,15 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # ratchet:actions/download-artifact@v3.0.2
- uses: actions/download-artifact@v4
id: download-artifact
with:
name: kubescape
path: .
# TODO: kubescape-windows-latest is deprecated and should be removed
- name: Get kubescape.exe from kubescape-windows-latest.exe
run: cp ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape-${{ env.WINDOWS_OS }}.exe ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape.exe
run: cp ${{steps.download-artifact.outputs.download-path}}/kubescape-${{ env.WINDOWS_OS }}.exe ${{steps.download-artifact.outputs.download-path}}/kubescape.exe
- name: Set release token
id: set-token
@@ -50,7 +51,7 @@ jobs:
find . -type f -print
- name: Release
uses: softprops/action-gh-release@975c1b265e11dd76618af1c374e7981f9a6ff44a
uses: softprops/action-gh-release@v2
with:
token: ${{ steps.set-token.outputs.token }}
name: ${{ inputs.RELEASE_NAME }}
@@ -60,32 +61,32 @@ jobs:
prerelease: false
fail_on_unmatched_files: true
files: |
./kubescape/kubescape-${{ env.MAC_OS }}
./kubescape/kubescape-${{ env.MAC_OS }}.sbom
./kubescape/kubescape-${{ env.MAC_OS }}.sha256
./kubescape/kubescape-${{ env.MAC_OS }}.tar.gz
./kubescape/kubescape-${{ env.UBUNTU_OS }}
./kubescape/kubescape-${{ env.UBUNTU_OS }}.sbom
./kubescape/kubescape-${{ env.UBUNTU_OS }}.sha256
./kubescape/kubescape-${{ env.UBUNTU_OS }}.tar.gz
./kubescape/kubescape-${{ env.WINDOWS_OS }}.exe
./kubescape/kubescape-${{ env.WINDOWS_OS }}.exe.sbom
./kubescape/kubescape-${{ env.WINDOWS_OS }}.exe.sha256
./kubescape/kubescape-${{ env.WINDOWS_OS }}.tar.gz
./kubescape/kubescape-arm64-${{ env.MAC_OS }}
./kubescape/kubescape-arm64-${{ env.MAC_OS }}.sbom
./kubescape/kubescape-arm64-${{ env.MAC_OS }}.sha256
./kubescape/kubescape-arm64-${{ env.MAC_OS }}.tar.gz
./kubescape/kubescape-arm64-${{ env.UBUNTU_OS }}
./kubescape/kubescape-arm64-${{ env.UBUNTU_OS }}.sbom
./kubescape/kubescape-arm64-${{ env.UBUNTU_OS }}.sha256
./kubescape/kubescape-arm64-${{ env.UBUNTU_OS }}.tar.gz
./kubescape/kubescape-arm64-${{ env.WINDOWS_OS }}.exe
./kubescape/kubescape-arm64-${{ env.WINDOWS_OS }}.exe.sbom
./kubescape/kubescape-arm64-${{ env.WINDOWS_OS }}.exe.sha256
./kubescape/kubescape-arm64-${{ env.WINDOWS_OS }}.tar.gz
./kubescape/kubescape-riscv64-${{ env.UBUNTU_OS }}
./kubescape/kubescape-riscv64-${{ env.UBUNTU_OS }}.sbom
./kubescape/kubescape-riscv64-${{ env.UBUNTU_OS }}.sha256
./kubescape/kubescape-riscv64-${{ env.UBUNTU_OS }}.tar.gz
./kubescape/kubescape.exe
./kubescape-${{ env.MAC_OS }}
./kubescape-${{ env.MAC_OS }}.sbom
./kubescape-${{ env.MAC_OS }}.sha256
./kubescape-${{ env.MAC_OS }}.tar.gz
./kubescape-${{ env.UBUNTU_OS }}
./kubescape-${{ env.UBUNTU_OS }}.sbom
./kubescape-${{ env.UBUNTU_OS }}.sha256
./kubescape-${{ env.UBUNTU_OS }}.tar.gz
./kubescape-${{ env.WINDOWS_OS }}.exe
./kubescape-${{ env.WINDOWS_OS }}.exe.sbom
./kubescape-${{ env.WINDOWS_OS }}.exe.sha256
./kubescape-${{ env.WINDOWS_OS }}.tar.gz
./kubescape-arm64-${{ env.MAC_OS }}
./kubescape-arm64-${{ env.MAC_OS }}.sbom
./kubescape-arm64-${{ env.MAC_OS }}.sha256
./kubescape-arm64-${{ env.MAC_OS }}.tar.gz
./kubescape-arm64-${{ env.UBUNTU_OS }}
./kubescape-arm64-${{ env.UBUNTU_OS }}.sbom
./kubescape-arm64-${{ env.UBUNTU_OS }}.sha256
./kubescape-arm64-${{ env.UBUNTU_OS }}.tar.gz
./kubescape-arm64-${{ env.WINDOWS_OS }}.exe
./kubescape-arm64-${{ env.WINDOWS_OS }}.exe.sbom
./kubescape-arm64-${{ env.WINDOWS_OS }}.exe.sha256
./kubescape-arm64-${{ env.WINDOWS_OS }}.tar.gz
./kubescape-riscv64-${{ env.UBUNTU_OS }}
./kubescape-riscv64-${{ env.UBUNTU_OS }}.sbom
./kubescape-riscv64-${{ env.UBUNTU_OS }}.sha256
./kubescape-riscv64-${{ env.UBUNTU_OS }}.tar.gz
./kubescape.exe

View File

@@ -63,22 +63,21 @@ jobs:
with:
submodules: recursive
- name: Set up QEMU
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # ratchet:docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # ratchet:docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Quay.io
env:
QUAY_PASSWORD: ${{ secrets.QUAYIO_REGISTRY_PASSWORD }}
QUAY_USERNAME: ${{ secrets.QUAYIO_REGISTRY_USERNAME }}
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # ratchet:actions/download-artifact@v3.0.2
- uses: actions/download-artifact@v4
id: download-artifact
with:
name: kubescape
path: .
- name: mv kubescape amd64 binary
run: mv ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape-ubuntu-latest kubescape-amd64-ubuntu-latest
- name: mv kubescape arm64 binary
run: mv ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape-arm64-ubuntu-latest kubescape-arm64-ubuntu-latest
run: mv kubescape-ubuntu-latest kubescape-amd64-ubuntu-latest
- name: chmod +x
run: chmod +x -v kubescape-a*
- name: Build and push images
@@ -106,4 +105,3 @@ jobs:
# Verify the image
echo "$COSIGN_PUBLIC_KEY" > cosign.pub
cosign verify -key cosign.pub ${{ inputs.image_name }}:${{ inputs.image_tag }}

View File

@@ -32,12 +32,12 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
uses: actions/checkout@v4
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@v2.4.0
with:
results_file: results.sarif
results_format: sarif
@@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
uses: actions/upload-artifact@v4
with:
name: SARIF file
path: results.sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif

View File

@@ -7,14 +7,14 @@ jobs:
if: github.event.label.name == 'typo'
runs-on: ubuntu-latest
steps:
- uses: ben-z/actions-comment-on-issue@10be23f9c43ac792663043420fda29dde07e2f0f # ratchet:ben-z/actions-comment-on-issue@1.0.2
- uses: ben-z/actions-comment-on-issue@1.0.2
with:
message: "Hello! :wave:\n\nThis issue is being automatically closed, Please open a PR with a relevant fix."
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
auto_close_issues:
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/close-matching-issues@e9e43aad2fa6f06a058cedfd8fb975fd93b56d8f # ratchet:lee-dohm/close-matching-issues@v2
- uses: lee-dohm/close-matching-issues@v2
with:
query: 'label:typo'
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -3,7 +3,7 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/kubescape/kubescape)](https://goreportcard.com/report/github.com/kubescape/kubescape)
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/kubescape/kubescape)
[![GitHub](https://img.shields.io/github/license/kubescape/kubescape)](https://github.com/kubescape/kubescape/blob/master/LICENSE)
[![CNCF](https://shields.io/badge/CNCF-Sandbox%20project-blue?logo=linux-foundation&style=flat)](https://landscape.cncf.io/card-mode?project=sandbox&selected=kubescape)
[![CNCF](https://shields.io/badge/CNCF-Incubating%20project-blue?logo=linux-foundation&style=flat)](https://landscape.cncf.io/?item=provisioning--security-compliance--kubescape)
[![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/kubescape)](https://artifacthub.io/packages/search?repo=kubescape)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkubescape%2Fkubescape.svg?type=shield&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkubescape%2Fkubescape?ref=badge_shield&issueType=license)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/6944/badge)](https://www.bestpractices.dev/projects/6944)
@@ -26,7 +26,7 @@ Kubescape is an open-source Kubernetes security platform that provides comprehen
Kubescape scans clusters, YAML files, and Helm charts. It detects misconfigurations according to multiple frameworks (including [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo/?utm_source=github&utm_medium=repository), [MITRE ATT&CK®](https://www.armosec.io/glossary/mitre-attck-framework/?utm_source=github&utm_medium=repository) and the [CIS Benchmark](https://www.armosec.io/blog/cis-kubernetes-benchmark-framework-scanning-tools-comparison/?utm_source=github&utm_medium=repository)).
Kubescape was created by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository) and is a [Cloud Native Computing Foundation (CNCF) sandbox project](https://www.cncf.io/sandbox-projects/).
Kubescape was created by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository) and is a [Cloud Native Computing Foundation (CNCF) incubating project](https://www.cncf.io/projects/).
_Please [star ⭐](https://github.com/kubescape/kubescape/stargazers) the repo if you want us to continue developing and improving Kubescape! 😀_
@@ -114,8 +114,8 @@ Kubescape changes are tracked on the [release](https://github.com/kubescape/kube
Copyright 2021-2024, the Kubescape Authors. All rights reserved. Kubescape is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
Kubescape is a [Cloud Native Computing Foundation (CNCF) sandbox project](https://www.cncf.io/sandbox-projects/) and was contributed by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository).
Kubescape is a [Cloud Native Computing Foundation (CNCF) incubating project](https://www.cncf.io/projects/kubescape/) and was contributed by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository).
<div align="center">
<img src="https://raw.githubusercontent.com/cncf/artwork/master/other/cncf-sandbox/horizontal/color/cncf-sandbox-horizontal-color.svg" width="300" alt="CNCF Sandbox Project">
<img src="https://raw.githubusercontent.com/cncf/artwork/refs/heads/main/other/cncf-member/incubating/color/cncf-incubating-color.svg" width="300" alt="CNCF Incubating Project">
</div>

View File

@@ -1,8 +1,6 @@
package config
import (
"context"
"github.com/kubescape/go-logger"
"github.com/kubescape/kubescape/v3/core/meta"
v1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
@@ -15,7 +13,7 @@ func getDeleteCmd(ks meta.IKubescape) *cobra.Command {
Short: "Delete cached configurations",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if err := ks.DeleteCachedConfig(context.TODO(), &v1.DeleteConfig{}); err != nil {
if err := ks.DeleteCachedConfig(&v1.DeleteConfig{}); err != nil {
logger.L().Fatal(err.Error())
}
},

View File

@@ -1,9 +1,9 @@
package download
import (
"context"
"fmt"
"path/filepath"
"slices"
"strings"
"github.com/kubescape/go-logger"
@@ -12,7 +12,6 @@ import (
"github.com/kubescape/kubescape/v3/core/meta"
v1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
)
var (
@@ -74,11 +73,9 @@ func GetDownloadCmd(ks meta.IKubescape) *cobra.Command {
downloadInfo.Target = args[0]
if len(args) >= 2 {
downloadInfo.Identifier = args[1]
}
if err := ks.Download(context.TODO(), &downloadInfo); err != nil {
if err := ks.Download(&downloadInfo); err != nil {
logger.L().Fatal(err.Error())
}
return nil

View File

@@ -1,7 +1,6 @@
package fix
import (
"context"
"errors"
"fmt"
@@ -35,7 +34,7 @@ func GetFixCmd(ks meta.IKubescape) *cobra.Command {
}
fixInfo.ReportFile = args[0]
return ks.Fix(context.TODO(), &fixInfo)
return ks.Fix(&fixInfo)
},
}

View File

@@ -1,9 +1,9 @@
package list
import (
"context"
"errors"
"fmt"
"slices"
"strings"
"github.com/kubescape/go-logger"
@@ -12,7 +12,6 @@ import (
"github.com/kubescape/kubescape/v3/core/meta"
v1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
)
var (
@@ -62,7 +61,7 @@ func GetListCmd(ks meta.IKubescape) *cobra.Command {
listPolicies.Target = args[0]
if err := ks.List(context.TODO(), &listPolicies); err != nil {
if err := ks.List(&listPolicies); err != nil {
logger.L().Fatal(err.Error())
}
return nil

View File

@@ -1,7 +1,6 @@
package patch
import (
"context"
"errors"
"fmt"
"strings"
@@ -50,7 +49,7 @@ func GetPatchCmd(ks meta.IKubescape) *cobra.Command {
return err
}
results, err := ks.Patch(context.Background(), &patchInfo, &scanInfo)
results, err := ks.Patch(&patchInfo, &scanInfo)
if err != nil {
return err
}

View File

@@ -1,17 +1,45 @@
package prerequisites
import (
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v3/core/meta"
"github.com/kubescape/sizing-checker/pkg/sizingchecker"
"github.com/kubescape/sizing-checker/pkg/checks/connectivitycheck"
"github.com/kubescape/sizing-checker/pkg/checks/ebpfcheck"
"github.com/kubescape/sizing-checker/pkg/checks/pvcheck"
"github.com/kubescape/sizing-checker/pkg/checks/sizing"
"github.com/kubescape/sizing-checker/pkg/common"
"github.com/spf13/cobra"
)
func GetPreReqCmd(ks meta.IKubescape) *cobra.Command {
// preReqCmd represents the prerequisites command
preReqCmd := &cobra.Command{
Use: "prerequisites",
Short: "Check prerequisites for installing Kubescape Operator",
Run: func(cmd *cobra.Command, args []string) {
sizingchecker.RunSizingChecker()
clientSet, inCluster := common.BuildKubeClient()
if clientSet == nil {
logger.L().Fatal("Could not create kube client. Exiting.")
}
// 1) Collect cluster data
clusterData, err := common.CollectClusterData(ks.Context(), clientSet)
if err != nil {
logger.L().Error("Failed to collect cluster data", helpers.Error(err))
}
// 2) Run checks
sizingResult := sizing.RunSizingChecker(clusterData)
pvResult := pvcheck.RunPVProvisioningCheck(ks.Context(), clientSet, clusterData, inCluster)
connectivityResult := connectivitycheck.RunConnectivityChecks(ks.Context(), clientSet, clusterData, inCluster)
ebpfResult := ebpfcheck.RunEbpfCheck(ks.Context(), clientSet, clusterData, inCluster)
// 3) Build and export the final ReportData
finalReport := common.BuildReportData(clusterData, sizingResult, pvResult, connectivityResult, ebpfResult)
finalReport.InCluster = inCluster
common.GenerateOutput(finalReport, inCluster)
},
}
return preReqCmd

View File

@@ -1,6 +1,7 @@
package cmd
import (
"context"
"fmt"
"strings"
@@ -42,8 +43,8 @@ var ksExamples = fmt.Sprintf(`
%[1]s config view
`, cautils.ExecName())
func NewDefaultKubescapeCommand() *cobra.Command {
ks := core.NewKubescape()
func NewDefaultKubescapeCommand(ctx context.Context) *cobra.Command {
ks := core.NewKubescape(ctx)
return getRootCmd(ks)
}
@@ -84,8 +85,6 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
rootCmd.PersistentFlags().StringVarP(&rootInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/")))
rootCmd.PersistentFlags().StringVar(&rootInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]")
rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable color output for logging")
rootCmd.PersistentFlags().BoolVarP(&rootInfo.EnableColor, "enable-color", "", false, "Force enable color output for logging")
rootCmd.PersistentFlags().StringVarP(&rootInfo.KubeContext, "kube-context", "", "", "Kube context. Default will use the current-context")
// Supported commands
@@ -93,9 +92,9 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
rootCmd.AddCommand(download.GetDownloadCmd(ks))
rootCmd.AddCommand(list.GetListCmd(ks))
rootCmd.AddCommand(completion.GetCompletionCmd())
rootCmd.AddCommand(version.GetVersionCmd())
rootCmd.AddCommand(version.GetVersionCmd(ks))
rootCmd.AddCommand(config.GetConfigCmd(ks))
rootCmd.AddCommand(update.GetUpdateCmd())
rootCmd.AddCommand(update.GetUpdateCmd(ks))
rootCmd.AddCommand(fix.GetFixCmd(ks))
rootCmd.AddCommand(patch.GetPatchCmd(ks))
rootCmd.AddCommand(vap.GetVapHelperCmd())
@@ -115,7 +114,7 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
return rootCmd
}
func Execute() error {
ks := NewDefaultKubescapeCommand()
func Execute(ctx context.Context) error {
ks := NewDefaultKubescapeCommand(ctx)
return ks.Execute()
}

View File

@@ -18,9 +18,6 @@ import (
)
func initLogger() {
logger.DisableColor(rootInfo.DisableColor)
logger.EnableColor(rootInfo.EnableColor)
if rootInfo.LoggerName == "" {
if l := os.Getenv("KS_LOGGER_NAME"); l != "" {
rootInfo.LoggerName = l
@@ -34,8 +31,8 @@ func initLogger() {
}
logger.InitLogger(rootInfo.LoggerName)
}
func initLoggerLevel() {
if rootInfo.Logger == helpers.InfoLevel.String() {
} else if l := os.Getenv("KS_LOGGER"); l != "" {

View File

@@ -1,7 +1,6 @@
package scan
import (
"context"
"fmt"
"io"
"os"
@@ -96,12 +95,11 @@ func getControlCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comman
return err
}
ctx := context.TODO()
results, err := ks.Scan(ctx, scanInfo)
results, err := ks.Scan(scanInfo)
if err != nil {
logger.L().Fatal(err.Error())
}
if err := results.HandleResults(ctx); err != nil {
if err := results.HandleResults(ks.Context()); err != nil {
logger.L().Fatal(err.Error())
}
if !scanInfo.VerboseMode {

View File

@@ -1,11 +1,11 @@
package scan
import (
"context"
"errors"
"fmt"
"io"
"os"
"slices"
"strings"
"github.com/kubescape/go-logger"
@@ -18,7 +18,6 @@ import (
reporthandlingapis "github.com/kubescape/opa-utils/reporthandling/apis"
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
)
var (
@@ -113,13 +112,12 @@ func getFrameworkCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comm
scanInfo.SetPolicyIdentifiers(frameworks, apisv1.KindFramework)
ctx := context.TODO()
results, err := ks.Scan(ctx, scanInfo)
results, err := ks.Scan(scanInfo)
if err != nil {
logger.L().Fatal(err.Error())
}
if err = results.HandleResults(ctx); err != nil {
if err = results.HandleResults(ks.Context()); err != nil {
logger.L().Fatal(err.Error())
}

View File

@@ -1,7 +1,6 @@
package scan
import (
"context"
"fmt"
"github.com/kubescape/go-logger"
@@ -24,12 +23,17 @@ var (
# Scan the 'nginx' image and see the full report
%[1]s scan image "nginx" -v
# Scan the 'nginx' image and use exceptions
%[1]s scan image "nginx" --exceptions exceptions.json
`, cautils.ExecName())
)
// getImageCmd returns the scan image command
func getImageCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command {
var imgCredentials shared.ImageCredentials
var exceptions string
cmd := &cobra.Command{
Use: "image <image>:<tag> [flags]",
Short: "Scan an image for vulnerabilities",
@@ -50,12 +54,13 @@ func getImageCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command
}
imgScanInfo := &metav1.ImageScanInfo{
Image: args[0],
Username: imgCredentials.Username,
Password: imgCredentials.Password,
Image: args[0],
Username: imgCredentials.Username,
Password: imgCredentials.Password,
Exceptions: exceptions,
}
results, err := ks.ScanImage(context.Background(), imgScanInfo, scanInfo)
results, err := ks.ScanImage(imgScanInfo, scanInfo)
if err != nil {
return err
}
@@ -68,6 +73,8 @@ func getImageCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command
},
}
// The exceptions flag
cmd.PersistentFlags().StringVarP(&exceptions, "exceptions", "", "", "Path to the exceptions file")
cmd.PersistentFlags().StringVarP(&imgCredentials.Username, "username", "u", "", "Username for registry login")
cmd.PersistentFlags().StringVarP(&imgCredentials.Password, "password", "p", "", "Password for registry login")

View File

@@ -1,7 +1,6 @@
package scan
import (
"context"
"flag"
"fmt"
"strings"
@@ -135,15 +134,12 @@ func setSecurityViewScanInfo(args []string, scanInfo *cautils.ScanInfo) {
}
func securityScan(scanInfo cautils.ScanInfo, ks meta.IKubescape) error {
ctx := context.TODO()
results, err := ks.Scan(ctx, &scanInfo)
results, err := ks.Scan(&scanInfo)
if err != nil {
return err
}
if err = results.HandleResults(ctx); err != nil {
if err = results.HandleResults(ks.Context()); err != nil {
return err
}

View File

@@ -1,7 +1,6 @@
package scan
import (
"context"
"errors"
"fmt"
"strings"
@@ -66,13 +65,12 @@ func getWorkloadCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comma
setWorkloadScanInfo(scanInfo, kind, name)
// todo: add api version if provided
ctx := context.TODO()
results, err := ks.Scan(ctx, scanInfo)
results, err := ks.Scan(scanInfo)
if err != nil {
logger.L().Fatal(err.Error())
}
if err = results.HandleResults(ctx); err != nil {
if err = results.HandleResults(ks.Context()); err != nil {
logger.L().Fatal(err.Error())
}

View File

@@ -5,10 +5,11 @@ package update
// kubescape update
import (
"context"
"fmt"
"strings"
"github.com/kubescape/kubescape/v3/core/meta"
"github.com/kubescape/backend/pkg/versioncheck"
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
@@ -25,17 +26,18 @@ var updateCmdExamples = fmt.Sprintf(`
%[1]s update
`, cautils.ExecName())
func GetUpdateCmd() *cobra.Command {
func GetUpdateCmd(ks meta.IKubescape) *cobra.Command {
updateCmd := &cobra.Command{
Use: "update",
Short: "Update to latest release version",
Long: ``,
Example: updateCmdExamples,
RunE: func(_ *cobra.Command, args []string) error {
ctx := context.TODO()
v := versioncheck.NewVersionCheckHandler()
versionCheckRequest := versioncheck.NewVersionCheckRequest("", versioncheck.BuildNumber, "", "", "update", nil)
v.CheckLatestVersion(ctx, versionCheckRequest)
if err := v.CheckLatestVersion(ks.Context(), versionCheckRequest); err != nil {
return err
}
//Checking the user's version of kubescape to the latest release
if versioncheck.BuildNumber == "" || strings.Contains(versioncheck.BuildNumber, "rc") {

View File

@@ -1,23 +1,26 @@
package version
import (
"context"
"fmt"
"github.com/kubescape/kubescape/v3/core/meta"
"github.com/kubescape/backend/pkg/versioncheck"
"github.com/spf13/cobra"
)
func GetVersionCmd() *cobra.Command {
func GetVersionCmd(ks meta.IKubescape) *cobra.Command {
versionCmd := &cobra.Command{
Use: "version",
Short: "Get current version",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.TODO()
v := versioncheck.NewIVersionCheckHandler(ctx)
v := versioncheck.NewIVersionCheckHandler(ks.Context())
versionCheckRequest := versioncheck.NewVersionCheckRequest("", versioncheck.BuildNumber, "", "", "version", nil)
v.CheckLatestVersion(ctx, versionCheckRequest)
if err := v.CheckLatestVersion(ks.Context(), versionCheckRequest); err != nil {
return err
}
fmt.Fprintf(cmd.OutOrStdout(),
"Your current version is: %s\n",
versionCheckRequest.ClientVersion,

View File

@@ -2,9 +2,12 @@ package version
import (
"bytes"
"context"
"io"
"testing"
"github.com/kubescape/kubescape/v3/core/core"
"github.com/kubescape/backend/pkg/versioncheck"
"github.com/stretchr/testify/assert"
)
@@ -30,7 +33,8 @@ func TestGetVersionCmd(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
versioncheck.BuildNumber = tt.buildNumber
if cmd := GetVersionCmd(); cmd != nil {
ks := core.NewKubescape(context.TODO())
if cmd := GetVersionCmd(ks); cmd != nil {
buf := bytes.NewBufferString("")
cmd.SetOut(buf)
cmd.Execute()

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"github.com/kubescape/go-logger"
@@ -14,7 +15,6 @@ import (
"github.com/kubescape/k8s-interface/workloadinterface"
"github.com/kubescape/opa-utils/objectsenvelopes"
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)

View File

@@ -10,8 +10,6 @@ type RootInfo struct {
Logger string // logger level
LoggerName string // logger name ("pretty"/"zap"/"none")
CacheDir string // cached dir
DisableColor bool // Disable Color
EnableColor bool // Force enable Color
DiscoveryServerURL string // Discovery Server URL (See https://github.com/kubescape/backend/tree/main/pkg/servicediscovery)
KubeContext string // context name
}

View File

@@ -1,7 +1,6 @@
package core
import (
"context"
"fmt"
"github.com/kubescape/kubescape/v3/core/cautils"
@@ -35,8 +34,8 @@ func (ks *Kubescape) ViewCachedConfig(viewConfig *metav1.ViewConfig) error {
return nil
}
func (ks *Kubescape) DeleteCachedConfig(ctx context.Context, deleteConfig *metav1.DeleteConfig) error {
func (ks *Kubescape) DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error {
tenant := cautils.GetTenantConfig("", "", "", "", nil) // change k8sinterface
return tenant.DeleteCachedConfig(ctx)
return tenant.DeleteCachedConfig(ks.Context())
}

View File

@@ -44,12 +44,12 @@ func DownloadSupportCommands() []string {
return commands
}
func (ks *Kubescape) Download(ctx context.Context, downloadInfo *metav1.DownloadInfo) error {
func (ks *Kubescape) Download(downloadInfo *metav1.DownloadInfo) error {
setPathAndFilename(downloadInfo)
if err := os.MkdirAll(downloadInfo.Path, os.ModePerm); err != nil {
return err
}
if err := downloadArtifact(ctx, downloadInfo, downloadFunc); err != nil {
if err := downloadArtifact(ks.Context(), downloadInfo, downloadFunc); err != nil {
return err
}
return nil

View File

@@ -1,7 +1,6 @@
package core
import (
"context"
"fmt"
"strings"
@@ -16,14 +15,14 @@ const (
confirmationQuestion = "Would you like to apply the changes to the files above? [y|n]: "
)
func (ks *Kubescape) Fix(ctx context.Context, fixInfo *metav1.FixInfo) error {
func (ks *Kubescape) Fix(fixInfo *metav1.FixInfo) error {
logger.L().Info("Reading report file...")
handler, err := fixhandler.NewFixHandler(fixInfo)
if err != nil {
return err
}
resourcesToFix := handler.PrepareResourcesToFix(ctx)
resourcesToFix := handler.PrepareResourcesToFix(ks.Context())
if len(resourcesToFix) == 0 {
logger.L().Info(noResourcesToFix)
@@ -42,12 +41,12 @@ func (ks *Kubescape) Fix(ctx context.Context, fixInfo *metav1.FixInfo) error {
return nil
}
updatedFilesCount, errors := handler.ApplyChanges(ctx, resourcesToFix)
updatedFilesCount, errors := handler.ApplyChanges(ks.Context(), resourcesToFix)
logger.L().Info(fmt.Sprintf("Fixed resources in %d files.", updatedFilesCount))
if len(errors) > 0 {
for _, err := range errors {
logger.L().Ctx(ctx).Warning(err.Error())
logger.L().Ctx(ks.Context()).Warning(err.Error())
}
return fmt.Errorf("Failed to fix some resources, check the logs for more details")
}

View File

@@ -1,8 +1,11 @@
package core
import (
"context"
"encoding/json"
"fmt"
"os"
"regexp"
"strings"
"github.com/anchore/grype/grype/presenter/models"
"github.com/kubescape/go-logger"
@@ -12,7 +15,153 @@ import (
"github.com/kubescape/kubescape/v3/pkg/imagescan"
)
func (ks *Kubescape) ScanImage(ctx context.Context, imgScanInfo *ksmetav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
// Data structure to represent attributes
type Attributes struct {
Registry string `json:"registry"`
Organization string `json:"organization,omitempty"`
ImageName string `json:"imageName"`
ImageTag string `json:"imageTag,omitempty"`
}
// Data structure for a target
type Target struct {
DesignatorType string `json:"designatorType"`
Attributes Attributes `json:"attributes"`
}
// Data structure for metadata
type Metadata struct {
Name string `json:"name"`
}
// Data structure for vulnerabilities and severities
type VulnerabilitiesIgnorePolicy struct {
Metadata Metadata `json:"metadata"`
Kind string `json:"kind"`
Targets []Target `json:"targets"`
Vulnerabilities []string `json:"vulnerabilities"`
Severities []string `json:"severities"`
}
// Loads excpetion policies from exceptions json object.
func GetImageExceptionsFromFile(filePath string) ([]VulnerabilitiesIgnorePolicy, error) {
// Read the JSON file
jsonFile, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("error reading exceptions file: %w", err)
}
// Unmarshal the JSON data into an array of VulnerabilitiesIgnorePolicy
var policies []VulnerabilitiesIgnorePolicy
err = json.Unmarshal(jsonFile, &policies)
if err != nil {
return nil, fmt.Errorf("error unmarshaling exceptions file: %w", err)
}
return policies, nil
}
// This function will identify the registry, organization and image tag from the image name
func getAttributesFromImage(imgName string) (Attributes, error) {
canonicalImageName, err := cautils.NormalizeImageName(imgName)
if err != nil {
return Attributes{}, err
}
tokens := strings.Split(canonicalImageName, "/")
registry := tokens[0]
organization := tokens[1]
imageNameAndTag := strings.Split(tokens[2], ":")
imageName := imageNameAndTag[0]
// Intialize the image tag with default value
imageTag := "latest"
if len(imageNameAndTag) > 1 {
imageTag = imageNameAndTag[1]
}
attributes := Attributes{
Registry: registry,
Organization: organization,
ImageName: imageName,
ImageTag: imageTag,
}
return attributes, nil
}
// Checks if the target string matches the regex pattern
func regexStringMatch(pattern, target string) bool {
re, err := regexp.Compile(pattern)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to generate regular expression: %s", err))
return false
}
if re.MatchString(target) {
return true
}
return false
}
// Compares the registry, organization, image name, image tag against the targets specified
// in the exception policy object to check if the image being scanned qualifies for an
// exception policy.
func isTargetImage(targets []Target, attributes Attributes) bool {
for _, target := range targets {
return regexStringMatch(target.Attributes.Registry, attributes.Registry) && regexStringMatch(target.Attributes.Organization, attributes.Organization) && regexStringMatch(target.Attributes.ImageName, attributes.ImageName) && regexStringMatch(target.Attributes.ImageTag, attributes.ImageTag)
}
return false
}
// Generates a list of unique CVE-IDs and the severities which are to be excluded for
// the image being scanned.
func getUniqueVulnerabilitiesAndSeverities(policies []VulnerabilitiesIgnorePolicy, image string) ([]string, []string) {
// Create maps with slices as values to store unique vulnerabilities and severities (case-insensitive)
uniqueVulns := make(map[string][]string)
uniqueSevers := make(map[string][]string)
imageAttributes, err := getAttributesFromImage(image)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to generate image attributes: %s", err))
}
// Iterate over each policy and its vulnerabilities/severities
for _, policy := range policies {
// Include the exceptions only if the image is one of the targets
if isTargetImage(policy.Targets, imageAttributes) {
for _, vulnerability := range policy.Vulnerabilities {
// Add to slice directly
vulnerabilityUppercase := strings.ToUpper(vulnerability)
uniqueVulns[vulnerabilityUppercase] = append(uniqueVulns[vulnerabilityUppercase], vulnerability)
}
for _, severity := range policy.Severities {
// Add to slice directly
severityUppercase := strings.ToUpper(severity)
uniqueSevers[severityUppercase] = append(uniqueSevers[severityUppercase], severity)
}
}
}
// Extract unique keys (which are unique vulnerabilities/severities) and their slices
uniqueVulnsList := make([]string, 0, len(uniqueVulns))
for vuln := range uniqueVulns {
uniqueVulnsList = append(uniqueVulnsList, vuln)
}
uniqueSeversList := make([]string, 0, len(uniqueSevers))
for sever := range uniqueSevers {
uniqueSeversList = append(uniqueSeversList, sever)
}
return uniqueVulnsList, uniqueSeversList
}
func (ks *Kubescape) ScanImage(imgScanInfo *ksmetav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
logger.L().Start(fmt.Sprintf("Scanning image %s...", imgScanInfo.Image))
dbCfg, _ := imagescan.NewDefaultDBConfig()
@@ -23,7 +172,19 @@ func (ks *Kubescape) ScanImage(ctx context.Context, imgScanInfo *ksmetav1.ImageS
Password: imgScanInfo.Password,
}
scanResults, err := svc.Scan(ctx, imgScanInfo.Image, creds)
var vulnerabilityExceptions []string
var severityExceptions []string
if imgScanInfo.Exceptions != "" {
exceptionPolicies, err := GetImageExceptionsFromFile(imgScanInfo.Exceptions)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to load exceptions from file: %s", imgScanInfo.Exceptions))
return nil, err
}
vulnerabilityExceptions, severityExceptions = getUniqueVulnerabilitiesAndSeverities(exceptionPolicies, imgScanInfo.Image)
}
scanResults, err := svc.Scan(ks.Context(), imgScanInfo.Image, creds, vulnerabilityExceptions, severityExceptions)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to scan image: %s", imgScanInfo.Image))
return nil, err
@@ -33,9 +194,9 @@ func (ks *Kubescape) ScanImage(ctx context.Context, imgScanInfo *ksmetav1.ImageS
scanInfo.SetScanType(cautils.ScanTypeImage)
outputPrinters := GetOutputPrinters(scanInfo, ctx, "")
outputPrinters := GetOutputPrinters(scanInfo, ks.Context(), "")
uiPrinter := GetUIPrinter(ctx, scanInfo, "")
uiPrinter := GetUIPrinter(ks.Context(), scanInfo, "")
resultsHandler := resultshandling.NewResultsHandler(nil, outputPrinters, uiPrinter)
@@ -46,5 +207,5 @@ func (ks *Kubescape) ScanImage(ctx context.Context, imgScanInfo *ksmetav1.ImageS
},
}
return scanResults, resultsHandler.HandleResults(ctx)
return scanResults, resultsHandler.HandleResults(ks.Context())
}

View File

@@ -0,0 +1,420 @@
package core
import (
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetImageExceptionsFromFile(t *testing.T) {
tests := []struct {
filePath string
expectedPolicies []VulnerabilitiesIgnorePolicy
expectedErr error
}{
{
filePath: "./testdata/exceptions.json",
expectedPolicies: []VulnerabilitiesIgnorePolicy{
{
Metadata: Metadata{
Name: "medium-severity-vulnerabilites-exceptions",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "docker.io",
Organization: "",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{},
Severities: []string{"medium"},
},
{
Metadata: Metadata{
Name: "exclude-allowed-hostPath-control",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "",
Organization: "",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{"CVE-2023-42366", "CVE-2023-42365"},
Severities: []string{"critical", "low"},
},
{
Metadata: Metadata{
Name: "regex-example",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "quay.*",
Organization: "kube*",
ImageName: "kubescape*",
ImageTag: "v2*",
},
},
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "docker.io",
Organization: ".*",
ImageName: "kube*",
ImageTag: "v3*",
},
},
},
Vulnerabilities: []string{"CVE-2023-6879", "CVE-2023-44487"},
Severities: []string{"critical", "low"},
},
},
expectedErr: nil,
},
{
filePath: "./testdata/empty_exceptions.json",
expectedPolicies: []VulnerabilitiesIgnorePolicy{},
expectedErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.filePath, func(t *testing.T) {
policies, err := GetImageExceptionsFromFile(tt.filePath)
assert.Equal(t, tt.expectedPolicies, policies)
assert.Equal(t, tt.expectedErr, err)
})
}
}
func TestGetAttributesFromImage(t *testing.T) {
tests := []struct {
imageName string
expectedAttributes Attributes
expectedErr error
}{
{
imageName: "quay.io/kubescape/kubescape-cli:v3.0.0",
expectedAttributes: Attributes{
Registry: "quay.io",
Organization: "kubescape",
ImageName: "kubescape-cli",
ImageTag: "v3.0.0",
},
expectedErr: nil,
},
{
imageName: "alpine",
expectedAttributes: Attributes{
Registry: "docker.io",
Organization: "library",
ImageName: "alpine",
ImageTag: "latest",
},
expectedErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.imageName, func(t *testing.T) {
attributes, err := getAttributesFromImage(tt.imageName)
assert.Equal(t, tt.expectedErr, err)
assert.Equal(t, tt.expectedAttributes, attributes)
})
}
}
func TestRegexStringMatch(t *testing.T) {
tests := []struct {
pattern string
target string
expected bool
}{
{
pattern: ".*",
target: "quay.io",
expected: true,
},
{
pattern: "kubescape",
target: "kubescape",
expected: true,
},
{
pattern: "kubescape*",
target: "kubescape-cli",
expected: true,
},
{
pattern: "",
target: "v3.0.0",
expected: true,
},
{
pattern: "docker.io",
target: "quay.io",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.target+"/"+tt.pattern, func(t *testing.T) {
assert.Equal(t, tt.expected, regexStringMatch(tt.pattern, tt.target))
})
}
}
func TestIsTargetImage(t *testing.T) {
tests := []struct {
targets []Target
attributes Attributes
expected bool
}{
{
targets: []Target{
{
Attributes: Attributes{
Registry: "docker.io",
Organization: ".*",
ImageName: ".*",
ImageTag: "",
},
},
},
attributes: Attributes{
Registry: "quay.io",
Organization: "kubescape",
ImageName: "kubescape-cli",
ImageTag: "v3.0.0",
},
expected: false,
},
{
targets: []Target{
{
Attributes: Attributes{
Registry: "quay.io",
Organization: "kubescape",
ImageName: "kubescape*",
ImageTag: "",
},
},
},
attributes: Attributes{
Registry: "quay.io",
Organization: "kubescape",
ImageName: "kubescape-cli",
ImageTag: "v3.0.0",
},
expected: true,
},
{
targets: []Target{
{
Attributes: Attributes{
Registry: "docker.io",
Organization: "library",
ImageName: "alpine",
ImageTag: "",
},
},
},
attributes: Attributes{
Registry: "docker.io",
Organization: "library",
ImageName: "alpine",
ImageTag: "latest",
},
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.attributes.Registry+"/"+tt.attributes.ImageName, func(t *testing.T) {
assert.Equal(t, tt.expected, isTargetImage(tt.targets, tt.attributes))
})
}
}
func TestGetVulnerabilitiesAndSeverities(t *testing.T) {
tests := []struct {
policies []VulnerabilitiesIgnorePolicy
image string
expectedVulnerabilities []string
expectedSeverities []string
}{
{
policies: []VulnerabilitiesIgnorePolicy{
{
Metadata: Metadata{
Name: "vulnerabilites-exceptions",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "",
Organization: "kubescape*",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{"CVE-2023-42365"},
Severities: []string{},
},
{
Metadata: Metadata{
Name: "exclude-allowed-hostPath-control",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "docker.io",
Organization: "",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{"CVE-2023-42366", "CVE-2023-42365"},
Severities: []string{"critical", "low"},
},
},
image: "quay.io/kubescape/kubescape-cli:v3.0.0",
expectedVulnerabilities: []string{"CVE-2023-42365"},
expectedSeverities: []string{},
},
{
policies: []VulnerabilitiesIgnorePolicy{
{
Metadata: Metadata{
Name: "medium-severity-vulnerabilites-exceptions",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "",
Organization: "",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{},
Severities: []string{"medium"},
},
{
Metadata: Metadata{
Name: "exclude-allowed-hostPath-control",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "quay.io",
Organization: "",
ImageName: "",
ImageTag: "",
},
},
},
Vulnerabilities: []string{"CVE-2023-42366", "CVE-2023-42365"},
Severities: []string{},
},
},
image: "alpine",
expectedVulnerabilities: []string{},
expectedSeverities: []string{"MEDIUM"},
},
{
policies: []VulnerabilitiesIgnorePolicy{
{
Metadata: Metadata{
Name: "regex-example",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "quay.io",
Organization: "kube*",
ImageName: "kubescape*",
ImageTag: ".*",
},
},
},
Vulnerabilities: []string{},
Severities: []string{"critical"},
},
{
Metadata: Metadata{
Name: "only-for-docker-registry",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
Registry: "docker.io",
ImageTag: "v3*",
},
},
},
Vulnerabilities: []string{"CVE-2023-42366", "CVE-2022-28391"},
Severities: []string{"high"},
},
{
Metadata: Metadata{
Name: "exclude-allowed-hostPath-control",
},
Kind: "VulnerabilitiesIgnorePolicy",
Targets: []Target{
{
DesignatorType: "Attributes",
Attributes: Attributes{
ImageTag: "v3*",
},
},
},
Vulnerabilities: []string{"CVE-2022-30065", "CVE-2022-28391"},
Severities: []string{},
},
},
image: "quay.io/kubescape/kubescape-cli:v3.0.0",
expectedVulnerabilities: []string{"CVE-2022-30065", "CVE-2022-28391"},
expectedSeverities: []string{"CRITICAL"},
},
}
for _, tt := range tests {
t.Run(tt.image, func(t *testing.T) {
vulnerabilities, severities := getUniqueVulnerabilitiesAndSeverities(tt.policies, tt.image)
sort.Strings(tt.expectedVulnerabilities)
sort.Strings(vulnerabilities)
assert.Equal(t, tt.expectedVulnerabilities, vulnerabilities)
assert.Equal(t, tt.expectedSeverities, severities)
})
}
}

View File

@@ -1,7 +1,17 @@
package core
type Kubescape struct{}
import (
"context"
)
func NewKubescape() *Kubescape {
return &Kubescape{}
type Kubescape struct {
Ctx context.Context
}
func (ks *Kubescape) Context() context.Context {
return ks.Ctx
}
func NewKubescape(ctx context.Context) *Kubescape {
return &Kubescape{Ctx: ctx}
}

View File

@@ -1,6 +1,7 @@
package core
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
@@ -8,7 +9,8 @@ import (
// The function should return a non-nil pointer.
func TestNewKubescape_ReturnsNonNilPointer(t *testing.T) {
k := NewKubescape()
ctx := context.TODO()
k := NewKubescape(ctx)
assert.NotNil(t, k)
}
@@ -19,5 +21,6 @@ func TestNewKubescape_DoesNotPanic(t *testing.T) {
t.Errorf("Function panicked: %v", r)
}
}()
NewKubescape()
ctx := context.TODO()
NewKubescape(ctx)
}

View File

@@ -38,16 +38,16 @@ func ListSupportActions() []string {
sort.Strings(commands)
return commands
}
func (ks *Kubescape) List(ctx context.Context, listPolicies *metav1.ListPolicies) error {
func (ks *Kubescape) List(listPolicies *metav1.ListPolicies) error {
if policyListerFunc, ok := listFunc[listPolicies.Target]; ok {
policies, err := policyListerFunc(ctx, listPolicies)
policies, err := policyListerFunc(ks.Context(), listPolicies)
if err != nil {
return err
}
policies = naturalSortPolicies(policies)
if listFormatFunction, ok := listFormatFunc[listPolicies.Format]; ok {
listFormatFunction(ctx, listPolicies.Target, policies)
listFormatFunction(ks.Context(), listPolicies.Target, policies)
} else {
return fmt.Errorf("Invalid format \"%s\", Supported formats: 'pretty-print'/'json' ", listPolicies.Format)
}

View File

@@ -24,7 +24,7 @@ import (
log "github.com/sirupsen/logrus"
)
func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
func (ks *Kubescape) Patch(patchInfo *ksmetav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
// ===================== Scan the image =====================
logger.L().Start(fmt.Sprintf("Scanning image: %s", patchInfo.Image))
@@ -37,7 +37,7 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
Password: patchInfo.Password,
}
// Scan the image
scanResults, err := svc.Scan(ctx, patchInfo.Image, creds)
scanResults, err := svc.Scan(ks.Context(), patchInfo.Image, creds, nil, nil)
if err != nil {
return nil, err
}
@@ -52,7 +52,7 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
fileName := fmt.Sprintf("%s:%s.json", patchInfo.ImageName, patchInfo.ImageTag)
fileName = strings.ReplaceAll(fileName, "/", "-")
writer := printer.GetWriter(ctx, fileName)
writer := printer.GetWriter(ks.Context(), fileName)
if err = pres.Present(writer); err != nil {
return nil, err
@@ -68,7 +68,7 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
disableCopaLogger()
}
if err = copaPatch(ctx, patchInfo.Timeout, patchInfo.BuildkitAddress, patchInfo.Image, fileName, patchedImageName, "", patchInfo.IgnoreError, patchInfo.BuildKitOpts); err != nil {
if err = copaPatch(ks.Context(), patchInfo.Timeout, patchInfo.BuildkitAddress, patchInfo.Image, fileName, patchedImageName, "", patchInfo.IgnoreError, patchInfo.BuildKitOpts); err != nil {
return nil, err
}
@@ -81,7 +81,7 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
logger.L().Start(fmt.Sprintf("Re-scanning image: %s", patchedImageName))
scanResultsPatched, err := svc.Scan(ctx, patchedImageName, creds)
scanResultsPatched, err := svc.Scan(ks.Context(), patchedImageName, creds, nil, nil)
if err != nil {
return nil, err
}
@@ -96,8 +96,8 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
// ===================== Results Handling =====================
scanInfo.SetScanType(cautils.ScanTypeImage)
outputPrinters := GetOutputPrinters(scanInfo, ctx, "")
uiPrinter := GetUIPrinter(ctx, scanInfo, "")
outputPrinters := GetOutputPrinters(scanInfo, ks.Context(), "")
uiPrinter := GetUIPrinter(ks.Context(), scanInfo, "")
resultsHandler := resultshandling.NewResultsHandler(nil, outputPrinters, uiPrinter)
resultsHandler.ImageScanData = []cautils.ImageScanData{
{
@@ -106,7 +106,7 @@ func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, s
},
}
return scanResultsPatched, resultsHandler.HandleResults(ctx)
return scanResultsPatched, resultsHandler.HandleResults(ks.Context())
}
func disableCopaLogger() {

View File

@@ -3,6 +3,7 @@ package core
import (
"context"
"fmt"
"slices"
"github.com/kubescape/backend/pkg/versioncheck"
"github.com/kubescape/go-logger"
@@ -23,7 +24,6 @@ import (
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
"github.com/kubescape/opa-utils/resources"
"go.opentelemetry.io/otel"
"golang.org/x/exp/slices"
"k8s.io/client-go/kubernetes"
)
@@ -121,8 +121,8 @@ func GetOutputPrinters(scanInfo *cautils.ScanInfo, ctx context.Context, clusterN
return outputPrinters
}
func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
ctxInit, spanInit := otel.Tracer("").Start(ctx, "initialization")
func (ks *Kubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
ctxInit, spanInit := otel.Tracer("").Start(ks.Context(), "initialization")
logger.L().Start("Kubescape scanner initializing...")
// ===================== Initialization =====================
@@ -148,7 +148,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
// remove host scanner components
defer func() {
if err := interfaces.hostSensorHandler.TearDown(); err != nil {
logger.L().Ctx(ctx).StopError("Failed to tear down host scanner", helpers.Error(err))
logger.L().Ctx(ks.Context()).StopError("Failed to tear down host scanner", helpers.Error(err))
}
}()
@@ -177,7 +177,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
spanInit.End()
// ========================= opa testing =====================
ctxOpa, spanOpa := otel.Tracer("").Start(ctx, "opa testing")
ctxOpa, spanOpa := otel.Tracer("").Start(ks.Context(), "opa testing")
defer spanOpa.End()
deps := resources.NewRegoDependenciesData(k8sinterface.GetK8sConfig(), interfaces.tenantConfig.GetContextName())
@@ -191,7 +191,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
if scanInfo.PrintAttackTree || isPrioritizationScanType(scanInfo.ScanType) {
_, spanPrioritization := otel.Tracer("").Start(ctxOpa, "prioritization")
if priotizationHandler, err := resourcesprioritization.NewResourcesPrioritizationHandler(ctxOpa, scanInfo.Getters.AttackTracksGetter, scanInfo.PrintAttackTree); err != nil {
logger.L().Ctx(ctx).Warning("failed to get attack tracks, this may affect the scanning results", helpers.Error(err))
logger.L().Ctx(ks.Context()).Warning("failed to get attack tracks, this may affect the scanning results", helpers.Error(err))
} else if err := priotizationHandler.PrioritizeResources(scanData); err != nil {
return resultsHandling, fmt.Errorf("%w", err)
}
@@ -202,7 +202,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
}
if scanInfo.ScanImages {
scanImages(scanInfo.ScanType, scanData, ctx, resultsHandling)
scanImages(scanInfo.ScanType, scanData, ks.Context(), resultsHandling)
}
// ========================= results handling =====================
resultsHandling.SetData(scanData)
@@ -257,7 +257,7 @@ func scanImages(scanType cautils.ScanTypes, scanData *cautils.OPASessionObj, ctx
func scanSingleImage(ctx context.Context, img string, svc imagescan.Service, resultsHandling *resultshandling.ResultsHandler) error {
scanResults, err := svc.Scan(ctx, img, imagescan.RegistryCredentials{})
scanResults, err := svc.Scan(ctx, img, imagescan.RegistryCredentials{}, nil, nil)
if err != nil {
return err
}

View File

@@ -0,0 +1,67 @@
[
{
"metadata": {
"name": "alpine-exceptions"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
"imageName": "alpine*"
}
}
],
"severities": [
"medium"
]
},
{
"metadata": {
"name": "nginx-exceptions"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
"imageName": "nginx*"
}
}
],
"vulnerabilities": [
"invalid-cve",
"CVE-2023-45853",
"CVE-2023-49463"
],
"severities": [
"critical",
"medium",
"invalid-severity"
]
},
{
"metadata": {
"name": "applicable-only-to-quay-registry-images"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
"registry": "quay.io"
}
}
],
"vulnerabilities": [
"CVE-2023-42365"
],
"severities": [
"critical",
"medium",
"high",
"low"
]
}
]

View File

@@ -0,0 +1 @@
[]

78
core/core/testdata/exceptions.json vendored Normal file
View File

@@ -0,0 +1,78 @@
[
{
"metadata": {
"name": "medium-severity-vulnerabilites-exceptions"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
"Registry": "docker.io",
"Organization": "",
"ImageName": ""
}
}
],
"vulnerabilities": [
],
"severities": [
"medium"
]
},
{
"metadata": {
"name": "exclude-allowed-hostPath-control"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
}
}
],
"vulnerabilities": [
"CVE-2023-42366",
"CVE-2023-42365"
],
"severities": [
"critical",
"low"
]
},
{
"metadata": {
"name": "regex-example"
},
"kind": "VulnerabilitiesIgnorePolicy",
"targets": [
{
"designatorType": "Attributes",
"attributes": {
"Registry": "quay.*",
"Organization": "kube*",
"ImageName": "kubescape*",
"ImageTag": "v2*"
}
},
{
"designatorType": "Attributes",
"attributes": {
"Registry": "docker.io",
"Organization": ".*",
"ImageName": "kube*",
"ImageTag": "v3*"
}
}
],
"vulnerabilities": [
"CVE-2023-6879",
"CVE-2023-44487"
],
"severities": [
"critical",
"low"
]
}
]

View File

@@ -1,7 +1,8 @@
package v1
type ImageScanInfo struct {
Username string
Password string
Image string
Username string
Password string
Image string
Exceptions string
}

View File

@@ -10,23 +10,25 @@ import (
)
type IKubescape interface {
Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) // TODO - use scanInfo from v1
Context() context.Context
Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) // TODO - use scanInfo from v1
// policies
List(ctx context.Context, listPolicies *metav1.ListPolicies) error // TODO - return list response
Download(ctx context.Context, downloadInfo *metav1.DownloadInfo) error // TODO - return downloaded policies
List(listPolicies *metav1.ListPolicies) error // TODO - return list response
Download(downloadInfo *metav1.DownloadInfo) error // TODO - return downloaded policies
// config
SetCachedConfig(setConfig *metav1.SetConfig) error
ViewCachedConfig(viewConfig *metav1.ViewConfig) error
DeleteCachedConfig(ctx context.Context, deleteConfig *metav1.DeleteConfig) error
DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error
// fix
Fix(ctx context.Context, fixInfo *metav1.FixInfo) error
Fix(fixInfo *metav1.FixInfo) error
// patch
Patch(ctx context.Context, patchInfo *metav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error)
Patch(patchInfo *metav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error)
// scan image
ScanImage(ctx context.Context, imgScanInfo *metav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error)
ScanImage(imgScanInfo *metav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error)
}

View File

@@ -11,15 +11,19 @@ import (
type MockIKubescape struct{}
func (m *MockIKubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
func (m *MockIKubescape) Context() context.Context {
return context.TODO()
}
func (m *MockIKubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
return nil, nil
}
func (m *MockIKubescape) List(ctx context.Context, listPolicies *metav1.ListPolicies) error {
func (m *MockIKubescape) List(listPolicies *metav1.ListPolicies) error {
return nil
}
func (m *MockIKubescape) Download(ctx context.Context, downloadInfo *metav1.DownloadInfo) error {
func (m *MockIKubescape) Download(downloadInfo *metav1.DownloadInfo) error {
return nil
}
@@ -31,18 +35,18 @@ func (m *MockIKubescape) ViewCachedConfig(viewConfig *metav1.ViewConfig) error {
return nil
}
func (m *MockIKubescape) DeleteCachedConfig(ctx context.Context, deleteConfig *metav1.DeleteConfig) error {
func (m *MockIKubescape) DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error {
return nil
}
func (m *MockIKubescape) Fix(ctx context.Context, fixInfo *metav1.FixInfo) error {
func (m *MockIKubescape) Fix(fixInfo *metav1.FixInfo) error {
return nil
}
func (m *MockIKubescape) Patch(ctx context.Context, patchInfo *metav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
func (m *MockIKubescape) Patch(patchInfo *metav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
return nil, nil
}
func (m *MockIKubescape) ScanImage(ctx context.Context, imgScanInfo *metav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
func (m *MockIKubescape) ScanImage(imgScanInfo *metav1.ImageScanInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
return nil, nil
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v3/core/cautils"
"github.com/kubescape/opa-utils/objectsenvelopes/hostsensor"
)
@@ -27,18 +28,19 @@ type workerPool struct {
func newWorkerPool() workerPool {
wp := workerPool{}
wp.noOfWorkers = noOfWorkers
wp.noOfWorkers, _ = cautils.ParseIntEnvVar("KUBESCAPE_WORKERS", noOfWorkers)
wp.init()
return wp
}
func (wp *workerPool) init(noOfPods ...int) {
if len(noOfPods) > 0 && noOfPods[0] < noOfWorkers {
if len(noOfPods) > 0 && noOfPods[0] < wp.noOfWorkers {
wp.noOfWorkers = noOfPods[0]
}
logger.L().Debug("Initializing worker pool", helpers.Int("noOfWorkers", wp.noOfWorkers))
// init the channels
wp.jobs = make(chan job, noOfWorkers)
wp.results = make(chan hostsensor.HostSensorDataEnvelope, noOfWorkers)
wp.jobs = make(chan job, wp.noOfWorkers)
wp.results = make(chan hostsensor.HostSensorDataEnvelope, wp.noOfWorkers)
wp.done = make(chan bool)
}
@@ -57,7 +59,7 @@ func (wp *workerPool) hostSensorWorker(ctx context.Context, hsh *HostSensorHandl
}
func (wp *workerPool) createWorkerPool(ctx context.Context, hsh *HostSensorHandler, wg *sync.WaitGroup, log *LogsMap) {
for i := 0; i < noOfWorkers; i++ {
for i := 0; i < wp.noOfWorkers; i++ {
wg.Add(1)
go wp.hostSensorWorker(ctx, hsh, wg, log)
}

View File

@@ -3,6 +3,7 @@ package opaprocessor
import (
"context"
"fmt"
"slices"
"strings"
"sync"
@@ -23,7 +24,6 @@ import (
"github.com/open-policy-agent/opa/storage"
opaprint "github.com/open-policy-agent/opa/topdown/print"
"go.opentelemetry.io/otel"
"golang.org/x/exp/slices"
)
const ScoreConfigPath = "/resources/config"

View File

@@ -2,6 +2,7 @@ package opaprocessor
import (
"fmt"
"slices"
"strings"
"github.com/kubescape/go-logger"
@@ -14,7 +15,6 @@ import (
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/topdown/builtins"
"github.com/open-policy-agent/opa/types"
"golang.org/x/exp/slices"
)
// convertFrameworksToPolicies convert list of frameworks to list of policies

View File

@@ -3,78 +3,39 @@ package printer
import (
"fmt"
"sort"
"strings"
"github.com/jwalton/gchalk"
"github.com/kubescape/kubescape/v3/core/cautils"
"github.com/kubescape/opa-utils/reporthandling/apis"
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
"github.com/olekukonko/tablewriter"
)
const (
columnSeverity = iota
columnRef = iota
columnName = iota
columnCounterFailed = iota
columnCounterAll = iota
columnComplianceScore = iota
_rowLen = iota
controlNameMaxLength = 70
)
const controlNameMaxLength = 70
func generateRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars, verbose bool) []string {
row := make([]string, _rowLen)
// ignore passed results
if !verbose && (controlSummary.GetStatus().IsPassed()) {
return []string{}
}
row[columnSeverity] = getSeverityColumn(controlSummary)
if len(controlSummary.GetName()) > controlNameMaxLength {
row[columnName] = controlSummary.GetName()[:controlNameMaxLength] + "..."
} else {
row[columnName] = controlSummary.GetName()
}
row[columnCounterFailed] = fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())
row[columnCounterAll] = fmt.Sprintf("%d", controlSummary.NumberOfResources().All())
row[columnComplianceScore] = getComplianceScoreColumn(controlSummary, infoToPrintInfo)
if row[columnComplianceScore] == "-1%" {
row[columnComplianceScore] = "N/A"
}
return row
type TableRow struct {
ref string
name string
counterFailed string
counterAll string
severity string
complianceScore string
}
func shortFormatRow(dataRows [][]string) [][]string {
rows := [][]string{}
for _, dataRow := range dataRows {
rows = append(rows, []string{fmt.Sprintf("Severity"+strings.Repeat(" ", 11)+": %+v\nControl Name"+strings.Repeat(" ", 7)+": %+v\nFailed Resources"+strings.Repeat(" ", 3)+": %+v\nAll Resources"+strings.Repeat(" ", 6)+": %+v\n%% Compliance-Score"+strings.Repeat(" ", 1)+": %+v", dataRow[columnSeverity], dataRow[columnName], dataRow[columnCounterFailed], dataRow[columnCounterAll], dataRow[columnComplianceScore])})
// generateTableRow is responsible for generating the row that will be printed in the table
func generateTableRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars) *TableRow {
tableRow := &TableRow{
ref: controlSummary.GetID(),
name: controlSummary.GetName(),
counterFailed: fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed()),
counterAll: fmt.Sprintf("%d", controlSummary.NumberOfResources().All()),
severity: apis.ControlSeverityToString(controlSummary.GetScoreFactor()),
complianceScore: getComplianceScoreColumn(controlSummary, infoToPrintInfo),
}
return rows
}
func generateRowPdf(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars, verbose bool) []string {
row := make([]string, _rowLen)
// ignore passed results
if !verbose && (controlSummary.GetStatus().IsPassed()) {
return []string{}
}
row[columnSeverity] = apis.ControlSeverityToString(controlSummary.GetScoreFactor())
row[columnRef] = controlSummary.GetID()
if len(controlSummary.GetName()) > controlNameMaxLength {
row[columnName] = controlSummary.GetName()[:controlNameMaxLength] + "..."
} else {
row[columnName] = controlSummary.GetName()
tableRow.name = controlSummary.GetName()[:controlNameMaxLength] + "..."
}
row[columnCounterFailed] = fmt.Sprintf("%d", controlSummary.NumberOfResources().Failed())
row[columnCounterAll] = fmt.Sprintf("%d", controlSummary.NumberOfResources().All())
row[columnComplianceScore] = getComplianceScoreColumn(controlSummary, infoToPrintInfo)
return row
return tableRow
}
func getInfoColumn(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars) string {
@@ -90,7 +51,12 @@ func getComplianceScoreColumn(controlSummary reportsummary.IControlSummary, info
if controlSummary.GetStatus().IsSkipped() {
return fmt.Sprintf("%s %s", "Action Required", getInfoColumn(controlSummary, infoToPrintInfo))
}
return fmt.Sprintf("%d", cautils.Float32ToInt(controlSummary.GetComplianceScore())) + "%"
if compliance := cautils.Float32ToInt(controlSummary.GetComplianceScore()); compliance < 0 {
return "N/A"
} else {
return fmt.Sprintf("%d", cautils.Float32ToInt(controlSummary.GetComplianceScore())) + "%"
}
}
func getSeverityColumn(controlSummary reportsummary.IControlSummary) string {
@@ -124,45 +90,3 @@ func getSortedControlsIDs(controls reportsummary.ControlSummaries) [][]string {
}
return controlIDs
}
/* unused for now
func getSortedControlsNames(controls reportsummary.ControlSummaries) [][]string {
controlNames := make([][]string, 5)
for k := range controls {
c := controls[k]
i := apis.ControlSeverityToInt(c.GetScoreFactor())
controlNames[i] = append(controlNames[i], c.GetName())
}
for i := range controlNames {
sort.Strings(controlNames[i])
}
return controlNames
}
*/
func getControlTableHeaders(short bool) []string {
var headers []string
if short {
headers = make([]string, 1)
headers[0] = "Controls"
} else {
headers = make([]string, _rowLen)
headers[columnRef] = "Control reference"
headers[columnName] = "Control name"
headers[columnCounterFailed] = "Failed resources"
headers[columnCounterAll] = "All resources"
headers[columnSeverity] = "Severity"
headers[columnComplianceScore] = "Compliance score"
}
return headers
}
func getColumnsAlignments() []int {
alignments := make([]int, _rowLen)
alignments[columnName] = tablewriter.ALIGN_LEFT
alignments[columnCounterFailed] = tablewriter.ALIGN_CENTER
alignments[columnCounterAll] = tablewriter.ALIGN_CENTER
alignments[columnSeverity] = tablewriter.ALIGN_LEFT
alignments[columnComplianceScore] = tablewriter.ALIGN_CENTER
return alignments
}

View File

@@ -23,45 +23,43 @@ func Test_generateRowPdf(t *testing.T) {
infoToPrintInfoMap := mapInfoToPrintInfo(mockSummary.Controls)
sortedControlIDs := getSortedControlsIDs(mockSummary.Controls)
var results [][]string
var rows []TableRow
for i := len(sortedControlIDs) - 1; i >= 0; i-- {
for _, c := range sortedControlIDs[i] {
result := generateRowPdf(mockSummary.Controls.GetControl(reportsummary.EControlCriteriaID, c), infoToPrintInfoMap, true)
if len(result) > 0 {
results = append(results, result)
}
row := *generateTableRow(mockSummary.Controls.GetControl(reportsummary.EControlCriteriaID, c), infoToPrintInfoMap)
rows = append(rows, row)
}
}
for _, c := range results {
for _, row := range rows {
//validating severity column
if c[0] != "Low" && c[0] != "Medium" && c[0] != "High" && c[0] != "Critical" {
t.Errorf("got %s, want either of these: %s", c[0], "Low, Medium, High, Critical")
if row.severity != "Low" && row.severity != "Medium" && row.severity != "High" && row.severity != "Critical" {
t.Errorf("got %s, want either of these: %s", row.severity, "Low, Medium, High, Critical")
}
// Validating length of control ID
if len(c[1]) > 6 {
t.Errorf("got %s, want %s", c[1], "less than 7 characters")
if len(row.ref) > 6 {
t.Errorf("got %s, want %s", row.ref, "less than 7 characters")
}
// Validating length of control name
if len(c[2]) > controlNameMaxLength {
t.Errorf("got %s, want %s", c[1], fmt.Sprintf("less than %d characters", controlNameMaxLength))
if len(row.name) > controlNameMaxLength {
t.Errorf("got %s, want %s", row.name, fmt.Sprintf("less than %d characters", controlNameMaxLength))
}
// Validating numeric fields
_, err := strconv.Atoi(c[3])
_, err := strconv.Atoi(row.counterFailed)
if err != nil {
t.Errorf("got %s, want an integer %s", c[2], err)
t.Errorf("got %s, want an integer %s", row.counterFailed, err)
}
_, err = strconv.Atoi(c[4])
_, err = strconv.Atoi(row.counterAll)
if err != nil {
t.Errorf("got %s, want an integer %s", c[3], err)
t.Errorf("got %s, want an integer %s", row.counterAll, err)
}
assert.NotEmpty(t, c[5], "expected a non-empty string")
assert.NotEmpty(t, row.complianceScore, "expected a non-empty string")
}

View File

@@ -3,21 +3,18 @@ package printer
import (
"context"
_ "embed"
b64 "encoding/base64"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/johnfercher/maroto/pkg/color"
"github.com/johnfercher/maroto/pkg/consts"
"github.com/johnfercher/maroto/pkg/pdf"
"github.com/johnfercher/maroto/pkg/props"
"github.com/johnfercher/maroto/v2/pkg/props"
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v3/core/cautils"
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/pdf"
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils"
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
)
@@ -27,11 +24,6 @@ const (
pdfOutputExt = ".pdf"
)
var (
//go:embed pdf/logo.png
kubescapeLogo []byte
)
var _ printer.IPrinter = &PdfPrinter{}
type PdfPrinter struct {
@@ -66,219 +58,79 @@ func (pp *PdfPrinter) Score(score float32) {
fmt.Fprintf(os.Stderr, "\nOverall compliance-score (100- Excellent, 0- All failed): %d\n", cautils.Float32ToInt(score))
}
func (pp *PdfPrinter) printInfo(m pdf.Maroto, summaryDetails *reportsummary.SummaryDetails, infoMap []infoStars) {
emptyRowCounter := 1
for i := range infoMap {
if infoMap[i].info != "" {
m.Row(5, func() {
m.Col(12, func() {
m.Text(fmt.Sprintf("%v %v", infoMap[i].stars, infoMap[i].info), props.Text{
Style: consts.Bold,
Align: consts.Left,
Size: 8,
Extrapolate: false,
Color: color.Color{
Red: 0,
Green: 0,
Blue: 255,
},
})
})
})
if emptyRowCounter < len(infoMap) {
m.Row(2.5, func() {})
emptyRowCounter++
}
}
}
}
func (pp *PdfPrinter) PrintNextSteps() {
}
// ActionPrint is responsible for generating a report in pdf format
func (pp *PdfPrinter) ActionPrint(ctx context.Context, opaSessionObj *cautils.OPASessionObj, imageScanData []cautils.ImageScanData) {
if opaSessionObj == nil {
logger.L().Ctx(ctx).Error("failed to print results, missing data")
return
}
sortedControlIDs := getSortedControlsIDs(opaSessionObj.Report.SummaryDetails.Controls)
infoToPrintInfo := mapInfoToPrintInfo(opaSessionObj.Report.SummaryDetails.Controls)
m := pdf.NewMaroto(consts.Portrait, consts.A4)
pp.printHeader(m)
pp.printFramework(m, opaSessionObj.Report.SummaryDetails.ListFrameworks())
pp.printTable(m, &opaSessionObj.Report.SummaryDetails, sortedControlIDs)
pp.printFinalResult(m, &opaSessionObj.Report.SummaryDetails)
pp.printInfo(m, &opaSessionObj.Report.SummaryDetails, infoToPrintInfo)
// Extrat output buffer.
outBuff, err := m.Output()
outBuff, err := pp.generatePdf(&opaSessionObj.Report.SummaryDetails)
if err != nil {
logger.L().Ctx(ctx).Error("failed to generate pdf format", helpers.Error(err))
return
}
if _, err := pp.writer.Write(outBuff.Bytes()); err != nil {
if _, err := pp.writer.Write(outBuff); err != nil {
logger.L().Ctx(ctx).Error("failed to write results", helpers.Error(err))
return
}
printer.LogOutputFile(pp.writer.Name())
}
// printHeader prints the Kubescape logo and report date
func (pp *PdfPrinter) printHeader(m pdf.Maroto) {
// Retrieve current time (we need it for the report timestamp).
t := time.Now()
// Enconde PNG into Base64 to embed it into the pdf.
kubescapeLogoEnc := b64.StdEncoding.EncodeToString(kubescapeLogo)
func (pp *PdfPrinter) generatePdf(summaryDetails *reportsummary.SummaryDetails) ([]byte, error) {
sortedControlIDs := getSortedControlsIDs(summaryDetails.Controls)
infoToPrintInfo := mapInfoToPrintInfo(summaryDetails.Controls)
m.SetPageMargins(10, 15, 10)
m.Row(40, func() {
//m.Text(fmt.Sprintf("Security Assessment"), props.Text{
// Align: consts.Center,
// Size: 24,
// Family: consts.Arial,
// Style: consts.Bold,
//})
_ = m.Base64Image(kubescapeLogoEnc, consts.Png, props.Rect{
Center: true,
Percent: 100,
})
})
m.Row(6, func() {
m.Text(fmt.Sprintf("Report date: %d-%02d-%02dT%02d:%02d:%02d",
t.Year(),
t.Month(),
t.Day(),
t.Hour(),
t.Minute(),
t.Second()), props.Text{
Align: consts.Left,
Size: 6.0,
Style: consts.Bold,
Family: consts.Arial,
})
})
m.Line(1)
template := pdf.NewReportTemplate()
template.GenerateHeader(utils.FrameworksScoresToString(summaryDetails.ListFrameworks()), time.Now().Format(time.DateTime))
err := template.GenerateTable(pp.getTableObjects(summaryDetails, sortedControlIDs),
summaryDetails.NumberOfResources().Failed(), summaryDetails.NumberOfResources().All(), summaryDetails.ComplianceScore)
if err != nil {
return nil, err
}
template.GenerateInfoRows(pp.getFormattedInformation(infoToPrintInfo))
return template.GetPdf()
}
// printFramework prints the PDF frameworks after the PDF header
func (pp *PdfPrinter) printFramework(m pdf.Maroto, frameworks []reportsummary.IFrameworkSummary) {
m.Row(10, func() {
m.Text(utils.FrameworksScoresToString(frameworks), props.Text{
Align: consts.Center,
Size: 8,
Family: consts.Arial,
Style: consts.Bold,
})
})
}
// printTable creates the PDF table
func (pp *PdfPrinter) printTable(m pdf.Maroto, summaryDetails *reportsummary.SummaryDetails, sortedControlIDs [][]string) {
headers := getControlTableHeaders(false)
infoToPrintInfoMap := mapInfoToPrintInfo(summaryDetails.Controls)
var controls [][]string
for i := len(sortedControlIDs) - 1; i >= 0; i-- {
for _, c := range sortedControlIDs[i] {
row := generateRowPdf(summaryDetails.Controls.GetControl(reportsummary.EControlCriteriaID, c), infoToPrintInfoMap, true)
if len(row) > 0 {
controls = append(controls, row)
}
func (pp *PdfPrinter) getFormattedInformation(infoMap []infoStars) []string {
rows := make([]string, 0, len(infoMap))
for i := range infoMap {
if infoMap[i].info != "" {
rows = append(rows, fmt.Sprintf("%v %v", infoMap[i].stars, infoMap[i].info))
}
}
size := 6.0
gridSize := []uint{1, 1, 6, 1, 1, 2}
m.TableList(headers, controls, props.TableList{
HeaderProp: props.TableListContent{
Family: consts.Arial,
Style: consts.Bold,
Size: size,
GridSizes: gridSize,
},
ContentProp: props.TableListContent{
Family: consts.Courier,
Style: consts.Normal,
Size: size,
GridSizes: gridSize,
CellTextColorChangerColumnIndex: 0,
CellTextColorChangerFunc: func(cellValue string) color.Color {
if cellValue == "Critical" {
return color.Color{
Red: 255,
Green: 0,
Blue: 0,
}
} else if cellValue == "High" {
return color.Color{
Red: 0,
Green: 0,
Blue: 255,
}
} else if cellValue == "Medium" {
return color.Color{
Red: 252,
Green: 186,
Blue: 3,
}
}
return color.NewBlack()
},
},
Align: consts.Left,
AlternatedBackground: &color.Color{
Red: 224,
Green: 224,
Blue: 224,
},
HeaderContentSpace: 2.0,
Line: false,
})
m.Line(1)
m.Row(2, func() {})
return rows
}
// printFinalResult adds the final results
func (pp *PdfPrinter) printFinalResult(m pdf.Maroto, summaryDetails *reportsummary.SummaryDetails) {
m.Row(_rowLen, func() {
m.Col(1, func() {
})
m.Col(5, func() {
m.Text("Resource summary", props.Text{
Align: consts.Left,
Size: 8.0,
Style: consts.Bold,
Family: consts.Arial,
})
})
m.Col(2, func() {
m.Text(fmt.Sprintf("%d", summaryDetails.NumberOfResources().Failed()), props.Text{
Align: consts.Left,
Size: 8.0,
Style: consts.Bold,
Family: consts.Arial,
})
})
m.Col(2, func() {
m.Text(fmt.Sprintf("%d", summaryDetails.NumberOfResources().All()), props.Text{
Align: consts.Left,
Size: 8.0,
Style: consts.Bold,
Family: consts.Arial,
})
})
m.Col(2, func() {
m.Text(fmt.Sprintf("%.2f%s", summaryDetails.ComplianceScore, "%"), props.Text{
Align: consts.Left,
Size: 8.0,
Style: consts.Bold,
Family: consts.Arial,
})
})
})
// getTableData is responsible for getting the table data in a standardized format
func (pp *PdfPrinter) getTableObjects(summaryDetails *reportsummary.SummaryDetails, sortedControlIDs [][]string) *[]pdf.TableObject {
infoToPrintInfoMap := mapInfoToPrintInfo(summaryDetails.Controls)
var controls []pdf.TableObject
for i := len(sortedControlIDs) - 1; i >= 0; i-- {
for _, c := range sortedControlIDs[i] {
row := generateTableRow(summaryDetails.Controls.GetControl(reportsummary.EControlCriteriaID, c), infoToPrintInfoMap)
controls = append(controls, *pdf.NewTableRow(
row.ref, row.name, row.counterFailed, row.counterAll, row.severity, row.complianceScore, getSeverityColor,
))
}
}
return &controls
}
func getSeverityColor(severity string) *props.Color {
if severity == "Critical" {
return &props.Color{Red: 255, Green: 0, Blue: 0}
} else if severity == "High" {
return &props.Color{Red: 0, Green: 0, Blue: 255}
} else if severity == "Medium" {
return &props.Color{Red: 252, Green: 186, Blue: 3}
}
return &props.BlackColor
}

View File

@@ -0,0 +1 @@
test_path: "testStructure/"

View File

@@ -0,0 +1,195 @@
package pdf
import (
_ "embed"
"fmt"
"github.com/johnfercher/go-tree/node"
"github.com/johnfercher/maroto/v2"
"github.com/johnfercher/maroto/v2/pkg/components/image"
"github.com/johnfercher/maroto/v2/pkg/components/line"
"github.com/johnfercher/maroto/v2/pkg/components/list"
"github.com/johnfercher/maroto/v2/pkg/components/row"
"github.com/johnfercher/maroto/v2/pkg/components/text"
"github.com/johnfercher/maroto/v2/pkg/config"
"github.com/johnfercher/maroto/v2/pkg/consts/align"
"github.com/johnfercher/maroto/v2/pkg/consts/extension"
"github.com/johnfercher/maroto/v2/pkg/consts/fontfamily"
"github.com/johnfercher/maroto/v2/pkg/consts/fontstyle"
"github.com/johnfercher/maroto/v2/pkg/consts/orientation"
"github.com/johnfercher/maroto/v2/pkg/consts/pagesize"
"github.com/johnfercher/maroto/v2/pkg/core"
"github.com/johnfercher/maroto/v2/pkg/props"
)
var (
//go:embed logo.png
kubescapeLogo []byte
)
type getTextColorFunc func(severity string) *props.Color
type Template struct {
maroto core.Maroto
}
// New Report Template is responsible for creating an object that generates a report with the submitted data
func NewReportTemplate() *Template {
return &Template{
maroto: maroto.New(
config.NewBuilder().
WithPageSize(pagesize.A4).
WithOrientation(orientation.Vertical).
WithLeftMargin(10).
WithTopMargin(15).
WithRightMargin(10).
Build()),
}
}
// GetPdf is responsible for generating the pdf and returning the file's bytes
func (t *Template) GetPdf() ([]byte, error) {
doc, err := t.maroto.Generate()
if err != nil {
return nil, err
}
return doc.GetBytes(), nil
}
// printHeader prints the Kubescape logo, report date and framework
func (t *Template) GenerateHeader(scoreOfScannedFrameworks, reportDate string) *Template {
t.maroto.AddRow(40, image.NewFromBytesCol(12, kubescapeLogo, extension.Png, props.Rect{
Center: true,
Percent: 100,
}))
t.maroto.AddRow(6, text.NewCol(12, fmt.Sprintf("Report date: %s", reportDate),
props.Text{
Align: align.Left,
Size: 6.0,
Style: fontstyle.Bold,
Family: fontfamily.Arial,
}))
t.maroto.AddAutoRow(line.NewCol(12, props.Line{Thickness: 0.3, SizePercent: 100}))
t.maroto.AddRow(10, text.NewCol(12, scoreOfScannedFrameworks, props.Text{
Align: align.Center,
Size: 8,
Family: fontfamily.Arial,
Style: fontstyle.Bold,
}))
return t
}
// GenerateTable is responsible for adding data in table format to the pdf
func (t *Template) GenerateTable(tableRows *[]TableObject, totalFailed, total int, score float32) error {
rows, err := list.Build[TableObject](*tableRows)
if err != nil {
return err
}
t.maroto.AddRows(rows...)
t.maroto.AddRows(
line.NewAutoRow(props.Line{Thickness: 0.3, SizePercent: 100}),
row.New(2),
)
t.generateTableTableResult(totalFailed, total, score)
return nil
}
// GenerateInfoRows is responsible for adding the information in pdf
func (t *Template) GenerateInfoRows(rows []string) *Template {
for _, row := range rows {
t.maroto.AddAutoRow(text.NewCol(12, row, props.Text{
Style: fontstyle.Bold,
Align: align.Left,
Top: 2.5,
Size: 8,
Color: &props.Color{
Red: 0,
Green: 0,
Blue: 255,
},
}))
}
return t
}
func (t *Template) generateTableTableResult(totalFailed, total int, score float32) {
defaultProps := props.Text{
Align: align.Left,
Size: 8,
Style: fontstyle.Bold,
Family: fontfamily.Arial,
}
t.maroto.AddRow(10,
text.NewCol(5, "Resource summary", defaultProps),
text.NewCol(2, fmt.Sprintf("%d", totalFailed), defaultProps),
text.NewCol(2, fmt.Sprintf("%d", total), defaultProps),
text.NewCol(2, fmt.Sprintf("%.2f%s", score, "%"), defaultProps),
)
}
func (t *Template) GetStructure() *node.Node[core.Structure] {
return t.maroto.GetStructure()
}
// TableObject is responsible for mapping the table data, it will be sent to Maroto and will make it possible to generate the table
type TableObject struct {
ref string
name string
counterFailed string
counterAll string
severity string
complianceScore string
getTextColor getTextColorFunc
}
func NewTableRow(ref, name, counterFailed, counterAll, severity, score string, getTextColor getTextColorFunc) *TableObject {
return &TableObject{
ref: ref,
name: name,
counterFailed: counterFailed,
counterAll: counterAll,
severity: severity,
complianceScore: score,
getTextColor: getTextColor,
}
}
func (t TableObject) GetHeader() core.Row {
return row.New(10).Add(
text.NewCol(1, "Severity", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
text.NewCol(1, "Control reference", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
text.NewCol(6, "Control name", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
text.NewCol(1, "Failed resources", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
text.NewCol(1, "All resources", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
text.NewCol(2, "Compliance score", props.Text{Size: 6, Family: fontfamily.Arial, Style: fontstyle.Bold}),
)
}
func (t TableObject) GetContent(i int) core.Row {
r := row.New(3).Add(
text.NewCol(1, t.severity, props.Text{Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6, Color: t.getTextColor(t.severity)}),
text.NewCol(1, t.ref, props.Text{Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6, Color: &props.Color{}}),
text.NewCol(6, t.name, props.Text{Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6}),
text.NewCol(1, t.counterFailed, props.Text{Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6}),
text.NewCol(1, t.counterAll, props.Text{Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6}),
text.NewCol(2, t.complianceScore, props.Text{VerticalPadding: 1, Style: fontstyle.Normal, Family: fontfamily.Courier, Size: 6}),
)
if i%2 == 0 {
r.WithStyle(&props.Cell{
BackgroundColor: &props.Color{
Red: 224,
Green: 224,
Blue: 224,
},
})
}
return r
}

View File

@@ -0,0 +1,58 @@
package pdf_test
import (
"testing"
"github.com/johnfercher/maroto/v2/pkg/props"
"github.com/johnfercher/maroto/v2/pkg/test"
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/pdf"
"github.com/stretchr/testify/assert"
)
func TestGetPdf(t *testing.T) {
t.Run("when GetPdf is called, it should return pdf bytes", func(t *testing.T) {
template := pdf.NewReportTemplate().GenerateHeader("Framework test 1, Framework test 2", "2024-04-01 20:31:00")
bytes, err := template.GetPdf()
assert.Nil(t, err)
assert.NotNil(t, bytes)
})
}
func TestGenerateHeader(t *testing.T) {
t.Run("when generateHeader is called, it should set the header in the pdf", func(t *testing.T) {
template := pdf.NewReportTemplate().GenerateHeader("Framework test 1, Framework test 2", "2024-04-01 20:31:00")
node := template.GetStructure()
assert.NotNil(t, node)
test.New(t).Assert(node).Equals("headerTemplate.json")
})
}
func TestGenerateTable(t *testing.T) {
t.Run("when generateTable is called, it should set the table in the pdf", func(t *testing.T) {
TableObjectMock := pdf.NewTableRow(
"ref", "name", "failed", "all", "severity", "score",
func(severity string) *props.Color { return &props.Color{Red: 0, Blue: 0, Green: 0} },
)
template := pdf.NewReportTemplate()
err := template.GenerateTable(&[]pdf.TableObject{*TableObjectMock}, 100, 10, 10.0)
assert.Nil(t, err)
test.New(t).Assert(template.GetStructure()).Equals("tableTemplate.json")
})
}
func TestGenerateInfoRows(t *testing.T) {
t.Run("when generateInfoRows is called, it should set the info rows in the pdf", func(t *testing.T) {
template := pdf.NewReportTemplate().GenerateInfoRows([]string{"row info 1", "row info 2", "row info 3"})
assert.NotNil(t, template)
test.New(t).Assert(template.GetStructure()).Equals("infoTemplate.json")
})
}

View File

@@ -0,0 +1,127 @@
{
"type": "maroto",
"details": {
"chunk_workers": 1,
"config_margin_bottom": 20.0025,
"config_margin_left": 10,
"config_margin_right": 10,
"config_margin_top": 15,
"config_max_grid_sum": 12,
"config_provider_type": "gofpdf",
"generation_mode": "sequential",
"maroto_dimension_height": 297,
"maroto_dimension_width": 210,
"prop_font_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 10
},
"nodes": [
{
"type": "page",
"nodes": [
{
"value": 40,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "iVBORw0KGgoAAA==",
"type": "bytesImage",
"details": {
"bytes_size": 54270,
"extension": "png",
"prop_center": true,
"prop_percent": 100
}
}
]
}
]
},
{
"value": 6,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "Report date: 2024-04-01 20:31:00",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
}
]
},
{
"value": 0.3,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"type": "line",
"details": {
"prop_offset_percent": 5,
"prop_orientation": "horizontal",
"prop_size_percent": 100,
"prop_style": "solid",
"prop_thickness": 0.3
}
}
]
}
]
},
{
"value": 10,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "Framework test 1, Framework test 2",
"type": "text",
"details": {
"prop_align": "C",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B"
}
}
]
}
]
},
{
"value": 205.6975,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col"
}
]
}
]
}
]
}

View File

@@ -0,0 +1,110 @@
{
"type": "maroto",
"details": {
"chunk_workers": 1,
"config_margin_bottom": 20.0025,
"config_margin_left": 10,
"config_margin_right": 10,
"config_margin_top": 15,
"config_max_grid_sum": 12,
"config_provider_type": "gofpdf",
"generation_mode": "sequential",
"maroto_dimension_height": 297,
"maroto_dimension_width": 210,
"prop_font_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 10
},
"nodes": [
{
"type": "page",
"nodes": [
{
"value": 5.322222222222223,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "row info 1",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 255)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B",
"prop_top": 2.5
}
}
]
}
]
},
{
"value": 5.322222222222223,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "row info 2",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 255)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B",
"prop_top": 2.5
}
}
]
}
]
},
{
"value": 5.322222222222223,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col",
"nodes": [
{
"value": "row info 3",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 255)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B",
"prop_top": 2.5
}
}
]
}
]
},
{
"value": 246.03083333333333,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col"
}
]
}
]
}
]
}

View File

@@ -0,0 +1,377 @@
{
"type": "maroto",
"details": {
"chunk_workers": 1,
"config_margin_bottom": 20.0025,
"config_margin_left": 10,
"config_margin_right": 10,
"config_margin_top": 15,
"config_max_grid_sum": 12,
"config_provider_type": "gofpdf",
"generation_mode": "sequential",
"maroto_dimension_height": 297,
"maroto_dimension_width": 210,
"prop_font_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 10
},
"nodes": [
{
"type": "page",
"nodes": [
{
"value": 10,
"type": "row",
"nodes": [
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "Severity",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "Control reference",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
},
{
"value": 6,
"type": "col",
"nodes": [
{
"value": "Control name",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "Failed resources",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "All resources",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
},
{
"value": 2,
"type": "col",
"nodes": [
{
"value": "Compliance score",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 6,
"prop_font_style": "B"
}
}
]
}
]
},
{
"value": 3,
"type": "row",
"details": {
"prop_background_color": "RGB(224, 224, 224)"
},
"nodes": [
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "severity",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "ref",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6
}
}
]
},
{
"value": 6,
"type": "col",
"nodes": [
{
"value": "name",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "failed",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6
}
}
]
},
{
"value": 1,
"type": "col",
"nodes": [
{
"value": "all",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6
}
}
]
},
{
"value": 2,
"type": "col",
"nodes": [
{
"value": "score",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "courier",
"prop_font_size": 6,
"prop_vertical_padding": 1
}
}
]
}
]
},
{
"value": 0.3,
"type": "row",
"nodes": [
{
"value": 0,
"type": "col",
"details": {
"is_max": true
},
"nodes": [
{
"type": "line",
"details": {
"prop_offset_percent": 5,
"prop_orientation": "horizontal",
"prop_size_percent": 100,
"prop_style": "solid",
"prop_thickness": 0.3
}
}
]
}
]
},
{
"value": 2,
"type": "row",
"nodes": [
{
"value": 0,
"type": "col",
"details": {
"is_max": true
}
}
]
},
{
"value": 10,
"type": "row",
"nodes": [
{
"value": 5,
"type": "col",
"nodes": [
{
"value": "Resource summary",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B"
}
}
]
},
{
"value": 2,
"type": "col",
"nodes": [
{
"value": "100",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B"
}
}
]
},
{
"value": 2,
"type": "col",
"nodes": [
{
"value": "10",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B"
}
}
]
},
{
"value": 2,
"type": "col",
"nodes": [
{
"value": "10.00%",
"type": "text",
"details": {
"prop_align": "L",
"prop_breakline_strategy": "empty_space_strategy",
"prop_color": "RGB(0, 0, 0)",
"prop_font_family": "arial",
"prop_font_size": 8,
"prop_font_style": "B"
}
}
]
}
]
},
{
"value": 236.6975,
"type": "row",
"nodes": [
{
"value": 12,
"type": "col"
}
]
}
]
}
]
}

View File

@@ -201,7 +201,7 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
}
// If the fileType is helm chart
if templateNodes, ok := opaSessionObj.TemplateMapping[resourceID]; ok {
if templateNodes, ok := opaSessionObj.TemplateMapping[resourceID]; ok && len(templateNodes.Nodes) > 0 {
mappingnodes = templateNodes.Nodes
helmChartFileType = true
}
@@ -209,8 +209,7 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
rsrcAbsPath := path.Join(basePath, filepath)
locationResolver, err := locationresolver.NewFixPathLocationResolver(rsrcAbsPath) //
if err != nil && !helmChartFileType {
logger.L().Debug("failed to create location resolver", helpers.Error(err))
continue
logger.L().Debug("failed to create location resolver, will use default location", helpers.Error(err))
}
for _, toPin := range result.AssociatedControls {

View File

@@ -10,13 +10,14 @@ import (
)
func main() {
ks := core.NewKubescape()
ctx := context.TODO()
ks := core.NewKubescape(ctx)
downloads := []metav1.DownloadInfo{
{Target: "artifacts"}, // download all artifacts
{Target: "framework", Identifier: "security"}, // force add the "security" framework
}
for _, download := range downloads {
if err := ks.Download(context.Background(), &download); err != nil {
if err := ks.Download(&download); err != nil {
logger.L().Error("failed to download artifact", helpers.Error(err), helpers.String("target", download.Target))
}
}

47
go.mod
View File

@@ -23,17 +23,18 @@ require (
github.com/go-git/go-git/v5 v5.13.0
github.com/google/go-containerregistry v0.19.1
github.com/google/uuid v1.6.0
github.com/johnfercher/maroto v1.0.0
github.com/johnfercher/go-tree v1.1.0
github.com/johnfercher/maroto/v2 v2.2.2
github.com/json-iterator/go v1.1.12
github.com/jwalton/gchalk v1.3.0
github.com/kubescape/backend v0.0.20
github.com/kubescape/go-git-url v0.0.30
github.com/kubescape/go-logger v0.0.23
github.com/kubescape/k8s-interface v0.0.174
github.com/kubescape/opa-utils v0.0.284
github.com/kubescape/opa-utils v0.0.287
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520
github.com/kubescape/regolibrary/v2 v2.0.1
github.com/kubescape/sizing-checker v0.0.0-20250116130326-857b8213eca8
github.com/kubescape/sizing-checker v0.0.0-20250225194755-bed52921170a
github.com/maruel/natural v1.1.1
github.com/matthyx/go-gitlog v0.0.0-20231005131906-9ffabe3c5bcd
github.com/mattn/go-isatty v0.0.20
@@ -50,16 +51,15 @@ require (
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/otel v1.30.0
go.opentelemetry.io/otel/metric v1.30.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/mod v0.20.0
golang.org/x/term v0.27.0
golang.org/x/term v0.28.0
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.14.4
k8s.io/api v0.32.0
k8s.io/apimachinery v0.32.0
k8s.io/client-go v0.32.0
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
k8s.io/api v0.32.2
k8s.io/apimachinery v0.32.2
k8s.io/client-go v0.32.2
k8s.io/utils v0.0.0-20241210054802-24370beab758
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3
sigs.k8s.io/yaml v1.4.0
@@ -163,7 +163,7 @@ require (
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/bmatcuk/doublestar/v2 v2.0.4 // indirect
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect
github.com/bugsnag/bugsnag-go/v2 v2.3.0 // indirect
github.com/bugsnag/panicwrap v1.3.4 // indirect
github.com/buildkite/agent/v3 v3.62.0 // indirect
@@ -218,6 +218,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/f-amaral/go-async v0.3.0 // indirect
github.com/facebookincubator/nvdtools v0.1.5 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
@@ -235,8 +236,8 @@ require (
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
@@ -265,7 +266,7 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/certificate-transparency-go v1.1.8 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-github/v55 v55.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -289,6 +290,8 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/hhrutter/lzw v1.0.0 // indirect
github.com/hhrutter/tiff v1.0.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
@@ -318,7 +321,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mholt/archiver/v3 v3.5.1 // indirect
github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032 // indirect
@@ -366,6 +369,7 @@ require (
github.com/package-url/packageurl-go v0.1.2-0.20230812223828-f8bb31c1f10b // indirect
github.com/pborman/indent v1.2.1 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pdfcpu/pdfcpu v0.9.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
@@ -382,7 +386,6 @@ require (
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.7 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
github.com/saferwall/pe v1.5.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
@@ -470,12 +473,14 @@ require (
go.step.sm/crypto v0.44.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.9.1 // indirect
@@ -495,7 +500,7 @@ require (
gorm.io/gorm v1.25.10 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
modernc.org/libc v1.49.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
@@ -503,7 +508,7 @@ require (
sigs.k8s.io/controller-runtime v0.15.0 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/release-utils v0.7.7 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
)
// Using the forked version of tablewriter

90
go.sum
View File

@@ -483,8 +483,8 @@ github.com/bmatcuk/doublestar/v2 v2.0.4/go.mod h1:QMmcs3H2AUQICWhfzLXz+IYln8lRQm
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.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 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
@@ -689,6 +689,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/f-amaral/go-async v0.3.0 h1:h4kLsX7aKfdWaHvV0lf+/EE3OIeCzyeDYJDb/vDZUyg=
github.com/f-amaral/go-async v0.3.0/go.mod h1:Hz5Qr6DAWpbTTUjytnrg1WIsDgS7NtOei5y8SipYS7U=
github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk=
github.com/facebookincubator/nvdtools v0.1.5 h1:jbmDT1nd6+k+rlvKhnkgMokrCAzHoASWE5LtHbX2qFQ=
github.com/facebookincubator/nvdtools v0.1.5/go.mod h1:Kh55SAWnjckS96TBSrXI99KrEKH4iB0OJby3N8GRJO4=
@@ -767,10 +769,10 @@ github.com/go-gota/gota v0.12.0 h1:T5BDg1hTf5fZ/CO+T/N0E+DDqUhvoKBl+UVckgcAAQg=
github.com/go-gota/gota v0.12.0/go.mod h1:UT+NsWpZC/FhaOyWb9Hui0jXg0Iq8e/YugZHTbyW/34=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -898,8 +900,8 @@ github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJ
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/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/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -1065,6 +1067,10 @@ github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGb
github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0=
github.com/hhrutter/tiff v1.0.1/go.mod h1:zU/dNgDm0cMIa8y8YwcYBeuEEveI4B0owqHyiPpJPHc=
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=
@@ -1106,8 +1112,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
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=
github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
github.com/johnfercher/maroto v1.0.0 h1:yo26a/Mxj2YbHCzpIW7FypKtdvv9BdeLNHaApHwLCXU=
github.com/johnfercher/maroto v1.0.0/go.mod h1:qeujdhKT+677jMjGWlIa5OCgR04GgIHvByJ6pSC+hOw=
github.com/johnfercher/go-tree v1.1.0 h1:L0Fs5jLR1uA2e/CwfHjNdO/Lt4IGQ46QgxarAC1yeXs=
github.com/johnfercher/go-tree v1.1.0/go.mod h1:DUO6QkXIFh1K7jeGBIkLCZaeUgnkdQAsB64FDSoHswg=
github.com/johnfercher/maroto/v2 v2.2.2 h1:6VSNfXe/kDNTNDE13+CDm53lxFfv9hHsW1SHtoKVicw=
github.com/johnfercher/maroto/v2 v2.2.2/go.mod h1:/LfW6AQGZzsG6xUixcfyxkKztDoszdwC+G2jNRl8bss=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -1175,14 +1183,14 @@ github.com/kubescape/go-logger v0.0.23 h1:5xh+Nm8eGImhFbtippRKLaFgsvlKE1ufvQhNM2
github.com/kubescape/go-logger v0.0.23/go.mod h1:Ayg7g769c7sXVB+P3fkJmbsJpoEmMmaUf9jeo+XuC3U=
github.com/kubescape/k8s-interface v0.0.174 h1:I62Dc0RZmdESJrZLhtv2ZDqvf35XQ8g19T1LQPLARsk=
github.com/kubescape/k8s-interface v0.0.174/go.mod h1:PAJHWlN7v+VI3jx4v2xH2VqvbN+4bcy7paqXd5/tQ4I=
github.com/kubescape/opa-utils v0.0.284 h1:I7wLXzRjeSCLrAVrktxr0/2cFHRQ3P9SCjh/nkJGrwo=
github.com/kubescape/opa-utils v0.0.284/go.mod h1:N/UnbZHpoiHQH7O50yadhIXZvVl0IVtTGBmePPrSQSg=
github.com/kubescape/opa-utils v0.0.287 h1:1jtwZNRlsJQWDmAFq5RqNPykvLQcWNBW/XYT9RmWReI=
github.com/kubescape/opa-utils v0.0.287/go.mod h1:fgL/Bykj2+HYQc81Mj2HkWrs5tBwIlb+/yEkKfA54fw=
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 h1:SqlwF8G+oFazeYmZQKoPczLEflBQpwpHCU8DoLLyfj8=
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520/go.mod h1:wuxMUSDzGUyWd25IJfBzEJ/Udmw2Vy7npj+MV3u3GrU=
github.com/kubescape/regolibrary/v2 v2.0.1 h1:7lKj171gslgTbbcmmGVHk34AZNqxForOXZIINoQfdzQ=
github.com/kubescape/regolibrary/v2 v2.0.1/go.mod h1:s0/Mi9PYw7s91vIf1VJTkuu1Blsl5ZLpYn5UA7yk/vM=
github.com/kubescape/sizing-checker v0.0.0-20250116130326-857b8213eca8 h1:nY7mudLcU3gFNq/pcfCcH2NN1xj31guA7Ozh76qfZVc=
github.com/kubescape/sizing-checker v0.0.0-20250116130326-857b8213eca8/go.mod h1:n/U3qC/lVtIgVi3yD7GYJ67tZ8y92XFYhEUdJH98wDE=
github.com/kubescape/sizing-checker v0.0.0-20250225194755-bed52921170a h1:qduF+/rE+UY1saBlfmSM1b594qgByqCCHzw5s4es5X8=
github.com/kubescape/sizing-checker v0.0.0-20250225194755-bed52921170a/go.mod h1:xCg5Fh96STR7zQ3Tj2jrHi6oIMCwdwfr7ir5n1nJBQw=
github.com/kubescape/tablewriter v0.0.6-0.20231106230230-aac7d2659c94 h1:uhabZUyrxo60JQrzGCQOp1gsJz06+6+PeDBTvXiKD7k=
github.com/kubescape/tablewriter v0.0.6-0.20231106230230-aac7d2659c94/go.mod h1:clwQfF3MN2cpaf7R6hc84aB6fQsRr+bnm66pXXSNAv8=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -1237,8 +1245,8 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
@@ -1387,6 +1395,8 @@ github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM=
github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrpz5K6Vw=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pdfcpu/pdfcpu v0.9.1 h1:q8/KlBdHjkE7ZJU4ofhKG5Rjf7M6L324CVM6BMDySao=
github.com/pdfcpu/pdfcpu v0.9.1/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -1465,8 +1475,6 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
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=
@@ -1833,8 +1841,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
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=
@@ -1860,6 +1868,8 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o
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.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
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=
@@ -2005,8 +2015,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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=
@@ -2112,8 +2122,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2126,8 +2136,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
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=
@@ -2143,8 +2153,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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=
@@ -2537,20 +2547,20 @@ 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.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
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-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
@@ -2589,8 +2599,8 @@ sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
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.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/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=

View File

@@ -18,22 +18,22 @@ require (
github.com/kubescape/go-logger v0.0.23
github.com/kubescape/k8s-interface v0.0.174
github.com/kubescape/kubescape/v3 v3.0.4
github.com/kubescape/opa-utils v0.0.284
github.com/kubescape/opa-utils v0.0.287
github.com/kubescape/storage v0.0.111
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.45.0
go.opentelemetry.io/otel v1.30.0
k8s.io/apimachinery v0.32.0
k8s.io/client-go v0.32.0
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
k8s.io/apimachinery v0.32.2
k8s.io/client-go v0.32.2
k8s.io/utils v0.0.0-20241210054802-24370beab758
)
require (
go.opentelemetry.io/otel/trace v1.30.0
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.33.0 // indirect
@@ -143,7 +143,7 @@ require (
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/bmatcuk/doublestar/v2 v2.0.4 // indirect
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect
github.com/briandowns/spinner v1.23.1 // indirect
github.com/buildkite/agent/v3 v3.62.0 // indirect
github.com/buildkite/go-pipeline v0.3.2 // indirect
@@ -201,6 +201,7 @@ require (
github.com/emirpasic/gods v1.18.1 // indirect
github.com/enescakir/emoji v1.0.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/f-amaral/go-async v0.3.0 // indirect
github.com/facebookincubator/nvdtools v0.1.5 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
@@ -220,8 +221,8 @@ require (
github.com/go-git/go-git/v5 v5.13.0 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
@@ -248,7 +249,7 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/certificate-transparency-go v1.1.8 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-containerregistry v0.20.0 // indirect
github.com/google/go-github/v55 v55.0.0 // indirect
@@ -273,6 +274,8 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/hhrutter/lzw v1.0.0 // indirect
github.com/hhrutter/tiff v1.0.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
@@ -284,7 +287,8 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/johnfercher/maroto v1.0.0 // indirect
github.com/johnfercher/go-tree v1.1.0 // indirect
github.com/johnfercher/maroto/v2 v2.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.16.2 // indirect
@@ -363,6 +367,7 @@ require (
github.com/package-url/packageurl-go v0.1.2 // indirect
github.com/pborman/indent v1.2.1 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pdfcpu/pdfcpu v0.9.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
@@ -380,7 +385,6 @@ require (
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.7 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
github.com/saferwall/pe v1.5.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
@@ -471,10 +475,11 @@ require (
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
go.step.sm/crypto v0.44.2 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.9.1 // indirect
@@ -492,10 +497,10 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/gorm v1.25.10 // indirect
helm.sh/helm/v3 v3.14.4 // indirect
k8s.io/api v0.32.0 // indirect
k8s.io/api v0.32.2 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
modernc.org/libc v1.49.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
@@ -505,7 +510,7 @@ require (
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/release-utils v0.7.7 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

View File

@@ -484,8 +484,8 @@ github.com/bmatcuk/doublestar/v2 v2.0.4/go.mod h1:QMmcs3H2AUQICWhfzLXz+IYln8lRQm
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.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 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
@@ -692,6 +692,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/f-amaral/go-async v0.3.0 h1:h4kLsX7aKfdWaHvV0lf+/EE3OIeCzyeDYJDb/vDZUyg=
github.com/f-amaral/go-async v0.3.0/go.mod h1:Hz5Qr6DAWpbTTUjytnrg1WIsDgS7NtOei5y8SipYS7U=
github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk=
github.com/facebookincubator/nvdtools v0.1.5 h1:jbmDT1nd6+k+rlvKhnkgMokrCAzHoASWE5LtHbX2qFQ=
github.com/facebookincubator/nvdtools v0.1.5/go.mod h1:Kh55SAWnjckS96TBSrXI99KrEKH4iB0OJby3N8GRJO4=
@@ -770,10 +772,10 @@ github.com/go-gota/gota v0.12.0 h1:T5BDg1hTf5fZ/CO+T/N0E+DDqUhvoKBl+UVckgcAAQg=
github.com/go-gota/gota v0.12.0/go.mod h1:UT+NsWpZC/FhaOyWb9Hui0jXg0Iq8e/YugZHTbyW/34=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -901,8 +903,8 @@ github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJ
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/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/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -1072,6 +1074,10 @@ github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGb
github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0=
github.com/hhrutter/tiff v1.0.1/go.mod h1:zU/dNgDm0cMIa8y8YwcYBeuEEveI4B0owqHyiPpJPHc=
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=
@@ -1113,8 +1119,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
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=
github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
github.com/johnfercher/maroto v1.0.0 h1:yo26a/Mxj2YbHCzpIW7FypKtdvv9BdeLNHaApHwLCXU=
github.com/johnfercher/maroto v1.0.0/go.mod h1:qeujdhKT+677jMjGWlIa5OCgR04GgIHvByJ6pSC+hOw=
github.com/johnfercher/go-tree v1.1.0 h1:L0Fs5jLR1uA2e/CwfHjNdO/Lt4IGQ46QgxarAC1yeXs=
github.com/johnfercher/go-tree v1.1.0/go.mod h1:DUO6QkXIFh1K7jeGBIkLCZaeUgnkdQAsB64FDSoHswg=
github.com/johnfercher/maroto/v2 v2.2.2 h1:6VSNfXe/kDNTNDE13+CDm53lxFfv9hHsW1SHtoKVicw=
github.com/johnfercher/maroto/v2 v2.2.2/go.mod h1:/LfW6AQGZzsG6xUixcfyxkKztDoszdwC+G2jNRl8bss=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -1182,8 +1190,8 @@ github.com/kubescape/go-logger v0.0.23 h1:5xh+Nm8eGImhFbtippRKLaFgsvlKE1ufvQhNM2
github.com/kubescape/go-logger v0.0.23/go.mod h1:Ayg7g769c7sXVB+P3fkJmbsJpoEmMmaUf9jeo+XuC3U=
github.com/kubescape/k8s-interface v0.0.174 h1:I62Dc0RZmdESJrZLhtv2ZDqvf35XQ8g19T1LQPLARsk=
github.com/kubescape/k8s-interface v0.0.174/go.mod h1:PAJHWlN7v+VI3jx4v2xH2VqvbN+4bcy7paqXd5/tQ4I=
github.com/kubescape/opa-utils v0.0.284 h1:I7wLXzRjeSCLrAVrktxr0/2cFHRQ3P9SCjh/nkJGrwo=
github.com/kubescape/opa-utils v0.0.284/go.mod h1:N/UnbZHpoiHQH7O50yadhIXZvVl0IVtTGBmePPrSQSg=
github.com/kubescape/opa-utils v0.0.287 h1:1jtwZNRlsJQWDmAFq5RqNPykvLQcWNBW/XYT9RmWReI=
github.com/kubescape/opa-utils v0.0.287/go.mod h1:fgL/Bykj2+HYQc81Mj2HkWrs5tBwIlb+/yEkKfA54fw=
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 h1:SqlwF8G+oFazeYmZQKoPczLEflBQpwpHCU8DoLLyfj8=
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520/go.mod h1:wuxMUSDzGUyWd25IJfBzEJ/Udmw2Vy7npj+MV3u3GrU=
github.com/kubescape/regolibrary/v2 v2.0.1 h1:7lKj171gslgTbbcmmGVHk34AZNqxForOXZIINoQfdzQ=
@@ -1393,6 +1401,8 @@ github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM=
github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrpz5K6Vw=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pdfcpu/pdfcpu v0.9.1 h1:q8/KlBdHjkE7ZJU4ofhKG5Rjf7M6L324CVM6BMDySao=
github.com/pdfcpu/pdfcpu v0.9.1/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -1471,8 +1481,6 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
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=
@@ -1846,8 +1854,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
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=
@@ -1873,6 +1881,8 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o
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.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
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=
@@ -2018,8 +2028,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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=
@@ -2125,8 +2135,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2139,8 +2149,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
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=
@@ -2156,8 +2166,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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=
@@ -2548,20 +2558,20 @@ 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.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
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-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
@@ -2600,8 +2610,8 @@ sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
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.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/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=

View File

@@ -1,8 +1,15 @@
package v1
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/armosec/armoapi-go/armotypes"
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v3/core/cautils"
"github.com/kubescape/kubescape/v3/core/cautils/getter"
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
@@ -67,6 +74,15 @@ func ToScanInfo(scanRequest *utilsmetav1.PostScanRequest) *cautils.ScanInfo {
scanInfo.IsDeletedScanObject = *scanRequest.IsDeletedScanObject
}
if scanRequest.Exceptions != nil {
path, err := saveExceptions(scanRequest.Exceptions)
if err != nil {
logger.L().Warning("failed to save exceptions, scanning without them", helpers.Error(err))
} else {
scanInfo.UseExceptions = path
}
}
return scanInfo
}
@@ -92,3 +108,15 @@ func setTargetInScanInfo(scanRequest *utilsmetav1.PostScanRequest, scanInfo *cau
scanInfo.ScanAll = true
}
}
func saveExceptions(exceptions []armotypes.PostureExceptionPolicy) (string, error) {
exceptionsJSON, err := json.Marshal(exceptions)
if err != nil {
return "", fmt.Errorf("failed to marshal exceptions: %w", err)
}
exceptionsPath := filepath.Join("/tmp", "exceptions.json") // FIXME potential race condition
if err := os.WriteFile(exceptionsPath, exceptionsJSON, 0644); err != nil {
return "", fmt.Errorf("failed to write exceptions file to disk: %w", err)
}
return exceptionsPath, nil
}

View File

@@ -66,7 +66,7 @@ func scan(ctx context.Context, scanInfo *cautils.ScanInfo, scanID string) (*repo
ctx, spanScan := otel.Tracer("").Start(ctx, "kubescape.scan")
defer spanScan.End()
ks := core.NewKubescape()
ks := core.NewKubescape(ctx)
spanScan.AddEvent("scanning metadata",
trace.WithAttributes(attribute.String("version", versioncheck.BuildNumber)),
@@ -79,7 +79,7 @@ func scan(ctx context.Context, scanInfo *cautils.ScanInfo, scanID string) (*repo
trace.WithAttributes(attribute.String("hostSensorYamlPath", scanInfo.HostSensorYamlPath)),
)
result, err := ks.Scan(ctx, scanInfo)
result, err := ks.Scan(scanInfo)
if err != nil {
return nil, writeScanErrorToFile(err, scanID)
}

13
main.go
View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"os"
"os/signal"
"syscall"
@@ -11,21 +12,17 @@ import (
func main() {
// Capture interrupt signal
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
// Handle interrupt signal
go func() {
<-signalChan
<-ctx.Done()
// Perform cleanup or graceful shutdown here
logger.L().StopError("Received interrupt signal, exiting...")
// Exit the program with proper exit code for SIGINT
os.Exit(130)
}()
if err := cmd.Execute(); err != nil {
if err := cmd.Execute(ctx); err != nil {
logger.L().Fatal(err.Error())
}
}

View File

@@ -5,11 +5,13 @@ import (
"errors"
"fmt"
"path/filepath"
"strings"
"github.com/adrg/xdg"
"github.com/anchore/grype/grype"
"github.com/anchore/grype/grype/db"
"github.com/anchore/grype/grype/grypeerr"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/matcher"
"github.com/anchore/grype/grype/matcher/dotnet"
"github.com/anchore/grype/grype/matcher/golang"
@@ -116,9 +118,67 @@ type Service struct {
dbCfg db.Config
}
func (s *Service) Scan(ctx context.Context, userInput string, creds RegistryCredentials) (*models.PresenterConfig, error) {
var err error
func getIgnoredMatches(vulnerabilityExceptions []string, store *store.Store, packages []pkg.Package, pkgContext pkg.Context) (*match.Matches, []match.IgnoredMatch, error) {
if vulnerabilityExceptions == nil {
vulnerabilityExceptions = []string{}
}
var ignoreRules []match.IgnoreRule
for _, exception := range vulnerabilityExceptions {
rule := match.IgnoreRule{
Vulnerability: exception,
}
ignoreRules = append(ignoreRules, rule)
}
matcher := grype.VulnerabilityMatcher{
Store: *store,
Matchers: getMatchers(),
IgnoreRules: ignoreRules,
}
remainingMatches, ignoredMatches, err := matcher.FindMatches(packages, pkgContext)
if err != nil {
if !errors.Is(err, grypeerr.ErrAboveSeverityThreshold) {
return nil, nil, err
}
}
return remainingMatches, ignoredMatches, nil
}
// Filter the remaing matches based on severity exceptions.
func filterMatchesBasedOnSeverity(severityExceptions []string, remainingMatches match.Matches, store *store.Store) match.Matches {
if severityExceptions == nil {
return remainingMatches
}
filteredMatches := match.NewMatches()
for m := range remainingMatches.Enumerate() {
metadata, err := store.GetMetadata(m.Vulnerability.ID, m.Vulnerability.Namespace)
if err != nil {
continue
}
// Skip this match if the severity of this match is present in severityExceptions.
excludeSeverity := false
for _, sever := range severityExceptions {
if strings.ToUpper(metadata.Severity) == sever {
excludeSeverity = true
continue
}
}
if !excludeSeverity {
filteredMatches.Add(m)
}
}
return filteredMatches
}
func (s *Service) Scan(ctx context.Context, userInput string, creds RegistryCredentials, vulnerabilityExceptions, severityExceptions []string) (*models.PresenterConfig, error) {
store, status, dbCloser, err := NewVulnerabilityDB(s.dbCfg, true)
if err = validateDBLoad(err, status); err != nil {
return nil, err
@@ -133,20 +193,15 @@ func (s *Service) Scan(ctx context.Context, userInput string, creds RegistryCred
defer dbCloser.Close()
}
matcher := grype.VulnerabilityMatcher{
Store: *store,
Matchers: getMatchers(),
remainingMatches, ignoredMatches, err := getIgnoredMatches(vulnerabilityExceptions, store, packages, pkgContext)
if err != nil {
return nil, err
}
remainingMatches, ignoredMatches, err := matcher.FindMatches(packages, pkgContext)
if err != nil {
if !errors.Is(err, grypeerr.ErrAboveSeverityThreshold) {
return nil, err
}
}
filteredMatches := filterMatchesBasedOnSeverity(severityExceptions, *remainingMatches, store)
pb := models.PresenterConfig{
Matches: *remainingMatches,
Matches: filteredMatches,
IgnoredMatches: ignoredMatches,
Packages: packages,
Context: pkgContext,

View File

@@ -2,9 +2,12 @@ package imagescan
import (
"errors"
"net/http"
"path"
"testing"
"time"
"github.com/adrg/xdg"
"github.com/anchore/grype/grype/db"
grypedb "github.com/anchore/grype/grype/db/v5"
"github.com/anchore/grype/grype/match"
@@ -16,63 +19,71 @@ import (
"github.com/stretchr/testify/assert"
)
// import (
// "context"
// "testing"
func TestVulnerabilityAndSeverityExceptions(t *testing.T) {
go func() {
_ = http.ListenAndServe(":8000", http.FileServer(http.Dir("testdata"))) //nolint:gosec
}()
dbCfg := db.Config{
DBRootDir: path.Join(xdg.CacheHome, "grype-light", "db"),
ListingURL: "http://localhost:8000/listing.json",
}
svc := NewScanService(dbCfg)
creds := RegistryCredentials{}
// "github.com/anchore/grype/grype/db"
// grypedb "github.com/anchore/grype/grype/db/v5"
// "github.com/anchore/grype/grype/match"
// "github.com/anchore/grype/grype/pkg"
// "github.com/anchore/grype/grype/presenter/models"
// "github.com/anchore/grype/grype/vulnerability"
// syftPkg "github.com/anchore/syft/syft/pkg"
// "github.com/google/uuid"
// "github.com/stretchr/testify/assert"
// )
tests := []struct {
name string
image string
vulnerabilityExceptions []string
ignoredLen int
severityExceptions []string
filteredLen int
}{
{
name: "alpine:3.19.1 without medium vulnerabilities",
image: "alpine:3.19.1",
ignoredLen: 0,
severityExceptions: []string{"MEDIUM"},
filteredLen: 0,
},
{
name: "alpine:3.9.6",
image: "alpine:3.9.6",
vulnerabilityExceptions: []string{"CVE-2020-1971", "CVE-2020-28928", "CVE-2021-23840"},
ignoredLen: 6,
severityExceptions: []string{"HIGH", "MEDIUM"},
filteredLen: 8,
},
{
name: "alpine:3.9.6 with invalid vulnerability and severity exceptions",
image: "alpine:3.9.6",
vulnerabilityExceptions: []string{"invalid-cve", "CVE-2020-28928", "CVE-2021-23840"},
ignoredLen: 4,
severityExceptions: []string{"CRITICAL", "MEDIUM", "invalid-severity"},
filteredLen: 10,
},
}
// func TestNewScanService(t *testing.T) {
// dbCfg, _ := NewDefaultDBConfig()
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
store, status, dbCloser, err := NewVulnerabilityDB(svc.dbCfg, true)
assert.NoError(t, validateDBLoad(err, status))
// svc := NewScanService(dbCfg)
packages, pkgContext, _, err := pkg.Provide(tc.image, getProviderConfig(creds))
assert.NoError(t, err)
// assert.IsType(t, Service{}, svc)
// }
if dbCloser != nil {
defer dbCloser.Close()
}
// func TestScan(t *testing.T) {
// tt := []struct {
// name string
// image string
// creds RegistryCredentials
// }{
// {
// name: "Valid image name produces a non-nil scan result",
// image: "nginx",
// },
// {
// name: "Scanning a valid image with provided credentials should produce a non-nil scan result",
// image: "nginx",
// creds: RegistryCredentials{
// Username: "test",
// Password: "password",
// },
// },
// }
remainingMatches, ignoredMatches, err := getIgnoredMatches(tc.vulnerabilityExceptions, store, packages, pkgContext)
assert.NoError(t, err)
assert.Equal(t, tc.ignoredLen, len(ignoredMatches))
// for _, tc := range tt {
// t.Run(tc.name, func(t *testing.T) {
// ctx := context.Background()
// dbCfg, _ := NewDefaultDBConfig()
// svc := NewScanService(dbCfg)
// creds := RegistryCredentials{}
// scanResults, err := svc.Scan(ctx, tc.image, creds)
// assert.NoError(t, err)
// assert.IsType(t, &models.PresenterConfig{}, scanResults)
// })
// }
// }
filteredMatches := filterMatchesBasedOnSeverity(tc.severityExceptions, *remainingMatches, store)
assert.Equal(t, tc.filteredLen, filteredMatches.Count())
})
}
}
// fakeMetaProvider is a test double that fakes an actual MetadataProvider
type fakeMetaProvider struct {

12
pkg/imagescan/testdata/listing.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"available": {
"5": [
{
"built": "2023-12-13T01:27:01Z",
"version": 5,
"url": "http://localhost:8000/vulnerability-db_v5_2023-03-24T06_54_57Z_fab15e5405c096d82dfd.tar.gz",
"checksum": "sha256:99ad9fd54be5295351555a02a0fb6986a461a9d23eb8ae3b34ea892c252a8c80"
}
]
}
}