mirror of
https://github.com/kubescape/kubescape.git
synced 2026-03-03 02:00:27 +00:00
Compare commits
98 Commits
v3.0.4-rc.
...
v3.0.10-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da6faa3df0 | ||
|
|
3cbd2c458d | ||
|
|
629451dd33 | ||
|
|
29a313e708 | ||
|
|
38896ccd24 | ||
|
|
834623762d | ||
|
|
c937ed16f4 | ||
|
|
ea5f72af4e | ||
|
|
beb5a4d43e | ||
|
|
77e21d5e94 | ||
|
|
3fd7bf40cc | ||
|
|
18e0a227e1 | ||
|
|
060c17b480 | ||
|
|
e67a2e9d1c | ||
|
|
dfa5f1037e | ||
|
|
a15fc066e1 | ||
|
|
effc57dfda | ||
|
|
4b5c2dfed4 | ||
|
|
f39d4efd62 | ||
|
|
97ce466fbd | ||
|
|
a94dc85e14 | ||
|
|
7811b0a4a6 | ||
|
|
f9cc9b5b28 | ||
|
|
2f208c0866 | ||
|
|
97e4ca749b | ||
|
|
9521cf1974 | ||
|
|
8ec56976c5 | ||
|
|
5993f2db3a | ||
|
|
d0abfb4ae7 | ||
|
|
bd35d521f2 | ||
|
|
533c0392d4 | ||
|
|
e0f2944fc8 | ||
|
|
bda7a17f41 | ||
|
|
dee6ed96f8 | ||
|
|
0d1de027c9 | ||
|
|
22c85b5e3b | ||
|
|
d27284b6f6 | ||
|
|
4bde684d8a | ||
|
|
8cf735f84c | ||
|
|
e1db7f3704 | ||
|
|
fd64a068aa | ||
|
|
1945d3dfaa | ||
|
|
42670c7a9f | ||
|
|
81a9ca4254 | ||
|
|
00c0a205d6 | ||
|
|
374d8be96f | ||
|
|
70daff7cec | ||
|
|
22fc14ae50 | ||
|
|
d9736d7d56 | ||
|
|
574763ccfc | ||
|
|
a8cc411945 | ||
|
|
0576548bbe | ||
|
|
0477f8cb03 | ||
|
|
9a2d58faa0 | ||
|
|
d975f8e64a | ||
|
|
a2bd504e36 | ||
|
|
8a671b9658 | ||
|
|
b7a4f82968 | ||
|
|
0ee121a08f | ||
|
|
708bf4477a | ||
|
|
56a9d9a7f3 | ||
|
|
337fb96e3f | ||
|
|
c5fa53c00f | ||
|
|
e2dc7d24f9 | ||
|
|
d13dd9b3a7 | ||
|
|
aa0f13e348 | ||
|
|
725eab67f9 | ||
|
|
6efa37a14d | ||
|
|
f05ab61421 | ||
|
|
5217ad21ec | ||
|
|
55e570a2b2 | ||
|
|
f64617c88c | ||
|
|
ad4996e553 | ||
|
|
46febea6d3 | ||
|
|
da022a1cf0 | ||
|
|
9d11f2d881 | ||
|
|
d0521b83ae | ||
|
|
d8d6ab96df | ||
|
|
abefe8c21a | ||
|
|
0e0e1ed6fb | ||
|
|
05ec28be48 | ||
|
|
f5e110c212 | ||
|
|
2429d2b89d | ||
|
|
cf75cc3a7a | ||
|
|
f1c34efa97 | ||
|
|
7fd1396cff | ||
|
|
522cc3a454 | ||
|
|
cbdbd7433b | ||
|
|
15b63401b7 | ||
|
|
7f5d513e6b | ||
|
|
e87f3399c7 | ||
|
|
fad8f2b272 | ||
|
|
bc33f10d0a | ||
|
|
0033dc881e | ||
|
|
9549e0dcde | ||
|
|
809146c070 | ||
|
|
546b982891 | ||
|
|
f1eaf09570 |
10
.github/workflows/00-pr-scanner.yaml
vendored
10
.github/workflows/00-pr-scanner.yaml
vendored
@@ -23,7 +23,6 @@ jobs:
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: read
|
||||
deployments: read
|
||||
id-token: write
|
||||
issues: read
|
||||
@@ -34,18 +33,22 @@ jobs:
|
||||
repository-projects: read
|
||||
security-events: read
|
||||
statuses: read
|
||||
attestations: read
|
||||
contents: write
|
||||
uses: ./.github/workflows/a-pr-scanner.yaml
|
||||
with:
|
||||
RELEASE: ""
|
||||
CLIENT: test
|
||||
CGO_ENABLED: 0
|
||||
GO111MODULE: ""
|
||||
secrets: inherit
|
||||
|
||||
binary-build:
|
||||
if: ${{ github.repository_owner == 'kubescape' }}
|
||||
if: ${{ github.actor == 'kubescape' }}
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: read
|
||||
contents: write
|
||||
deployments: read
|
||||
discussions: read
|
||||
id-token: write
|
||||
@@ -56,6 +59,7 @@ jobs:
|
||||
repository-projects: read
|
||||
security-events: read
|
||||
statuses: read
|
||||
attestations: read
|
||||
uses: ./.github/workflows/b-binary-build-and-e2e-tests.yaml
|
||||
with:
|
||||
COMPONENT_NAME: kubescape
|
||||
|
||||
10
.github/workflows/02-release.yaml
vendored
10
.github/workflows/02-release.yaml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
NEW_TAG: ${{ steps.tag-calculator.outputs.NEW_TAG }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # ratchet:actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- id: tag-calculator
|
||||
uses: ./.github/actions/tag-action
|
||||
with:
|
||||
@@ -19,7 +19,6 @@ jobs:
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: read
|
||||
deployments: read
|
||||
discussions: read
|
||||
id-token: write
|
||||
@@ -30,6 +29,8 @@ jobs:
|
||||
repository-projects: read
|
||||
security-events: read
|
||||
statuses: read
|
||||
contents: write
|
||||
attestations: write
|
||||
needs: [retag]
|
||||
uses: ./.github/workflows/b-binary-build-and-e2e-tests.yaml
|
||||
with:
|
||||
@@ -55,6 +56,7 @@ jobs:
|
||||
repository-projects: read
|
||||
statuses: read
|
||||
security-events: read
|
||||
attestations: read
|
||||
needs: [retag, binary-build]
|
||||
uses: ./.github/workflows/c-create-release.yaml
|
||||
with:
|
||||
@@ -66,7 +68,6 @@ jobs:
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: read
|
||||
deployments: read
|
||||
discussions: read
|
||||
id-token: write
|
||||
@@ -77,6 +78,8 @@ jobs:
|
||||
repository-projects: read
|
||||
security-events: read
|
||||
statuses: read
|
||||
attestations: read
|
||||
contents: write
|
||||
uses: ./.github/workflows/d-publish-image.yaml
|
||||
needs: [create-release, retag]
|
||||
with:
|
||||
@@ -86,3 +89,4 @@ jobs:
|
||||
support_platforms: true
|
||||
cosign: true
|
||||
secrets: inherit
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'kubescape'
|
||||
steps:
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # ratchet:actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Update new version in krew-index
|
||||
|
||||
63
.github/workflows/a-pr-scanner.yaml
vendored
63
.github/workflows/a-pr-scanner.yaml
vendored
@@ -15,7 +15,70 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: "./..."
|
||||
GO111MODULE:
|
||||
required: true
|
||||
type: string
|
||||
CGO_ENABLED:
|
||||
type: number
|
||||
default: 1
|
||||
jobs:
|
||||
unit-tests:
|
||||
if: ${{ github.actor != 'kubescape' }}
|
||||
name: Create cross-platform build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
name: Installing go
|
||||
with:
|
||||
go-version: ${{ inputs.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- name: Test core pkg
|
||||
run: ${{ env.DOCKER_CMD }} go test -v ./...
|
||||
if: startsWith(github.ref, 'refs/tags')
|
||||
|
||||
- name: Test httphandler pkg
|
||||
run: ${{ env.DOCKER_CMD }} sh -c 'cd httphandler && go test -v ./...'
|
||||
if: startsWith(github.ref, 'refs/tags')
|
||||
|
||||
- uses: anchore/sbom-action/download-syft@v0.15.2
|
||||
name: Setup Syft
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v5
|
||||
name: Build
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
args: release --clean --snapshot
|
||||
env:
|
||||
RELEASE: ${{ inputs.RELEASE }}
|
||||
CLIENT: ${{ inputs.CLIENT }}
|
||||
CGO_ENABLED: ${{ inputs.CGO_ENABLED }}
|
||||
|
||||
- name: Smoke Testing
|
||||
env:
|
||||
RELEASE: ${{ inputs.RELEASE }}
|
||||
KUBESCAPE_SKIP_UPDATE_CHECK: "true"
|
||||
run: ${{ env.DOCKER_CMD }} python3 smoke_testing/init.py ${PWD}/dist/kubescape-ubuntu-latest
|
||||
|
||||
- name: golangci-lint
|
||||
continue-on-error: false
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 10m
|
||||
only-new-issues: true
|
||||
skip-pkg-cache: true
|
||||
skip-build-cache: true
|
||||
|
||||
scanners:
|
||||
env:
|
||||
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
|
||||
|
||||
@@ -30,7 +30,32 @@ on:
|
||||
BINARY_TESTS:
|
||||
type: string
|
||||
required: false
|
||||
default: '[ "scan_nsa", "scan_mitre", "scan_with_exceptions", "scan_repository", "scan_local_file", "scan_local_glob_files", "scan_local_list_of_files", "scan_nsa_and_submit_to_backend", "scan_mitre_and_submit_to_backend", "scan_local_repository_and_submit_to_backend", "scan_repository_from_url_and_submit_to_backend", "scan_with_exception_to_backend", "scan_with_custom_framework", "scan_customer_configuration", "host_scanner", "scan_compliance_score", "control_cluster_from_CLI_config_scan_exclude_namespaces", "control_cluster_from_CLI_config_scan_include_namespaces", "control_cluster_from_CLI_config_scan_host_scanner_enabled", "control_cluster_from_CLI_config_scan_MITRE_framework", "control_cluster_from_CLI_vulnerabilities_scan_default", "control_cluster_from_CLI_vulnerabilities_scan_include_namespaces" ]'
|
||||
default: '[
|
||||
"ks_microservice_create_2_cronjob_mitre_and_nsa_proxy",
|
||||
"ks_microservice_triggering_with_cron_job",
|
||||
"ks_microservice_update_cronjob_schedule",
|
||||
"ks_microservice_delete_cronjob",
|
||||
"ks_microservice_create_2_cronjob_mitre_and_nsa",
|
||||
"ks_microservice_ns_creation",
|
||||
"ks_microservice_on_demand",
|
||||
"ks_microservice_mitre_framework_on_demand",
|
||||
"ks_microservice_nsa_and_mitre_framework_demand",
|
||||
"scan_nsa",
|
||||
"scan_mitre",
|
||||
"scan_with_exceptions",
|
||||
"scan_repository",
|
||||
"scan_local_file",
|
||||
"scan_local_glob_files",
|
||||
"scan_local_list_of_files",
|
||||
"scan_with_exception_to_backend",
|
||||
"scan_nsa_and_submit_to_backend",
|
||||
"scan_mitre_and_submit_to_backend",
|
||||
"scan_local_repository_and_submit_to_backend",
|
||||
"scan_repository_from_url_and_submit_to_backend",
|
||||
"scan_with_custom_framework",
|
||||
"scan_customer_configuration",
|
||||
"scan_compliance_score"
|
||||
]'
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -54,7 +79,25 @@ on:
|
||||
default: 1
|
||||
BINARY_TESTS:
|
||||
type: string
|
||||
default: '[ "scan_nsa", "scan_mitre", "scan_with_exceptions", "scan_repository", "scan_local_file", "scan_local_glob_files", "scan_local_list_of_files", "scan_nsa_and_submit_to_backend", "scan_mitre_and_submit_to_backend", "scan_local_repository_and_submit_to_backend", "scan_repository_from_url_and_submit_to_backend", "scan_with_exception_to_backend", "scan_with_custom_framework", "scan_customer_configuration", "host_scanner", "scan_compliance_score", "scan_custom_framework_scanning_file_scope_testing", "scan_custom_framework_scanning_cluster_scope_testing", "scan_custom_framework_scanning_cluster_and_file_scope_testing" ]'
|
||||
default: '[
|
||||
"scan_nsa",
|
||||
"scan_mitre",
|
||||
"scan_with_exceptions",
|
||||
"scan_repository",
|
||||
"scan_local_file",
|
||||
"scan_local_glob_files",
|
||||
"scan_local_list_of_files",
|
||||
"scan_nsa_and_submit_to_backend",
|
||||
"scan_mitre_and_submit_to_backend",
|
||||
"scan_local_repository_and_submit_to_backend",
|
||||
"scan_repository_from_url_and_submit_to_backend",
|
||||
"scan_with_custom_framework",
|
||||
"scan_customer_configuration",
|
||||
"scan_compliance_score",
|
||||
"scan_custom_framework_scanning_file_scope_testing",
|
||||
"scan_custom_framework_scanning_cluster_scope_testing",
|
||||
"scan_custom_framework_scanning_cluster_and_file_scope_testing"
|
||||
]'
|
||||
|
||||
jobs:
|
||||
wf-preparation:
|
||||
@@ -75,7 +118,7 @@ jobs:
|
||||
SECRET_KEY: ${{ secrets.SECRET_KEY_PROD }}
|
||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
run: "echo \"is-secret-set=${{ env.CUSTOMER != '' && \n env.USERNAME != '' &&\n env.PASSWORD != '' &&\n env.CLIENT_ID != '' &&\n env.SECRET_KEY != '' &&\n env.REGISTRY_USERNAME != '' &&\n env.REGISTRY_PASSWORD != ''\n }}\" >> $GITHUB_OUTPUT\n"
|
||||
run: "echo \"is-secret-set=${{ env.CUSTOMER != '' && env.USERNAME != '' && env.PASSWORD != '' && env.CLIENT_ID != '' && env.SECRET_KEY != '' && env.REGISTRY_USERNAME != '' && env.REGISTRY_PASSWORD != '' }}\" >> $GITHUB_OUTPUT\n"
|
||||
|
||||
- id: export_tests_to_env
|
||||
name: set test name
|
||||
@@ -106,7 +149,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
@@ -147,11 +190,13 @@ jobs:
|
||||
|
||||
- name: golangci-lint
|
||||
continue-on-error: true
|
||||
uses: golangci/golangci-lint-action@08e2f20817b15149a52b5b3ebe7de50aff2ba8c5 # ratchet:golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 10m --build-tags=static
|
||||
args: --timeout 10m
|
||||
only-new-issues: true
|
||||
skip-pkg-cache: true
|
||||
skip-build-cache: true
|
||||
|
||||
- uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # ratchet:actions/upload-artifact@v3.1.1
|
||||
name: Upload artifacts
|
||||
@@ -162,7 +207,7 @@ jobs:
|
||||
|
||||
build-http-image:
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
id-token: write
|
||||
packages: write
|
||||
pull-requests: read
|
||||
@@ -186,8 +231,22 @@ jobs:
|
||||
"ks_microservice_on_demand",
|
||||
"ks_microservice_mitre_framework_on_demand",
|
||||
"ks_microservice_nsa_and_mitre_framework_demand",
|
||||
"scan_nsa",
|
||||
"scan_mitre",
|
||||
"scan_with_exceptions",
|
||||
"scan_repository",
|
||||
"scan_local_file",
|
||||
"scan_local_glob_files",
|
||||
"scan_local_list_of_files",
|
||||
"scan_with_exception_to_backend",
|
||||
"scan_nsa_and_submit_to_backend",
|
||||
"scan_mitre_and_submit_to_backend",
|
||||
"scan_local_repository_and_submit_to_backend",
|
||||
"scan_repository_from_url_and_submit_to_backend",
|
||||
"scan_with_custom_framework",
|
||||
"scan_customer_configuration",
|
||||
"scan_compliance_score"
|
||||
]'
|
||||
]'
|
||||
COSIGN: true
|
||||
HELM_E2E_TEST: true
|
||||
FORCE: true
|
||||
@@ -214,7 +273,7 @@ jobs:
|
||||
run: chmod +x -R ${{steps.download-artifact.outputs.download-path}}/kubescape-ubuntu-latest
|
||||
|
||||
- name: Checkout systests repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # ratchet:actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: armosec/system-tests
|
||||
path: .
|
||||
@@ -267,5 +326,6 @@ jobs:
|
||||
uses: mikepenz/action-junit-report@6e9933f4a97f4d2b99acef4d7b97924466037882 # ratchet:mikepenz/action-junit-report@v3.6.1
|
||||
if: always() # always run even if the previous step fails
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
report_paths: '**/results_xml_format/**.xml'
|
||||
commit: ${{github.event.workflow_run.head_sha}}
|
||||
|
||||
2
.github/workflows/build-image.yaml
vendored
2
.github/workflows/build-image.yaml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
packages: write
|
||||
contents: read
|
||||
contents: write
|
||||
pull-requests: read
|
||||
uses: kubescape/workflows/.github/workflows/incluster-comp-pr-merged.yaml@main
|
||||
with:
|
||||
|
||||
70
.github/workflows/c-create-release.yaml
vendored
70
.github/workflows/c-create-release.yaml
vendored
@@ -24,8 +24,8 @@ jobs:
|
||||
MAC_OS: macos-latest
|
||||
UBUNTU_OS: ubuntu-latest
|
||||
WINDOWS_OS: windows-latest
|
||||
# permissions:
|
||||
# contents: write
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # ratchet:actions/download-artifact@v3.0.2
|
||||
id: download-artifact
|
||||
@@ -33,41 +33,59 @@ jobs:
|
||||
path: .
|
||||
|
||||
# TODO: kubescape-windows-latest is deprecated and should be removed
|
||||
- name: Get kubescape.exe from kubescape-windows-latest
|
||||
run: cp ./kubescape-${{ env.WINDOWS_OS }}/kubescape-${{ env.WINDOWS_OS }} ./kubescape-${{ env.WINDOWS_OS }}/kubescape.exe
|
||||
- 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
|
||||
|
||||
- name: Set release token
|
||||
id: set-token
|
||||
run: |
|
||||
if [ "${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}" != "" ]; then
|
||||
echo "TOKEN=${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}" >> $GITHUB_ENV;
|
||||
echo "token=${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}" >> $GITHUB_OUTPUT;
|
||||
else
|
||||
echo "TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV;
|
||||
echo "token=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_OUTPUT;
|
||||
fi
|
||||
|
||||
- name: List artifacts
|
||||
run: |
|
||||
find . -type f -print
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # ratchet:softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@975c1b265e11dd76618af1c374e7981f9a6ff44a
|
||||
with:
|
||||
token: ${{ env.TOKEN }}
|
||||
token: ${{ steps.set-token.outputs.token }}
|
||||
name: ${{ inputs.RELEASE_NAME }}
|
||||
tag_name: ${{ inputs.TAG }}
|
||||
body: ${{ github.event.pull_request.body }}
|
||||
draft: ${{ inputs.DRAFT }}
|
||||
fail_on_unmatched_files: true
|
||||
prerelease: false
|
||||
# TODO: kubescape-windows-latest is deprecated and should be removed
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
./kubescape-${{ env.WINDOWS_OS }}/kubescape-${{ env.WINDOWS_OS }}
|
||||
./kubescape-${{ env.MAC_OS }}/kubescape-${{ env.MAC_OS }}
|
||||
./kubescape-${{ env.MAC_OS }}/kubescape-${{ env.MAC_OS }}.sha256
|
||||
./kubescape-${{ env.MAC_OS }}/kubescape-${{ env.MAC_OS }}.tar.gz
|
||||
./kubescape-${{ env.UBUNTU_OS }}/kubescape-${{ env.UBUNTU_OS }}
|
||||
./kubescape-${{ env.UBUNTU_OS }}/kubescape-${{ env.UBUNTU_OS }}.sha256
|
||||
./kubescape-${{ env.UBUNTU_OS }}/kubescape-${{ env.UBUNTU_OS }}.tar.gz
|
||||
./kubescape-${{ env.WINDOWS_OS }}/kubescape.exe
|
||||
./kubescape-${{ env.WINDOWS_OS }}/kubescape-${{ env.WINDOWS_OS }}.sha256
|
||||
./kubescape-${{ env.WINDOWS_OS }}/kubescape-${{ env.WINDOWS_OS }}.tar.gz
|
||||
./kubescapearm64-${{ env.MAC_OS }}/kubescape-arm64-${{ env.MAC_OS }}
|
||||
./kubescapearm64-${{ env.MAC_OS }}/kubescape-arm64-${{ env.MAC_OS }}.sha256
|
||||
./kubescapearm64-${{ env.MAC_OS }}/kubescape-arm64-${{ env.MAC_OS }}.tar.gz
|
||||
./kubescapearm64-${{ env.UBUNTU_OS }}/kubescape-arm64-${{ env.UBUNTU_OS }}
|
||||
./kubescapearm64-${{ env.UBUNTU_OS }}/kubescape-arm64-${{ env.UBUNTU_OS }}.sha256
|
||||
./kubescapearm64-${{ env.UBUNTU_OS }}/kubescape-arm64-${{ env.UBUNTU_OS }}.tar.gz
|
||||
./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
|
||||
|
||||
21
.github/workflows/d-publish-image.yaml
vendored
21
.github/workflows/d-publish-image.yaml
vendored
@@ -1,5 +1,18 @@
|
||||
name: d-publish-image
|
||||
permissions: read-all
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: write
|
||||
deployments: read
|
||||
discussions: read
|
||||
id-token: write
|
||||
issues: read
|
||||
packages: read
|
||||
pages: read
|
||||
pull-requests: read
|
||||
repository-projects: read
|
||||
statuses: read
|
||||
security-events: read
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -46,7 +59,7 @@ jobs:
|
||||
name: Build image and upload to registry
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # ratchet:actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up QEMU
|
||||
@@ -63,9 +76,9 @@ jobs:
|
||||
with:
|
||||
path: .
|
||||
- name: mv kubescape amd64 binary
|
||||
run: mv kubescape-ubuntu-latest/kubescape-ubuntu-latest kubescape-amd64-ubuntu-latest
|
||||
run: mv ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape-ubuntu-latest kubescape-amd64-ubuntu-latest
|
||||
- name: mv kubescape arm64 binary
|
||||
run: mv kubescape-ubuntu-latest/kubescape-arm64-ubuntu-latest kubescape-arm64-ubuntu-latest
|
||||
run: mv ${{steps.download-artifact.outputs.download-path}}/kubescape/kubescape-arm64-ubuntu-latest kubescape-arm64-ubuntu-latest
|
||||
- name: chmod +x
|
||||
run: chmod +x -v kubescape-a*
|
||||
- name: Build and push images
|
||||
|
||||
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
|
||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
||||
@@ -12,14 +12,18 @@ before:
|
||||
- go mod tidy
|
||||
|
||||
builds:
|
||||
- id: "kubescape-cli"
|
||||
goos:
|
||||
- goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- riscv64
|
||||
ldflags:
|
||||
- -s -w
|
||||
- -X "github.com/kubescape/kubescape/v3/core/cautils.BuildNumber={{.Env.RELEASE}}"
|
||||
- -X "github.com/kubescape/kubescape/v3/core/cautils.Client={{.Env.CLIENT}}"
|
||||
binary: >-
|
||||
{{ .ProjectName }}-
|
||||
{{- if eq .Arch "amd64" }}
|
||||
@@ -30,8 +34,11 @@ builds:
|
||||
no_unique_dist_dir: true
|
||||
|
||||
archives:
|
||||
- format: binary
|
||||
id: binaries
|
||||
name_template: >-
|
||||
{{ .Binary }}
|
||||
- format: tar.gz
|
||||
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||
name_template: >-
|
||||
{{ .Binary }}
|
||||
|
||||
@@ -42,5 +49,12 @@ changelog:
|
||||
- "^docs:"
|
||||
- "^test:"
|
||||
|
||||
checksum:
|
||||
ids:
|
||||
- binaries
|
||||
split: true
|
||||
|
||||
sboms:
|
||||
- artifacts: archive
|
||||
- artifacts: binary
|
||||
documents:
|
||||
- "{{ .Binary }}.sbom"
|
||||
|
||||
18
ADOPTERS.md
18
ADOPTERS.md
@@ -1,14 +1,16 @@
|
||||
# Adopters
|
||||
|
||||
# Well-known companies
|
||||
Well-known companies who are using and/or contributing to Kubescape are (in alphabetical order):
|
||||
* Accenture
|
||||
* Amazon.com
|
||||
* IBM
|
||||
* Intel
|
||||
* Meetup
|
||||
* RedHat
|
||||
* Scaleway
|
||||
|
||||
List of well-known companies who are publicly acknowledge using and/or contributing to Kubescape are (in alphabetical order):
|
||||
* AWS uses Kubescape in the security training material [link](https://catalog.workshops.aws/containersecurity/en-US/module2)
|
||||
* Energi Danmark: Publicly talking about how they use Kubescape in their CI/CD pipeline [link](https://www.armosec.io/energi-danmark-business-support/)
|
||||
* Gitpod: Used Kubescape in their SOC2 compliance process [link](https://www.armosec.io/gitpod/)
|
||||
* Intel: using Kubescape for security prioritization [video](https://youtu.be/1iCW1KboypY?si=OjmnshWbpFNVPGJT)
|
||||
* Orange Business: talking about Kubescape/ARMO service they are doing [video](https://www.youtube.com/watch?v=cbJYCUM8578)
|
||||
* Rabobank: talked at KCD Amsterdam about having Kubescape in their technology stack [video](https://youtu.be/oa_YJmjwepI?si=vSrFW6seMKHj2Lze) [image](/docs/img/kcd-amsterdam-rabo.jpg)
|
||||
* VMWare/Bitnami: listing Kubescape in their public image/helm repository [link](https://github.com/bitnami/containers/tree/main/bitnami/kubescape)
|
||||
|
||||
|
||||
# Users
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ _Did you know you can use Kubescape in all these places?_
|
||||
|
||||
## Kubescape-operator Helm-Chart
|
||||
|
||||
Besides the CLI, the Kubescape operator can also be installed via a Helm chart. Installing the Helm chart is an excellent way to begin using Kubescape, as it provides extensive features such as continuous scanning, image vulnerability scanning, runtime analysis, network policy generation, and more. You can find the Helm chart in the [Kubescape-operator documentation](https://kubescape.io/docs/install-helm-chart/).
|
||||
Besides the CLI, the Kubescape operator can also be installed via a Helm chart. Installing the Helm chart is an excellent way to begin using Kubescape, as it provides extensive features such as continuous scanning, image vulnerability scanning, runtime analysis, network policy generation, and more. You can find the Helm chart in the [Kubescape-operator documentation](https://kubescape.io/docs/install-operator/).
|
||||
|
||||
## Kubescape GitHub Action
|
||||
|
||||
@@ -81,7 +81,7 @@ It retrieves Kubernetes objects from the API server and runs a set of [Rego snip
|
||||
|
||||
Kubescape is an open source project, we welcome your feedback and ideas for improvement. We are part of the Kubernetes community and are building more tests and controls as the ecosystem develops.
|
||||
|
||||
We hold [community meetings](https://zoom.us/j/95174063585) on Zoom, on the first Tuesday of every month, at 14:00 GMT. ([See that in your local time zone](https://time.is/compare/1400_in_GMT)).
|
||||
We hold [community meetings](https://zoom.us/j/95174063585) on Zoom, every second week on Tuesdays, at 15:00 CET. ([See that in your local time zone](https://time.is/compare/1500_in_CET)).
|
||||
|
||||
The Kubescape project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ref "github.com/distribution/distribution/reference"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/distribution/reference"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
@@ -97,22 +96,22 @@ func validateImagePatchInfo(patchInfo *metav1.PatchInfo) error {
|
||||
}
|
||||
|
||||
// Parse the image full name to get image name and tag
|
||||
named, err := ref.ParseNamed(patchInfoImage)
|
||||
named, err := reference.ParseNamed(patchInfoImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If no tag or digest is provided, default to 'latest'
|
||||
if ref.IsNameOnly(named) {
|
||||
if reference.IsNameOnly(named) {
|
||||
logger.L().Warning("Image name has no tag or digest, using latest as tag")
|
||||
named = ref.TagNameOnly(named)
|
||||
named = reference.TagNameOnly(named)
|
||||
}
|
||||
patchInfo.Image = named.String()
|
||||
|
||||
// If no patched image tag is provided, default to '<image-tag>-patched'
|
||||
if patchInfo.PatchedImageTag == "" {
|
||||
|
||||
taggedName, ok := named.(ref.Tagged)
|
||||
taggedName, ok := named.(reference.Tagged)
|
||||
if !ok {
|
||||
return errors.New("unexpected error while parsing image tag")
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func initEnvironment() {
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.L().Fatal("failed to to get services from server", helpers.Error(err), helpers.String("server", rootInfo.DiscoveryServerURL))
|
||||
logger.L().Fatal("failed to get services from server", helpers.Error(err), helpers.String("server", rootInfo.DiscoveryServerURL))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ func getFrameworkCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comm
|
||||
|
||||
}
|
||||
if len(args) > 1 {
|
||||
if len(args[1:]) == 0 || args[1] != "-" {
|
||||
if args[1] != "-" {
|
||||
scanInfo.InputPatterns = args[1:]
|
||||
logger.L().Debug("List of input files", helpers.Interface("patterns", scanInfo.InputPatterns))
|
||||
} else { // store stdin to file - do NOT move to separate function !!
|
||||
@@ -112,7 +112,6 @@ func getFrameworkCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comm
|
||||
}
|
||||
}
|
||||
scanInfo.SetScanType(cautils.ScanTypeFramework)
|
||||
scanInfo.FrameworkScan = true
|
||||
|
||||
scanInfo.SetPolicyIdentifiers(frameworks, apisv1.KindFramework)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -32,22 +33,22 @@ func GetUpdateCmd() *cobra.Command {
|
||||
Example: updateCmdExamples,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
ctx := context.TODO()
|
||||
v := cautils.NewVersionCheckHandler()
|
||||
versionCheckRequest := cautils.NewVersionCheckRequest(cautils.BuildNumber, "", "", "update")
|
||||
v := versioncheck.NewVersionCheckHandler()
|
||||
versionCheckRequest := versioncheck.NewVersionCheckRequest("", versioncheck.BuildNumber, "", "", "update", nil)
|
||||
v.CheckLatestVersion(ctx, versionCheckRequest)
|
||||
|
||||
//Checking the user's version of kubescape to the latest release
|
||||
if cautils.BuildNumber == "" || strings.Contains(cautils.BuildNumber, "rc") {
|
||||
if versioncheck.BuildNumber == "" || strings.Contains(versioncheck.BuildNumber, "rc") {
|
||||
//your version is unknown
|
||||
fmt.Printf("Nothing to update: you are running the development version\n")
|
||||
} else if cautils.LatestReleaseVersion == "" {
|
||||
} else if versioncheck.LatestReleaseVersion == "" {
|
||||
//Failed to check for updates
|
||||
logger.L().Info(("Failed to check for updates"))
|
||||
} else if cautils.BuildNumber == cautils.LatestReleaseVersion {
|
||||
logger.L().Info("Failed to check for updates")
|
||||
} else if versioncheck.BuildNumber == versioncheck.LatestReleaseVersion {
|
||||
//your version == latest version
|
||||
logger.L().Info(("Nothing to update: you are running the latest version"), helpers.String("Version", cautils.BuildNumber))
|
||||
logger.L().Info("Nothing to update: you are running the latest version", helpers.String("Version", versioncheck.BuildNumber))
|
||||
} else {
|
||||
fmt.Printf("Version %s is available. Please refer to our installation documentation: %s\n", cautils.LatestReleaseVersion, installationLink)
|
||||
fmt.Printf("Version %s is available. Please refer to our installation documentation: %s\n", versioncheck.LatestReleaseVersion, installationLink)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -15,8 +15,8 @@ func GetVersionCmd() *cobra.Command {
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.TODO()
|
||||
v := cautils.NewIVersionCheckHandler(ctx)
|
||||
versionCheckRequest := cautils.NewVersionCheckRequest(cautils.BuildNumber, "", "", "version")
|
||||
v := versioncheck.NewIVersionCheckHandler(ctx)
|
||||
versionCheckRequest := versioncheck.NewVersionCheckRequest("", versioncheck.BuildNumber, "", "", "version", nil)
|
||||
v.CheckLatestVersion(ctx, versionCheckRequest)
|
||||
fmt.Fprintf(cmd.OutOrStdout(),
|
||||
"Your current version is: %s\n",
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestGetVersionCmd(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cautils.BuildNumber = tt.buildNumber
|
||||
versioncheck.BuildNumber = tt.buildNumber
|
||||
|
||||
if cmd := GetVersionCmd(); cmd != nil {
|
||||
buf := bytes.NewBufferString("")
|
||||
|
||||
21
core/cautils/buildinfo.go
Normal file
21
core/cautils/buildinfo.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
)
|
||||
|
||||
var BuildNumber string
|
||||
var Client string
|
||||
|
||||
func init() {
|
||||
if BuildNumber != "" {
|
||||
versioncheck.BuildNumber = BuildNumber
|
||||
} else {
|
||||
versioncheck.BuildNumber = os.Getenv("RELEASE")
|
||||
}
|
||||
if Client != "" {
|
||||
versioncheck.Client = Client
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ type OPASessionObj struct {
|
||||
OmitRawResources bool // omit raw resources from output
|
||||
SingleResourceScan workloadinterface.IWorkload // single resource scan
|
||||
TopWorkloadsByScore []reporthandling.IResource
|
||||
TemplateMapping map[string]MappingNodes // Map chart obj to template (only for rendering from path)
|
||||
}
|
||||
|
||||
func NewOPASessionObj(ctx context.Context, frameworks []reporthandling.Framework, k8sResources K8SResources, scanInfo *ScanInfo) *OPASessionObj {
|
||||
@@ -74,6 +75,7 @@ func NewOPASessionObj(ctx context.Context, frameworks []reporthandling.Framework
|
||||
SessionID: scanInfo.ScanID,
|
||||
Metadata: scanInfoToScanMetadata(ctx, scanInfo),
|
||||
OmitRawResources: scanInfo.OmitRawResources,
|
||||
TemplateMapping: make(map[string]MappingNodes),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package cautils
|
||||
import (
|
||||
"golang.org/x/mod/semver"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
@@ -63,7 +64,7 @@ func (policies *Policies) Set(frameworks []reporthandling.Framework, excludedRul
|
||||
// 1. Rule is compatible with the current kubescape version
|
||||
// 2. Rule fits the current scanning scope
|
||||
func ShouldSkipRule(control reporthandling.Control, rule reporthandling.PolicyRule, scanningScope reporthandling.ScanningScopeType) bool {
|
||||
if !isRuleKubescapeVersionCompatible(rule.Attributes, BuildNumber) {
|
||||
if !isRuleKubescapeVersionCompatible(rule.Attributes, versioncheck.BuildNumber) {
|
||||
return true
|
||||
}
|
||||
if !isControlFitToScanScope(control, scanningScope) {
|
||||
|
||||
@@ -239,3 +239,59 @@ func TestIsFrameworkFitToScanScope(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var rule_v1_0_131 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useUntilKubescapeVersion": "v1.0.132"}}}
|
||||
var rule_v1_0_132 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.132", "useUntilKubescapeVersion": "v1.0.133"}}}
|
||||
var rule_v1_0_133 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.133", "useUntilKubescapeVersion": "v1.0.134"}}}
|
||||
var rule_v1_0_134 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.134"}}}
|
||||
var rule_invalid_from = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": 1.0135, "useUntilKubescapeVersion": "v1.0.135"}}}
|
||||
var rule_invalid_until = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.135", "useUntilKubescapeVersion": 1.0135}}}
|
||||
|
||||
func TestIsRuleKubescapeVersionCompatible(t *testing.T) {
|
||||
// local build- no build number
|
||||
|
||||
// should not crash when the value of useUntilKubescapeVersion is not a string
|
||||
buildNumberMock := "v1.0.135"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_invalid_from.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_invalid_until.Attributes, buildNumberMock))
|
||||
// should use only rules that don't have "until"
|
||||
buildNumberMock = ""
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.130"
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.132"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.133"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.135"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ type Chart struct {
|
||||
}
|
||||
|
||||
// LoadResourcesFromHelmCharts scans a given path (recursively) for helm charts, renders the templates and returns a map of workloads and a map of chart names
|
||||
func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[string][]workloadinterface.IMetadata, map[string]Chart) {
|
||||
func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[string][]workloadinterface.IMetadata, map[string]Chart, map[string]MappingNodes) {
|
||||
directories, _ := listDirs(basePath)
|
||||
helmDirectories := make([]string, 0)
|
||||
for _, dir := range directories {
|
||||
@@ -49,14 +49,18 @@ func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[stri
|
||||
|
||||
sourceToWorkloads := map[string][]workloadinterface.IMetadata{}
|
||||
sourceToChart := make(map[string]Chart, 0)
|
||||
sourceToNodes := map[string]MappingNodes{}
|
||||
for _, helmDir := range helmDirectories {
|
||||
chart, err := NewHelmChart(helmDir)
|
||||
if err == nil {
|
||||
wls, errs := chart.GetWorkloadsWithDefaultValues()
|
||||
wls, templateToNodes, errs := chart.GetWorkloadsWithDefaultValues()
|
||||
if len(errs) > 0 {
|
||||
logger.L().Ctx(ctx).Warning(fmt.Sprintf("Rendering of Helm chart template '%s', failed: %v", chart.GetName(), errs))
|
||||
continue
|
||||
}
|
||||
for k, v := range templateToNodes {
|
||||
sourceToNodes[k] = v
|
||||
}
|
||||
|
||||
chartName := chart.GetName()
|
||||
for k, v := range wls {
|
||||
@@ -68,7 +72,7 @@ func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[stri
|
||||
}
|
||||
}
|
||||
}
|
||||
return sourceToWorkloads, sourceToChart
|
||||
return sourceToWorkloads, sourceToChart, sourceToNodes
|
||||
}
|
||||
|
||||
// If the contents at given path is a Kustomize Directory, LoadResourcesFromKustomizeDirectory will
|
||||
|
||||
@@ -45,10 +45,11 @@ func TestLoadResourcesFromFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadResourcesFromHelmCharts(t *testing.T) {
|
||||
sourceToWorkloads, sourceToChartName := LoadResourcesFromHelmCharts(context.TODO(), helmChartPath())
|
||||
sourceToWorkloads, sourceToChartName, _ := LoadResourcesFromHelmCharts(context.TODO(), helmChartPath())
|
||||
assert.Equal(t, 6, len(sourceToWorkloads))
|
||||
|
||||
for file, workloads := range sourceToWorkloads {
|
||||
|
||||
assert.Equalf(t, 1, len(workloads), "expected 1 workload in file %s", file)
|
||||
|
||||
w := workloads[0]
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
|
||||
|
||||
"github.com/kubescape/regolibrary/gitregostore"
|
||||
"github.com/kubescape/regolibrary/v2/gitregostore"
|
||||
)
|
||||
|
||||
// =======================================================================================================================
|
||||
@@ -29,7 +29,7 @@ type DownloadReleasedPolicy struct {
|
||||
|
||||
func NewDownloadReleasedPolicy() *DownloadReleasedPolicy {
|
||||
return &DownloadReleasedPolicy{
|
||||
gs: gitregostore.NewDefaultGitRegoStore(-1),
|
||||
gs: gitregostore.NewGitRegoStoreV2(-1),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package cautils
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
@@ -45,22 +46,32 @@ func (hc *HelmChart) GetDefaultValues() map[string]interface{} {
|
||||
}
|
||||
|
||||
// GetWorkloads renders chart template using the default values and returns a map of source file to its workloads
|
||||
func (hc *HelmChart) GetWorkloadsWithDefaultValues() (map[string][]workloadinterface.IMetadata, []error) {
|
||||
func (hc *HelmChart) GetWorkloadsWithDefaultValues() (map[string][]workloadinterface.IMetadata, map[string]MappingNodes, []error) {
|
||||
return hc.GetWorkloads(hc.GetDefaultValues())
|
||||
}
|
||||
|
||||
// GetWorkloads renders chart template using the provided values and returns a map of source (absolute) file path to its workloads
|
||||
func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]workloadinterface.IMetadata, []error) {
|
||||
func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]workloadinterface.IMetadata, map[string]MappingNodes, []error) {
|
||||
vals, err := helmchartutil.ToRenderValues(hc.chart, values, helmchartutil.ReleaseOptions{}, nil)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
return nil, nil, []error{err}
|
||||
}
|
||||
|
||||
// change the chart to template with comment, only is template(.yaml added otherwise no)
|
||||
hc.AddCommentToTemplate()
|
||||
|
||||
sourceToFile, err := helmengine.Render(hc.chart, vals)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
return nil, nil, []error{err}
|
||||
}
|
||||
|
||||
// get the resouse and analysis and store it to the struct
|
||||
fileMapping := make(map[string]MappingNodes)
|
||||
GetTemplateMapping(sourceToFile, fileMapping)
|
||||
|
||||
// delete the comment from chart and from sourceToFile
|
||||
RemoveComment(sourceToFile)
|
||||
|
||||
workloads := make(map[string][]workloadinterface.IMetadata, 0)
|
||||
errs := []error{}
|
||||
|
||||
@@ -76,10 +87,13 @@ func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]w
|
||||
if len(wls) == 0 {
|
||||
continue
|
||||
}
|
||||
// separate base path and file name. We do not use the os.Separator because the paths returned from the helm engine are not OS specific (e.g. mychart/templates/myfile.yaml)
|
||||
if firstPathSeparatorIndex := strings.Index(path, string("/")); firstPathSeparatorIndex != -1 {
|
||||
absPath := filepath.Join(hc.path, path[firstPathSeparatorIndex:])
|
||||
|
||||
if nodes, ok := fileMapping[path]; ok {
|
||||
fileMapping[absPath] = nodes
|
||||
delete(fileMapping, path)
|
||||
}
|
||||
workloads[absPath] = []workloadinterface.IMetadata{}
|
||||
for i := range wls {
|
||||
lw := localworkload.NewLocalWorkload(wls[i].GetObject())
|
||||
@@ -88,5 +102,46 @@ func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]w
|
||||
}
|
||||
}
|
||||
}
|
||||
return workloads, errs
|
||||
return workloads, fileMapping, errs
|
||||
}
|
||||
|
||||
func (hc *HelmChart) AddCommentToTemplate() {
|
||||
for index, t := range hc.chart.Templates {
|
||||
if IsYaml(strings.ToLower(t.Name)) {
|
||||
var newLines []string
|
||||
originalTemplate := string(t.Data)
|
||||
lines := strings.Split(originalTemplate, "\n")
|
||||
|
||||
for index, line := range lines {
|
||||
comment := " #This is the " + strconv.Itoa(index+1) + " line"
|
||||
newLines = append(newLines, line+comment)
|
||||
}
|
||||
templateWithComment := strings.Join(newLines, "\n")
|
||||
hc.chart.Templates[index].Data = []byte(templateWithComment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RemoveComment(sourceToFile map[string]string) {
|
||||
// commentRe := regexp.MustCompile(CommentFormat)
|
||||
for fileName, file := range sourceToFile {
|
||||
if !IsYaml(strings.ToLower((fileName))) {
|
||||
continue
|
||||
}
|
||||
sourceToFile[fileName] = commentRe.ReplaceAllLiteralString(file, "")
|
||||
}
|
||||
}
|
||||
|
||||
func GetTemplateMapping(sourceToFile map[string]string, fileMapping map[string]MappingNodes) {
|
||||
for fileName, fileContent := range sourceToFile {
|
||||
mappingNodes, err := GetMapping(fileName, fileContent)
|
||||
if err != nil {
|
||||
// if one file cannot get mapping nodes, generate error, then ignore it
|
||||
logger.L().Warning("Failed to get File Mapping nodes", helpers.String("file name", fileName), helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
if len(mappingNodes.Nodes) != 0 {
|
||||
fileMapping[fileName] = *mappingNodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (s *HelmChartTestSuite) TestGetWorkloadsWithOverride() {
|
||||
// Override default value
|
||||
values["image"].(map[string]interface{})["pullPolicy"] = "Never"
|
||||
|
||||
fileToWorkloads, errs := chart.GetWorkloads(values)
|
||||
fileToWorkloads, _, errs := chart.GetWorkloads(values)
|
||||
s.Len(errs, 0)
|
||||
|
||||
s.Lenf(fileToWorkloads, len(s.expectedFiles), "Expected %d files", len(s.expectedFiles))
|
||||
@@ -111,7 +111,7 @@ func (s *HelmChartTestSuite) TestGetWorkloadsMissingValue() {
|
||||
values := chart.GetDefaultValues()
|
||||
delete(values, "image")
|
||||
|
||||
fileToWorkloads, errs := chart.GetWorkloads(values)
|
||||
fileToWorkloads, _, errs := chart.GetWorkloads(values)
|
||||
s.Nil(fileToWorkloads)
|
||||
s.Len(errs, 1, "Expected an error due to missing value")
|
||||
|
||||
|
||||
34
core/cautils/mappingnode.go
Normal file
34
core/cautils/mappingnode.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package cautils
|
||||
|
||||
type ObjectID struct {
|
||||
apiVersion string
|
||||
kind string
|
||||
}
|
||||
|
||||
type MappingNode struct {
|
||||
ObjectID *ObjectID
|
||||
Field string
|
||||
Value string
|
||||
TemplateFileName string
|
||||
TemplateLineNumber int
|
||||
}
|
||||
|
||||
type MappingNodes struct {
|
||||
Nodes []map[string]MappingNode //Map line number of chart to template obj map[int]MappingNode
|
||||
TemplateFileName string
|
||||
}
|
||||
|
||||
func (node *MappingNode) writeInfoToNode(objectID *ObjectID, path string, lineNumber int, value string, fileName string) {
|
||||
node.Field = path
|
||||
node.TemplateLineNumber = lineNumber
|
||||
node.ObjectID = objectID
|
||||
node.Value = value
|
||||
node.TemplateFileName = fileName
|
||||
}
|
||||
|
||||
func NewMappingNodes() *MappingNodes {
|
||||
mappingNodes := new(MappingNodes)
|
||||
mappingNodes.TemplateFileName = ""
|
||||
return mappingNodes
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/distribution/reference"
|
||||
)
|
||||
|
||||
func NormalizeImageName(img string) (string, error) {
|
||||
|
||||
266
core/cautils/parseFile.go
Normal file
266
core/cautils/parseFile.go
Normal file
@@ -0,0 +1,266 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
)
|
||||
|
||||
const (
|
||||
CommentFormat = `#This is the (?P<line>\d*) line`
|
||||
)
|
||||
|
||||
var apiVersionRe = regexp.MustCompile(`apiVersion: (?P<apiVersion>\S*)`)
|
||||
var kindRe = regexp.MustCompile(`kind: (?P<kind>\S*)`)
|
||||
var pathRe = regexp.MustCompile(`path: (?P<path>\S*)`)
|
||||
var typeRe = regexp.MustCompile(`type: '(?P<type>\S*)'`)
|
||||
var valueRe = regexp.MustCompile(`value: (?P<value>\[.+\]|\S*)`)
|
||||
var commentRe = regexp.MustCompile(CommentFormat)
|
||||
var seqRe = regexp.MustCompile(`.(?P<number>\d+)(?P<point>\.?)`)
|
||||
var newSeqRe = "[${number}]${point}"
|
||||
var newFileSeperator = "---"
|
||||
|
||||
// change to use go func
|
||||
func GetMapping(fileName string, fileContent string) (*MappingNodes, error) {
|
||||
|
||||
node := new(MappingNode)
|
||||
objectID := new(ObjectID)
|
||||
subFileNodes := make(map[string]MappingNode)
|
||||
mappingNodes := NewMappingNodes()
|
||||
mappingNodes.TemplateFileName = fileName
|
||||
|
||||
lines := strings.Split(fileContent, "\n")
|
||||
|
||||
lastNumber := -1
|
||||
reducedNumber := -1 // uses to make sure line and line in yq is the same
|
||||
|
||||
isApiVersionEmpty := true
|
||||
isKindEmpty := true
|
||||
var err error
|
||||
|
||||
var lineExpression = `..| select(line == %d)| {"destpath": path | join("."),"type": type,"value": .}`
|
||||
|
||||
for i, line := range lines {
|
||||
index := i
|
||||
if apiVersionRe.MatchString(line) {
|
||||
isApiVersionEmpty, err = extractApiVersion(line, objectID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("extractApiVersion error: err, %s", err.Error())
|
||||
}
|
||||
if reducedNumber == -1 {
|
||||
reducedNumber = index + reducedNumber
|
||||
}
|
||||
continue
|
||||
} else if kindRe.MatchString(line) {
|
||||
isKindEmpty, err = extractKind(line, objectID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("extractKind error: err, %s", err.Error())
|
||||
}
|
||||
continue
|
||||
} else if strings.Contains(line, newFileSeperator) { //At least two files in one yaml
|
||||
mappingNodes.Nodes = append(mappingNodes.Nodes, subFileNodes)
|
||||
// Restart a subfileNode
|
||||
isApiVersionEmpty = false
|
||||
isKindEmpty = false
|
||||
subFileNodes = make(map[string]MappingNode)
|
||||
continue
|
||||
}
|
||||
|
||||
if !isApiVersionEmpty || !isKindEmpty {
|
||||
// not sure if it can go to the end
|
||||
index = index - reducedNumber
|
||||
expression := fmt.Sprintf(lineExpression, index)
|
||||
output, err := getYamlLineInfo(expression, fileContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path := extractParameter(pathRe, output, "$path")
|
||||
//if path is empty, continue
|
||||
if path != "" && path != "\"\"" {
|
||||
if isApiVersionEmpty || isKindEmpty {
|
||||
return nil, fmt.Errorf("there is no enough objectID info")
|
||||
}
|
||||
splits := strings.Split(output, "dest")
|
||||
if len(splits) < 2 {
|
||||
return nil, fmt.Errorf("something wrong with the length of the splits, which is %d", len(splits))
|
||||
} else {
|
||||
// cut the redundant one
|
||||
splits = splits[1:]
|
||||
lastNumber, err = writeNodes(splits, lastNumber, fileName, node, objectID, subFileNodes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("writeNodes err: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if i == len(lines)-1 {
|
||||
mappingNodes.Nodes = append(mappingNodes.Nodes, subFileNodes)
|
||||
}
|
||||
}
|
||||
return mappingNodes, nil
|
||||
}
|
||||
|
||||
func writeNodes(splits []string, lastNumber int, fileName string, node *MappingNode, objectID *ObjectID, subFileNodes map[string]MappingNode) (int, error) {
|
||||
for _, split := range splits {
|
||||
path := extractPath(split)
|
||||
mapMatched, err := extractMapType(split)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("extractMapType err: %s", err.Error())
|
||||
}
|
||||
if mapMatched {
|
||||
lastNumber, err = writeNoteToMapping(split, lastNumber, path, fileName, node, objectID, true, subFileNodes)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("map type: writeNoteToMapping, err: %s", err.Error())
|
||||
}
|
||||
|
||||
} else {
|
||||
lastNumber, err = writeNoteToMapping(split, lastNumber, path, fileName, node, objectID, false, subFileNodes)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("not map type: writeNoteToMapping, err: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
return lastNumber, nil
|
||||
}
|
||||
|
||||
func writeNoteToMapping(split string, lastNumber int, path string, fileName string, node *MappingNode, objectID *ObjectID, isMapType bool, subFileNodes map[string]MappingNode) (int, error) {
|
||||
newlastNumber, err := writeNodeInfo(split, lastNumber, path, fileName, node, objectID, isMapType)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("isMapType: %v, writeNodeInfo wrong err: %s", isMapType, err.Error())
|
||||
}
|
||||
if _, ok := subFileNodes[path]; !ok { // Assume the path is unique in one subfile
|
||||
subFileNodes[path] = *node
|
||||
}
|
||||
// else {
|
||||
// return 0, fmt.Errorf("isMapType: %v, %s in mapping.Nodes exists", isMapType, path)
|
||||
// }
|
||||
return newlastNumber, nil
|
||||
}
|
||||
|
||||
func writeNodeInfo(split string, lastNumber int, path string, fileName string, node *MappingNode, objectID *ObjectID, isMapType bool) (int, error) {
|
||||
value, lineNumber, newLastNumber, err := getInfoFromOne(split, lastNumber, isMapType)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("getInfoFromOne wrong err: %s", err.Error())
|
||||
}
|
||||
// lastNumber = newLastNumber
|
||||
node.writeInfoToNode(objectID, path, lineNumber, value, fileName)
|
||||
return newLastNumber, nil
|
||||
}
|
||||
|
||||
func getInfoFromOne(output string, lastNumber int, isMapType bool) (value string, lineNumber int, newLastNumber int, err error) {
|
||||
if isMapType {
|
||||
value = ""
|
||||
} else {
|
||||
value = extractParameter(valueRe, output, "$value")
|
||||
}
|
||||
number := extractParameter(commentRe, output, "$line")
|
||||
if number != "" {
|
||||
lineNumber, err = strconv.Atoi(number)
|
||||
if err != nil {
|
||||
return "", -1, -1, fmt.Errorf("strconv.Atoi err: %s", err.Error())
|
||||
}
|
||||
if isMapType {
|
||||
lineNumber = lineNumber - 1
|
||||
}
|
||||
lastNumber = lineNumber
|
||||
// save to structure
|
||||
} else {
|
||||
lineNumber = lastNumber
|
||||
// use the last one number
|
||||
}
|
||||
newLastNumber = lineNumber
|
||||
return value, lineNumber, newLastNumber, nil
|
||||
}
|
||||
|
||||
func getYamlLineInfo(expression string, yamlFile string) (string, error) {
|
||||
out, err := exectuateYq(expression, yamlFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("exectuate yqlib err: %s", err.Error())
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func exectuateYq(expression string, yamlContent string) (string, error) {
|
||||
|
||||
backendLoggerLeveled := logging.AddModuleLevel(logging.NewLogBackend(logger.L().GetWriter(), "", 0))
|
||||
backendLoggerLeveled.SetLevel(logging.ERROR, "")
|
||||
yqlib.GetLogger().SetBackend(backendLoggerLeveled)
|
||||
|
||||
encoder := configureEncoder()
|
||||
|
||||
decoder := configureDecoder(false)
|
||||
|
||||
stringEvaluator := yqlib.NewStringEvaluator()
|
||||
|
||||
out, err := stringEvaluator.Evaluate(expression, yamlContent, encoder, decoder)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("no matches found")
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
func extractApiVersion(line string, objectID *ObjectID) (bool, error) {
|
||||
apiVersion := extractParameter(apiVersionRe, line, "$apiVersion")
|
||||
if apiVersion == "" {
|
||||
return true, fmt.Errorf("something wrong when extracting the apiVersion, the line is %s", line)
|
||||
}
|
||||
objectID.apiVersion = apiVersion
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func extractKind(line string, objectID *ObjectID) (bool, error) {
|
||||
kind := extractParameter(kindRe, line, "$kind")
|
||||
if kind == "" {
|
||||
return true, fmt.Errorf("something wrong when extracting the kind, the line is %s", line)
|
||||
}
|
||||
objectID.kind = kind
|
||||
return false, nil
|
||||
}
|
||||
func extractPath(split string) string {
|
||||
path := extractParameter(pathRe, split, "$path")
|
||||
// For each match of the regex in the content.
|
||||
path = seqRe.ReplaceAllString(path, newSeqRe)
|
||||
return path
|
||||
}
|
||||
|
||||
func extractMapType(split string) (bool, error) {
|
||||
pathType := extractParameter(typeRe, split, "$type")
|
||||
mapMatched, err := regexp.MatchString(`!!map`, pathType)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("regexp.MatchString err: %s", err.Error())
|
||||
return false, err
|
||||
}
|
||||
return mapMatched, nil
|
||||
}
|
||||
|
||||
func extractParameter(re *regexp.Regexp, line string, keyword string) string {
|
||||
submatch := re.FindStringSubmatchIndex(line)
|
||||
result := []byte{}
|
||||
result = re.ExpandString(result, keyword, line, submatch)
|
||||
parameter := string(result)
|
||||
return parameter
|
||||
}
|
||||
|
||||
//yqlib configuration
|
||||
|
||||
func configureEncoder() yqlib.Encoder {
|
||||
indent := 2
|
||||
colorsEnabled := false
|
||||
yqlibEncoder := yqlib.NewYamlEncoder(indent, colorsEnabled, yqlib.ConfiguredYamlPreferences)
|
||||
return yqlibEncoder
|
||||
}
|
||||
|
||||
func configureDecoder(evaluateTogether bool) yqlib.Decoder {
|
||||
prefs := yqlib.ConfiguredYamlPreferences
|
||||
prefs.EvaluateTogether = evaluateTogether
|
||||
yqlibDecoder := yqlib.NewYamlDecoder(prefs)
|
||||
return yqlibDecoder
|
||||
}
|
||||
79
core/cautils/parseFile_test.go
Normal file
79
core/cautils/parseFile_test.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
helmchartutil "helm.sh/helm/v3/pkg/chartutil"
|
||||
helmengine "helm.sh/helm/v3/pkg/engine"
|
||||
)
|
||||
|
||||
type HelmChartGetMappingSuite struct {
|
||||
suite.Suite
|
||||
helmChartPath string
|
||||
expectedFiles []string
|
||||
fileContent map[string]string
|
||||
}
|
||||
|
||||
func TestHelmChartGetMappingSuite(t *testing.T) {
|
||||
suite.Run(t, new(HelmChartGetMappingSuite))
|
||||
}
|
||||
|
||||
func (s *HelmChartGetMappingSuite) SetupSuite() {
|
||||
o, _ := os.Getwd()
|
||||
|
||||
s.helmChartPath = filepath.Join(filepath.Dir(o), "..", "examples", "helm_chart_mapping_node")
|
||||
|
||||
s.expectedFiles = []string{
|
||||
filepath.Join(s.helmChartPath, "templates", "clusterrolebinding.yaml"),
|
||||
filepath.Join(s.helmChartPath, "templates", "clusterrole.yaml"),
|
||||
filepath.Join(s.helmChartPath, "templates", "serviceaccount.yaml"),
|
||||
filepath.Join(s.helmChartPath, "templates", "rolebinding.yaml"),
|
||||
filepath.Join(s.helmChartPath, "templates", "role.yaml"),
|
||||
filepath.Join(s.helmChartPath, "templates", "cronjob.yaml"),
|
||||
}
|
||||
|
||||
s.fileContent = make(map[string]string)
|
||||
|
||||
hc, _ := NewHelmChart(s.helmChartPath)
|
||||
|
||||
values := hc.GetDefaultValues()
|
||||
|
||||
vals, _ := helmchartutil.ToRenderValues(hc.chart, values, helmchartutil.ReleaseOptions{}, nil)
|
||||
|
||||
sourceToFile, _ := helmengine.Render(hc.chart, vals)
|
||||
|
||||
s.fileContent = sourceToFile
|
||||
|
||||
}
|
||||
|
||||
func (s *HelmChartGetMappingSuite) TestGetMapping() {
|
||||
fileNodes, err := GetMapping("rolebinding.yaml", s.fileContent["kubescape/templates/rolebinding.yaml"])
|
||||
s.NoError(err, "Get Mapping nodes correctly")
|
||||
s.Equal(fileNodes.TemplateFileName, "rolebinding.yaml")
|
||||
s.Len(fileNodes.Nodes, 1)
|
||||
s.Len(fileNodes.Nodes[0], 13)
|
||||
}
|
||||
|
||||
func (s *HelmChartGetMappingSuite) TestGetMappingFromFileContainsMultipleSubFiles() {
|
||||
fileNodes, err := GetMapping("serviceaccount.yaml", s.fileContent["kubescape/templates/serviceaccount.yaml"])
|
||||
s.NoError(err, "Get Mapping nodes correctly")
|
||||
s.Equal(fileNodes.TemplateFileName, "serviceaccount.yaml")
|
||||
s.Len(fileNodes.Nodes, 2)
|
||||
s.Len(fileNodes.Nodes[0], 8)
|
||||
s.Len(fileNodes.Nodes[1], 2)
|
||||
}
|
||||
|
||||
func (s *HelmChartGetMappingSuite) TestGetMappingFromFileCWithoutKindOrApiVersion() {
|
||||
fileNodes, err := GetMapping("clusterrole.yaml", s.fileContent["kubescape/templates/clusterrole.yaml"])
|
||||
s.Contains(err.Error(), "there is no enough objectID info")
|
||||
s.Nil(fileNodes)
|
||||
}
|
||||
|
||||
func (s *HelmChartGetMappingSuite) TestGetMappingFromFileCWithoutApiVersion() {
|
||||
fileNodes, err := GetMapping("clusterrolebinding.yaml", s.fileContent["kubescape/templates/clusterrolebinding.yaml"])
|
||||
s.Contains(err.Error(), "there is no enough objectID info")
|
||||
s.Nil(fileNodes)
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the the correct apiVersion?
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the correct apiVersion?
|
||||
crIMeta := workloadinterface.NewWorkloadObj(crmap)
|
||||
crIMeta.SetKind("ClusterRole")
|
||||
allresources[crIMeta.GetID()] = crIMeta
|
||||
@@ -95,7 +95,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the the correct apiVersion?
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the correct apiVersion?
|
||||
crIMeta := workloadinterface.NewWorkloadObj(crmap)
|
||||
crIMeta.SetKind("Role")
|
||||
allresources[crIMeta.GetID()] = crIMeta
|
||||
@@ -105,7 +105,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the the correct apiVersion?
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the correct apiVersion?
|
||||
crIMeta := workloadinterface.NewWorkloadObj(crmap)
|
||||
crIMeta.SetKind("ClusterRoleBinding")
|
||||
allresources[crIMeta.GetID()] = crIMeta
|
||||
@@ -115,7 +115,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the the correct apiVersion?
|
||||
crmap["apiVersion"] = "rbac.authorization.k8s.io/v1" // TODO - is the correct apiVersion?
|
||||
crIMeta := workloadinterface.NewWorkloadObj(crmap)
|
||||
crIMeta.SetKind("RoleBinding")
|
||||
allresources[crIMeta.GetID()] = crIMeta
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package resourcehandler
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
nethttp "net/http"
|
||||
@@ -12,8 +13,44 @@ import (
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
giturl "github.com/kubescape/go-git-url"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
)
|
||||
|
||||
var tmpDirPaths map[string]string
|
||||
|
||||
func hashRepoURL(repoURL string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(repoURL))
|
||||
return string(h.Sum(nil))
|
||||
}
|
||||
|
||||
func getDirPath(repoURL string) string {
|
||||
if tmpDirPaths == nil {
|
||||
return ""
|
||||
}
|
||||
return tmpDirPaths[hashRepoURL(repoURL)]
|
||||
}
|
||||
|
||||
// Create a temporary directory this function is called once
|
||||
func createTempDir(repoURL string) (string, error) {
|
||||
tmpDirPath := getDirPath(repoURL)
|
||||
if tmpDirPath != "" {
|
||||
return tmpDirPath, nil
|
||||
}
|
||||
// create temp directory
|
||||
tmpDir, err := os.MkdirTemp("", "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create temporary directory: %w", err)
|
||||
}
|
||||
if tmpDirPaths == nil {
|
||||
tmpDirPaths = make(map[string]string)
|
||||
}
|
||||
tmpDirPaths[hashRepoURL(repoURL)] = tmpDir
|
||||
|
||||
return tmpDir, nil
|
||||
}
|
||||
|
||||
// To Check if the given repository is Public(No Authentication needed), send a HTTP GET request to the URL
|
||||
// If response code is 200, the repository is Public.
|
||||
func isGitRepoPublic(u string) bool {
|
||||
@@ -55,34 +92,38 @@ func getProviderError(gitURL giturl.IGitAPI) error {
|
||||
|
||||
// cloneRepo clones a repository to a local temporary directory and returns the directory
|
||||
func cloneRepo(gitURL giturl.IGitAPI) (string, error) {
|
||||
|
||||
// Create temp directory
|
||||
tmpDir, err := os.MkdirTemp("", "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create temporary directory: %w", err)
|
||||
}
|
||||
|
||||
// Get the URL to clone
|
||||
cloneURL := gitURL.GetHttpCloneURL()
|
||||
|
||||
isGitRepoPublic := isGitRepoPublic(cloneURL)
|
||||
// Check if directory exists
|
||||
if p := getDirPath(cloneURL); p != "" {
|
||||
// directory exists, meaning this repo was cloned
|
||||
return p, nil
|
||||
}
|
||||
// Get the URL to clone
|
||||
|
||||
// Create temp directory
|
||||
tmpDir, err := createTempDir(cloneURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
isGitTokenPresent := isGitTokenPresent(gitURL)
|
||||
|
||||
// Declare the authentication variable required for cloneOptions
|
||||
var auth transport.AuthMethod
|
||||
|
||||
if isGitRepoPublic {
|
||||
// No authentication needed if repository is public
|
||||
auth = nil
|
||||
} else {
|
||||
|
||||
// Return Error if the AUTH_TOKEN is not present
|
||||
if isGitTokenPresent := isGitTokenPresent(gitURL); !isGitTokenPresent {
|
||||
return "", getProviderError(gitURL)
|
||||
}
|
||||
if isGitTokenPresent {
|
||||
auth = &http.BasicAuth{
|
||||
Username: "x-token-auth",
|
||||
Password: gitURL.GetToken(),
|
||||
}
|
||||
} else {
|
||||
// If the repository is public, no authentication is needed
|
||||
if isGitRepoPublic(cloneURL) {
|
||||
auth = nil
|
||||
} else {
|
||||
return "", getProviderError(gitURL)
|
||||
}
|
||||
}
|
||||
|
||||
// For Azure repo cloning
|
||||
@@ -102,6 +143,42 @@ func cloneRepo(gitURL giturl.IGitAPI) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to clone %s. %w", gitURL.GetRepoName(), err)
|
||||
}
|
||||
// tmpDir = filepath.Join(tmpDir, gitURL.GetRepoName())
|
||||
tmpDirPaths[hashRepoURL(cloneURL)] = tmpDir
|
||||
|
||||
return tmpDir, nil
|
||||
}
|
||||
|
||||
// CloneGitRepo clone git repository
|
||||
func CloneGitRepo(path *string) (string, error) {
|
||||
var clonedDir string
|
||||
|
||||
gitURL, err := giturl.NewGitAPI(*path)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Clone git repository if needed
|
||||
logger.L().Start("cloning", helpers.String("repository url", gitURL.GetURL().String()))
|
||||
|
||||
clonedDir, err = cloneRepo(gitURL)
|
||||
if err != nil {
|
||||
logger.L().StopError("failed to clone git repo", helpers.String("url", gitURL.GetURL().String()), helpers.Error(err))
|
||||
return "", fmt.Errorf("failed to clone git repo '%s', %w", gitURL.GetURL().String(), err)
|
||||
}
|
||||
*path = clonedDir
|
||||
|
||||
logger.L().StopSuccess("Done accessing remote repo")
|
||||
|
||||
return clonedDir, nil
|
||||
}
|
||||
|
||||
func GetClonedPath(path string) string {
|
||||
|
||||
gitURL, err := giturl.NewGitAPI(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return getDirPath(gitURL.GetHttpCloneURL())
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package resourcehandler
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -93,3 +93,63 @@ func TestCloneRepo(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestGetClonedPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
path string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "Valid Git URL",
|
||||
path: "https://github.com/kubescape/kubescape.git",
|
||||
expected: "/path/to/cloned/repo", // replace with the expected path
|
||||
},
|
||||
{
|
||||
name: "Invalid Git URL",
|
||||
path: "invalid",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
tmpDirPaths = make(map[string]string)
|
||||
tmpDirPaths[hashRepoURL("https://github.com/kubescape/kubescape.git")] = "/path/to/cloned/repo" // replace with the actual path
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := GetClonedPath(tc.path)
|
||||
if result != tc.expected {
|
||||
t.Errorf("Expected %q, got %q", tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestGetDirPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
repoURL string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "Existing Repo URL",
|
||||
repoURL: "https://github.com/user/repo.git",
|
||||
expected: "/path/to/cloned/repo", // replace with the expected path
|
||||
},
|
||||
{
|
||||
name: "Non-Existing Repo URL",
|
||||
repoURL: "https://github.com/user/nonexistentrepo.git",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
// Initialize tmpDirPaths
|
||||
tmpDirPaths = make(map[string]string)
|
||||
tmpDirPaths[hashRepoURL("https://github.com/user/repo.git")] = "/path/to/cloned/repo" // replace with the actual path
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := getDirPath(tc.repoURL)
|
||||
if result != tc.expected {
|
||||
t.Errorf("Expected %q, got %q", tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
giturl "github.com/kubescape/go-git-url"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
@@ -24,20 +25,17 @@ import (
|
||||
type ScanningContext string
|
||||
|
||||
const (
|
||||
ContextCluster ScanningContext = "cluster"
|
||||
ContextFile ScanningContext = "single-file"
|
||||
ContextDir ScanningContext = "local-dir"
|
||||
ContextGitURL ScanningContext = "git-url"
|
||||
ContextGitLocal ScanningContext = "git-local"
|
||||
ContextCluster ScanningContext = "cluster"
|
||||
ContextFile ScanningContext = "single-file"
|
||||
ContextDir ScanningContext = "local-dir"
|
||||
ContextGitLocal ScanningContext = "git-local"
|
||||
ContextGitRemote ScanningContext = "git-remote"
|
||||
)
|
||||
|
||||
const ( // deprecated
|
||||
ScopeCluster = "cluster"
|
||||
ScopeYAML = "yaml"
|
||||
)
|
||||
const (
|
||||
// ScanCluster string = "cluster"
|
||||
// ScanLocalFiles string = "yaml"
|
||||
localControlInputsFilename string = "controls-inputs.json"
|
||||
LocalExceptionsFilename string = "exceptions.json"
|
||||
LocalAttackTracksFilename string = "attack-tracks.json"
|
||||
@@ -110,8 +108,8 @@ type ScanInfo struct {
|
||||
UseFrom []string // Load framework from local file (instead of download). Use when running offline
|
||||
UseDefault bool // Load framework from cached file (instead of download). Use when running offline
|
||||
UseArtifactsFrom string // Load artifacts from local path. Use when running offline
|
||||
VerboseMode bool // Display all of the input resources and not only failed resources
|
||||
View string // Display all of the input resources and not only failed resources
|
||||
VerboseMode bool // Display all the input resources and not only failed resources
|
||||
View string //
|
||||
Format string // Format results (table, json, junit ...)
|
||||
Output string // Store results in an output file, Output file name
|
||||
FormatVersion string // Output object can be different between versions, this is for testing and backward compatibility
|
||||
@@ -140,6 +138,8 @@ type ScanInfo struct {
|
||||
ScanImages bool
|
||||
ChartPath string
|
||||
FilePath string
|
||||
scanningContext *ScanningContext
|
||||
cleanups []func()
|
||||
}
|
||||
|
||||
type Getters struct {
|
||||
@@ -155,7 +155,12 @@ func (scanInfo *ScanInfo) Init(ctx context.Context) {
|
||||
if scanInfo.ScanID == "" {
|
||||
scanInfo.ScanID = uuid.NewString()
|
||||
}
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) Cleanup() {
|
||||
for _, cleanup := range scanInfo.cleanups {
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) setUseArtifactsFrom(ctx context.Context) {
|
||||
@@ -259,7 +264,7 @@ func scanInfoToScanMetadata(ctx context.Context, scanInfo *ScanInfo) *reporthand
|
||||
metadata.ScanMetadata.TargetNames = append(metadata.ScanMetadata.TargetNames, policy.Identifier)
|
||||
}
|
||||
|
||||
metadata.ScanMetadata.KubescapeVersion = BuildNumber
|
||||
metadata.ScanMetadata.KubescapeVersion = versioncheck.BuildNumber
|
||||
metadata.ScanMetadata.VerboseMode = scanInfo.VerboseMode
|
||||
metadata.ScanMetadata.FailThreshold = scanInfo.FailThreshold
|
||||
metadata.ScanMetadata.ComplianceThreshold = scanInfo.ComplianceThreshold
|
||||
@@ -267,51 +272,63 @@ func scanInfoToScanMetadata(ctx context.Context, scanInfo *ScanInfo) *reporthand
|
||||
metadata.ScanMetadata.VerboseMode = scanInfo.VerboseMode
|
||||
metadata.ScanMetadata.ControlsInputs = scanInfo.ControlsInputs
|
||||
|
||||
inputFiles := ""
|
||||
if len(scanInfo.InputPatterns) > 0 {
|
||||
inputFiles = scanInfo.InputPatterns[0]
|
||||
}
|
||||
switch GetScanningContext(inputFiles) {
|
||||
switch scanInfo.GetScanningContext() {
|
||||
case ContextCluster:
|
||||
// cluster
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Cluster
|
||||
case ContextFile:
|
||||
// local file
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.File
|
||||
case ContextGitURL:
|
||||
// url
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Repo
|
||||
case ContextGitLocal:
|
||||
// local-git
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.GitLocal
|
||||
case ContextGitRemote:
|
||||
// remote
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Repo
|
||||
case ContextDir:
|
||||
// directory
|
||||
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Directory
|
||||
|
||||
}
|
||||
|
||||
setContextMetadata(ctx, &metadata.ContextMetadata, inputFiles)
|
||||
scanInfo.setContextMetadata(ctx, &metadata.ContextMetadata)
|
||||
|
||||
return metadata
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) GetScanningContext() ScanningContext {
|
||||
func (scanInfo *ScanInfo) GetInputFiles() string {
|
||||
if len(scanInfo.InputPatterns) > 0 {
|
||||
return GetScanningContext(scanInfo.InputPatterns[0])
|
||||
return scanInfo.InputPatterns[0]
|
||||
}
|
||||
return GetScanningContext("")
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetScanningContext get scanning context from the input param
|
||||
func GetScanningContext(input string) ScanningContext {
|
||||
func (scanInfo *ScanInfo) GetScanningContext() ScanningContext {
|
||||
if scanInfo.scanningContext == nil {
|
||||
scanningContext := scanInfo.getScanningContext(scanInfo.GetInputFiles())
|
||||
scanInfo.scanningContext = &scanningContext
|
||||
}
|
||||
return *scanInfo.scanningContext
|
||||
}
|
||||
|
||||
// getScanningContext get scanning context from the input param
|
||||
// this function should be called only once. Call GetScanningContext() to get the scanning context
|
||||
func (scanInfo *ScanInfo) getScanningContext(input string) ScanningContext {
|
||||
// cluster
|
||||
if input == "" {
|
||||
return ContextCluster
|
||||
}
|
||||
|
||||
// url
|
||||
// git url
|
||||
if _, err := giturl.NewGitURL(input); err == nil {
|
||||
return ContextGitURL
|
||||
if repo, err := CloneGitRepo(&input); err == nil {
|
||||
if _, err := NewLocalGitRepository(repo); err == nil {
|
||||
scanInfo.cleanups = append(scanInfo.cleanups, func() {
|
||||
_ = os.RemoveAll(repo)
|
||||
})
|
||||
return ContextGitRemote
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(input) { // parse path
|
||||
@@ -333,19 +350,14 @@ func GetScanningContext(input string) ScanningContext {
|
||||
// dir/glob
|
||||
return ContextDir
|
||||
}
|
||||
func setContextMetadata(ctx context.Context, contextMetadata *reporthandlingv2.ContextMetadata, input string) {
|
||||
switch GetScanningContext(input) {
|
||||
|
||||
func (scanInfo *ScanInfo) setContextMetadata(ctx context.Context, contextMetadata *reporthandlingv2.ContextMetadata) {
|
||||
input := scanInfo.GetInputFiles()
|
||||
switch scanInfo.GetScanningContext() {
|
||||
case ContextCluster:
|
||||
contextMetadata.ClusterContextMetadata = &reporthandlingv2.ClusterMetadata{
|
||||
ContextName: k8sinterface.GetContextName(),
|
||||
}
|
||||
case ContextGitURL:
|
||||
// url
|
||||
context, err := metadataGitURL(input)
|
||||
if err != nil {
|
||||
logger.L().Ctx(ctx).Warning("in setContextMetadata", helpers.Interface("case", ContextGitURL), helpers.Error(err))
|
||||
}
|
||||
contextMetadata.RepoContextMetadata = context
|
||||
case ContextDir:
|
||||
contextMetadata.DirectoryContextMetadata = &reporthandlingv2.DirectoryContextMetadata{
|
||||
BasePath: getAbsPath(input),
|
||||
@@ -377,43 +389,21 @@ func setContextMetadata(ctx context.Context, contextMetadata *reporthandlingv2.C
|
||||
}
|
||||
case ContextGitLocal:
|
||||
// local
|
||||
context, err := metadataGitLocal(input)
|
||||
repoContext, err := metadataGitLocal(input)
|
||||
if err != nil {
|
||||
logger.L().Ctx(ctx).Warning("in setContextMetadata", helpers.Interface("case", ContextGitURL), helpers.Error(err))
|
||||
logger.L().Ctx(ctx).Warning("in setContextMetadata", helpers.Interface("case", ContextGitLocal), helpers.Error(err))
|
||||
}
|
||||
contextMetadata.RepoContextMetadata = context
|
||||
contextMetadata.RepoContextMetadata = repoContext
|
||||
case ContextGitRemote:
|
||||
// remote
|
||||
repoContext, err := metadataGitLocal(GetClonedPath(input))
|
||||
if err != nil {
|
||||
logger.L().Ctx(ctx).Warning("in setContextMetadata", helpers.Interface("case", ContextGitRemote), helpers.Error(err))
|
||||
}
|
||||
contextMetadata.RepoContextMetadata = repoContext
|
||||
}
|
||||
}
|
||||
|
||||
func metadataGitURL(input string) (*reporthandlingv2.RepoContextMetadata, error) {
|
||||
context := &reporthandlingv2.RepoContextMetadata{}
|
||||
gitParser, err := giturl.NewGitAPI(input)
|
||||
if err != nil {
|
||||
return context, fmt.Errorf("%w", err)
|
||||
}
|
||||
if gitParser.GetBranchName() == "" {
|
||||
gitParser.SetDefaultBranchName()
|
||||
}
|
||||
context.Provider = gitParser.GetProvider()
|
||||
context.Repo = gitParser.GetRepoName()
|
||||
context.Owner = gitParser.GetOwnerName()
|
||||
context.Branch = gitParser.GetBranchName()
|
||||
context.RemoteURL = gitParser.GetURL().String()
|
||||
|
||||
commit, err := gitParser.GetLatestCommit()
|
||||
if err != nil {
|
||||
return context, fmt.Errorf("%w", err)
|
||||
}
|
||||
|
||||
context.LastCommit = reporthandling.LastCommit{
|
||||
Hash: commit.SHA,
|
||||
Date: commit.Committer.Date,
|
||||
CommitterName: commit.Committer.Name,
|
||||
}
|
||||
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func metadataGitLocal(input string) (*reporthandlingv2.RepoContextMetadata, error) {
|
||||
gitParser, err := NewLocalGitRepository(input)
|
||||
if err != nil {
|
||||
@@ -423,31 +413,31 @@ func metadataGitLocal(input string) (*reporthandlingv2.RepoContextMetadata, erro
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w", err)
|
||||
}
|
||||
context := &reporthandlingv2.RepoContextMetadata{}
|
||||
repoContext := &reporthandlingv2.RepoContextMetadata{}
|
||||
gitParserURL, err := giturl.NewGitURL(remoteURL)
|
||||
if err != nil {
|
||||
return context, fmt.Errorf("%w", err)
|
||||
return repoContext, fmt.Errorf("%w", err)
|
||||
}
|
||||
gitParserURL.SetBranchName(gitParser.GetBranchName())
|
||||
|
||||
context.Provider = gitParserURL.GetProvider()
|
||||
context.Repo = gitParserURL.GetRepoName()
|
||||
context.Owner = gitParserURL.GetOwnerName()
|
||||
context.Branch = gitParserURL.GetBranchName()
|
||||
context.RemoteURL = gitParserURL.GetURL().String()
|
||||
repoContext.Provider = gitParserURL.GetProvider()
|
||||
repoContext.Repo = gitParserURL.GetRepoName()
|
||||
repoContext.Owner = gitParserURL.GetOwnerName()
|
||||
repoContext.Branch = gitParserURL.GetBranchName()
|
||||
repoContext.RemoteURL = gitParserURL.GetURL().String()
|
||||
|
||||
commit, err := gitParser.GetLastCommit()
|
||||
if err != nil {
|
||||
return context, fmt.Errorf("%w", err)
|
||||
return repoContext, fmt.Errorf("%w", err)
|
||||
}
|
||||
context.LastCommit = reporthandling.LastCommit{
|
||||
repoContext.LastCommit = reporthandling.LastCommit{
|
||||
Hash: commit.SHA,
|
||||
Date: commit.Committer.Date,
|
||||
CommitterName: commit.Committer.Name,
|
||||
}
|
||||
context.LocalRootPath, _ = gitParser.GetRootDir()
|
||||
repoContext.LocalRootPath, _ = gitParser.GetRootDir()
|
||||
|
||||
return context, nil
|
||||
return repoContext, nil
|
||||
}
|
||||
func getHostname() string {
|
||||
if h, e := os.Hostname(); e == nil {
|
||||
@@ -464,11 +454,3 @@ func getAbsPath(p string) string {
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ScanningContextToScanningScope convert the context to the deprecated scope
|
||||
func ScanningContextToScanningScope(scanningContext ScanningContext) string {
|
||||
if scanningContext == ContextCluster {
|
||||
return ScopeCluster
|
||||
}
|
||||
return ScopeYAML
|
||||
}
|
||||
|
||||
@@ -3,17 +3,19 @@ package cautils
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSetContextMetadata(t *testing.T) {
|
||||
{
|
||||
ctx := reporthandlingv2.ContextMetadata{}
|
||||
setContextMetadata(context.TODO(), &ctx, "")
|
||||
scanInfo := &ScanInfo{}
|
||||
scanInfo.setContextMetadata(context.TODO(), &ctx)
|
||||
|
||||
assert.NotNil(t, ctx.ClusterContextMetadata)
|
||||
assert.Nil(t, ctx.DirectoryContextMetadata)
|
||||
@@ -42,13 +44,57 @@ func TestGetHostname(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetScanningContext(t *testing.T) {
|
||||
// Test with empty input
|
||||
assert.Equal(t, ContextCluster, GetScanningContext(""))
|
||||
|
||||
// Test with Git URL input
|
||||
assert.Equal(t, ContextGitURL, GetScanningContext("https://github.com/kubescape/kubescape"))
|
||||
|
||||
// TODO: Add more tests with other input types
|
||||
repoRoot, err := os.MkdirTemp("", "repo")
|
||||
require.NoError(t, err)
|
||||
defer func(name string) {
|
||||
_ = os.Remove(name)
|
||||
}(repoRoot)
|
||||
_, err = git.PlainClone(repoRoot, false, &git.CloneOptions{
|
||||
URL: "https://github.com/kubescape/http-request",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
tmpFile, err := os.CreateTemp("", "single.*.txt")
|
||||
require.NoError(t, err)
|
||||
defer func(name string) {
|
||||
_ = os.Remove(name)
|
||||
}(tmpFile.Name())
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want ScanningContext
|
||||
}{
|
||||
{
|
||||
name: "empty input",
|
||||
input: "",
|
||||
want: ContextCluster,
|
||||
},
|
||||
{
|
||||
name: "git URL input",
|
||||
input: "https://github.com/kubescape/http-request",
|
||||
want: ContextGitRemote,
|
||||
},
|
||||
{
|
||||
name: "local git input",
|
||||
input: repoRoot,
|
||||
want: ContextGitLocal,
|
||||
},
|
||||
{
|
||||
name: "single file input",
|
||||
input: tmpFile.Name(),
|
||||
want: ContextFile,
|
||||
},
|
||||
{
|
||||
name: "directory input",
|
||||
input: os.TempDir(),
|
||||
want: ContextDir,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
scanInfo := &ScanInfo{}
|
||||
assert.Equalf(t, tt.want, scanInfo.getScanningContext(tt.input), "GetScanningContext(%v)", tt.input)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanInfoFormats(t *testing.T) {
|
||||
@@ -77,30 +123,3 @@ func TestScanInfoFormats(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetScanningContextWithFile(t *testing.T) {
|
||||
// Test with a file
|
||||
dir, err := os.MkdirTemp("", "example")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
filePath := filepath.Join(dir, "file.txt")
|
||||
if _, err := os.Create(filePath); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, ContextFile, GetScanningContext(filePath))
|
||||
}
|
||||
|
||||
func TestGetScanningContextWithDir(t *testing.T) {
|
||||
// Test with a directory
|
||||
dir, err := os.MkdirTemp("", "example")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
assert.Equal(t, ContextDir, GetScanningContext(dir))
|
||||
}
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/utils-go/boolutils"
|
||||
utils "github.com/kubescape/backend/pkg/utils"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
"github.com/mattn/go-isatty"
|
||||
"go.opentelemetry.io/otel"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
const SKIP_VERSION_CHECK_DEPRECATED_ENV = "KUBESCAPE_SKIP_UPDATE_CHECK"
|
||||
const SKIP_VERSION_CHECK_ENV = "KS_SKIP_UPDATE_CHECK"
|
||||
const CLIENT_ENV = "KS_CLIENT"
|
||||
|
||||
var BuildNumber string
|
||||
var Client string
|
||||
var LatestReleaseVersion string
|
||||
|
||||
const UnknownBuildNumber = "unknown"
|
||||
|
||||
type IVersionCheckHandler interface {
|
||||
CheckLatestVersion(context.Context, *VersionCheckRequest) error
|
||||
}
|
||||
|
||||
func NewIVersionCheckHandler(ctx context.Context) IVersionCheckHandler {
|
||||
if BuildNumber == "" {
|
||||
logger.L().Ctx(ctx).Warning("Unknown build number: this might affect your scan results. Please ensure that you are running the latest version.")
|
||||
}
|
||||
|
||||
if v, ok := os.LookupEnv(CLIENT_ENV); ok && v != "" {
|
||||
Client = v
|
||||
}
|
||||
|
||||
if v, ok := os.LookupEnv(SKIP_VERSION_CHECK_ENV); ok && boolutils.StringToBool(v) {
|
||||
return NewVersionCheckHandlerMock()
|
||||
} else if v, ok := os.LookupEnv(SKIP_VERSION_CHECK_DEPRECATED_ENV); ok && boolutils.StringToBool(v) {
|
||||
return NewVersionCheckHandlerMock()
|
||||
}
|
||||
return NewVersionCheckHandler()
|
||||
}
|
||||
|
||||
type VersionCheckHandlerMock struct {
|
||||
}
|
||||
|
||||
func NewVersionCheckHandlerMock() *VersionCheckHandlerMock {
|
||||
return &VersionCheckHandlerMock{}
|
||||
}
|
||||
|
||||
type VersionCheckHandler struct {
|
||||
versionURL string
|
||||
}
|
||||
type VersionCheckRequest struct {
|
||||
Client string `json:"client"` // kubescape
|
||||
ClientBuild string `json:"clientBuild"` // client build environment
|
||||
ClientVersion string `json:"clientVersion"` // kubescape version
|
||||
Framework string `json:"framework"` // framework name
|
||||
FrameworkVersion string `json:"frameworkVersion"` // framework version
|
||||
ScanningTarget string `json:"target"` // Deprecated
|
||||
ScanningContext string `json:"context"` // scanning context- cluster/file/gitURL/localGit/dir
|
||||
TriggeredBy string `json:"triggeredBy"` // triggered by - cli/ ci / microservice
|
||||
}
|
||||
|
||||
type VersionCheckResponse struct {
|
||||
Client string `json:"client"` // kubescape
|
||||
ClientUpdate string `json:"clientUpdate"` // kubescape latest version
|
||||
Framework string `json:"framework"` // framework name
|
||||
FrameworkUpdate string `json:"frameworkUpdate"` // framework latest version
|
||||
Message string `json:"message"` // alert message
|
||||
}
|
||||
|
||||
func NewVersionCheckHandler() *VersionCheckHandler {
|
||||
return &VersionCheckHandler{
|
||||
versionURL: "https://us-central1-elated-pottery-310110.cloudfunctions.net/ksgf1v1",
|
||||
}
|
||||
}
|
||||
|
||||
func getTriggerSource() string {
|
||||
if strings.Contains(os.Args[0], "ksserver") {
|
||||
return "microservice"
|
||||
}
|
||||
|
||||
if !isatty.IsTerminal(os.Stdin.Fd()) && !isatty.IsCygwinTerminal(os.Stdin.Fd()) {
|
||||
// non-interactive shell
|
||||
return "pipeline"
|
||||
}
|
||||
|
||||
if os.Getenv("GITHUB_ACTIONS") == "true" {
|
||||
return "pipeline"
|
||||
}
|
||||
|
||||
return "cli"
|
||||
}
|
||||
|
||||
func NewVersionCheckRequest(buildNumber, frameworkName, frameworkVersion, scanningTarget string) *VersionCheckRequest {
|
||||
if buildNumber == "" {
|
||||
buildNumber = UnknownBuildNumber
|
||||
}
|
||||
|
||||
if scanningTarget == "" {
|
||||
scanningTarget = "unknown"
|
||||
}
|
||||
|
||||
if Client == "" {
|
||||
Client = "local-build"
|
||||
}
|
||||
|
||||
return &VersionCheckRequest{
|
||||
Client: "kubescape",
|
||||
ClientBuild: Client,
|
||||
ClientVersion: buildNumber,
|
||||
Framework: frameworkName,
|
||||
FrameworkVersion: frameworkVersion,
|
||||
ScanningTarget: scanningTarget,
|
||||
TriggeredBy: getTriggerSource(),
|
||||
}
|
||||
}
|
||||
|
||||
func (v *VersionCheckHandlerMock) CheckLatestVersion(_ context.Context, _ *VersionCheckRequest) error {
|
||||
logger.L().Info("Skipping version check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VersionCheckHandler) CheckLatestVersion(ctx context.Context, versionData *VersionCheckRequest) error {
|
||||
ctx, span := otel.Tracer("").Start(ctx, "versionCheckHandler.CheckLatestVersion")
|
||||
defer span.End()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.L().Ctx(ctx).Warning("failed to get latest version", helpers.Interface("error", err))
|
||||
}
|
||||
}()
|
||||
|
||||
latestVersion, err := v.getLatestVersion(versionData)
|
||||
if err != nil || latestVersion == nil {
|
||||
return fmt.Errorf("failed to get latest version")
|
||||
}
|
||||
|
||||
LatestReleaseVersion = latestVersion.ClientUpdate
|
||||
|
||||
if latestVersion.ClientUpdate != "" {
|
||||
if BuildNumber != "" && semver.Compare(BuildNumber, LatestReleaseVersion) == -1 {
|
||||
logger.L().Ctx(ctx).Warning(warningMessage(LatestReleaseVersion))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - Enable after supporting framework version
|
||||
// if latestVersion.FrameworkUpdate != "" {
|
||||
// fmt.Println(warningMessage(latestVersion.Framework, latestVersion.FrameworkUpdate))
|
||||
// }
|
||||
|
||||
if latestVersion.Message != "" {
|
||||
logger.L().Info(latestVersion.Message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VersionCheckHandler) getLatestVersion(versionData *VersionCheckRequest) (*VersionCheckResponse, error) {
|
||||
|
||||
reqBody, err := json.Marshal(*versionData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in 'CheckLatestVersion' failed to json.Marshal, reason: %s", err.Error())
|
||||
}
|
||||
|
||||
rdr, _, err := getter.HTTPPost(http.DefaultClient, v.versionURL, reqBody, map[string]string{"Content-Type": "application/json"})
|
||||
|
||||
vResp, err := utils.Decode[*VersionCheckResponse](rdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vResp, nil
|
||||
}
|
||||
|
||||
func warningMessage(release string) string {
|
||||
return fmt.Sprintf("current version '%s' is not updated to the latest release: '%s'", BuildNumber, release)
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
func TestGetKubernetesObjects(t *testing.T) {
|
||||
}
|
||||
|
||||
var rule_v1_0_131 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useUntilKubescapeVersion": "v1.0.132"}}}
|
||||
var rule_v1_0_132 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.132", "useUntilKubescapeVersion": "v1.0.133"}}}
|
||||
var rule_v1_0_133 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.133", "useUntilKubescapeVersion": "v1.0.134"}}}
|
||||
var rule_v1_0_134 = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.134"}}}
|
||||
var rule_invalid_from = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": 1.0135, "useUntilKubescapeVersion": "v1.0.135"}}}
|
||||
var rule_invalid_until = &reporthandling.PolicyRule{PortalBase: armotypes.PortalBase{
|
||||
Attributes: map[string]interface{}{"useFromKubescapeVersion": "v1.0.135", "useUntilKubescapeVersion": 1.0135}}}
|
||||
|
||||
func TestIsRuleKubescapeVersionCompatible(t *testing.T) {
|
||||
// local build- no build number
|
||||
|
||||
// should not crash when the value of useUntilKubescapeVersion is not a string
|
||||
buildNumberMock := "v1.0.135"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_invalid_from.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_invalid_until.Attributes, buildNumberMock))
|
||||
// should use only rules that don't have "until"
|
||||
buildNumberMock = ""
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.130"
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.132"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.133"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
|
||||
// should only use rules that version is in range of use
|
||||
buildNumberMock = "v1.0.135"
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_131.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_132.Attributes, buildNumberMock))
|
||||
assert.False(t, isRuleKubescapeVersionCompatible(rule_v1_0_133.Attributes, buildNumberMock))
|
||||
assert.True(t, isRuleKubescapeVersionCompatible(rule_v1_0_134.Attributes, buildNumberMock))
|
||||
}
|
||||
|
||||
func TestCheckLatestVersion_Semver_Compare(t *testing.T) {
|
||||
assert.Equal(t, -1, semver.Compare("v2.0.150", "v2.0.151"))
|
||||
assert.Equal(t, 0, semver.Compare("v2.0.150", "v2.0.150"))
|
||||
assert.Equal(t, 1, semver.Compare("v2.0.150", "v2.0.149"))
|
||||
assert.Equal(t, -1, semver.Compare("v2.0.150", "v3.0.150"))
|
||||
|
||||
}
|
||||
|
||||
func TestCheckLatestVersion(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
versionData *VersionCheckRequest
|
||||
versionURL string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "Get latest version",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
versionData: &VersionCheckRequest{},
|
||||
versionURL: "https://us-central1-elated-pottery-310110.cloudfunctions.net/ksgf1v1",
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "Failed to get latest version",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
versionData: &VersionCheckRequest{},
|
||||
versionURL: "https://example.com",
|
||||
},
|
||||
err: fmt.Errorf("failed to get latest version"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := &VersionCheckHandler{
|
||||
versionURL: tt.args.versionURL,
|
||||
}
|
||||
err := v.CheckLatestVersion(tt.args.ctx, tt.args.versionData)
|
||||
|
||||
assert.Equal(t, tt.err, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionCheckHandler_getLatestVersion(t *testing.T) {
|
||||
type fields struct {
|
||||
versionURL string
|
||||
}
|
||||
type args struct {
|
||||
versionData *VersionCheckRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want *VersionCheckResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Get latest version",
|
||||
fields: fields{
|
||||
versionURL: "https://us-central1-elated-pottery-310110.cloudfunctions.net/ksgf1v1",
|
||||
},
|
||||
args: args{
|
||||
versionData: &VersionCheckRequest{
|
||||
Client: "kubescape",
|
||||
},
|
||||
},
|
||||
want: &VersionCheckResponse{
|
||||
Client: "kubescape",
|
||||
ClientUpdate: "v3.0.0",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Failed to get latest version",
|
||||
fields: fields{
|
||||
versionURL: "https://example.com",
|
||||
},
|
||||
args: args{
|
||||
versionData: &VersionCheckRequest{},
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := &VersionCheckHandler{
|
||||
versionURL: tt.fields.versionURL,
|
||||
}
|
||||
got, err := v.getLatestVersion(tt.args.versionData)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("VersionCheckHandler.getLatestVersion() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("VersionCheckHandler.getLatestVersion() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTriggerSource(t *testing.T) {
|
||||
// Running in github actions pipeline
|
||||
os.Setenv("GITHUB_ACTIONS", "true")
|
||||
source := getTriggerSource()
|
||||
assert.Equal(t, "pipeline", source)
|
||||
|
||||
os.Args[0] = "ksserver"
|
||||
source = getTriggerSource()
|
||||
assert.Equal(t, "microservice", source)
|
||||
}
|
||||
@@ -83,7 +83,10 @@ func (a *OperatorAdapter) httpPostOperatorScanRequest(body apis.Commands) (strin
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return httputils.HttpRespToString(resp)
|
||||
if resp.StatusCode != 200 {
|
||||
return "", fmt.Errorf("http-error: %d", resp.StatusCode)
|
||||
}
|
||||
return "success", nil
|
||||
}
|
||||
|
||||
func (a *OperatorAdapter) OperatorScan() (string, error) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"go.opentelemetry.io/otel"
|
||||
"golang.org/x/exp/slices"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/kubescape/opa-utils/resources"
|
||||
)
|
||||
@@ -41,10 +43,13 @@ func getInterfaces(ctx context.Context, scanInfo *cautils.ScanInfo) componentInt
|
||||
|
||||
// ================== setup k8s interface object ======================================
|
||||
var k8s *k8sinterface.KubernetesApi
|
||||
var k8sClient kubernetes.Interface
|
||||
if scanInfo.GetScanningContext() == cautils.ContextCluster {
|
||||
k8s = getKubernetesApi()
|
||||
if k8s == nil {
|
||||
logger.L().Ctx(ctx).Fatal("failed connecting to Kubernetes cluster")
|
||||
} else {
|
||||
k8sClient = k8s.KubernetesClient
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +68,8 @@ func getInterfaces(ctx context.Context, scanInfo *cautils.ScanInfo) componentInt
|
||||
|
||||
// ================== version testing ======================================
|
||||
|
||||
v := cautils.NewIVersionCheckHandler(ctx)
|
||||
v.CheckLatestVersion(ctx, cautils.NewVersionCheckRequest(cautils.BuildNumber, policyIdentifierIdentities(scanInfo.PolicyIdentifier), "", cautils.ScanningContextToScanningScope(scanInfo.GetScanningContext())))
|
||||
v := versioncheck.NewIVersionCheckHandler(ctx)
|
||||
_ = v.CheckLatestVersion(ctx, versioncheck.NewVersionCheckRequest(scanInfo.AccountID, versioncheck.BuildNumber, policyIdentifierIdentities(scanInfo.PolicyIdentifier), "", string(scanInfo.GetScanningContext()), k8sClient))
|
||||
|
||||
// ================== setup host scanner object ======================================
|
||||
ctxHostScanner, spanHostScanner := otel.Tracer("").Start(ctx, "setup host scanner")
|
||||
@@ -123,6 +128,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
|
||||
// ===================== Initialization =====================
|
||||
scanInfo.Init(ctxInit) // initialize scan info
|
||||
defer scanInfo.Cleanup()
|
||||
|
||||
interfaces := getInterfaces(ctxInit, scanInfo)
|
||||
interfaces.report.SetTenantConfig(interfaces.tenantConfig)
|
||||
@@ -190,7 +196,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
} else if err := priotizationHandler.PrioritizeResources(scanData); err != nil {
|
||||
return resultsHandling, fmt.Errorf("%w", err)
|
||||
}
|
||||
if err == nil && isPrioritizationScanType(scanInfo.ScanType) {
|
||||
if isPrioritizationScanType(scanInfo.ScanType) {
|
||||
scanData.SetTopWorkloads()
|
||||
}
|
||||
spanPrioritization.End()
|
||||
@@ -210,7 +216,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
}
|
||||
|
||||
func scanImages(scanType cautils.ScanTypes, scanData *cautils.OPASessionObj, ctx context.Context, resultsHandling *resultshandling.ResultsHandler) {
|
||||
imagesToScan := []string{}
|
||||
var imagesToScan []string
|
||||
|
||||
if scanType == cautils.ScanTypeWorkload {
|
||||
containers, err := workloadinterface.NewWorkloadObj(scanData.SingleResourceScan.GetObject()).GetContainers()
|
||||
@@ -246,7 +252,7 @@ func scanImages(scanType cautils.ScanTypes, scanData *cautils.OPASessionObj, ctx
|
||||
if err := scanSingleImage(ctx, img, svc, resultsHandling); err != nil {
|
||||
logger.L().StopError("failed to scan", helpers.String("image", img), helpers.Error(err))
|
||||
}
|
||||
logger.L().StopSuccess("Scan successful: ", helpers.String("image", img))
|
||||
logger.L().StopSuccess("Done scanning", helpers.String("image", img))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ func GenerateContainerScanReportMock() ScanResultReport {
|
||||
return ds
|
||||
}
|
||||
|
||||
// GenerateContainerScanReportMock - generate a scan result
|
||||
// GenerateContainerScanReportNoVulMock - generate a scan result
|
||||
func GenerateContainerScanReportNoVulMock() ScanResultReport {
|
||||
ds := ScanResultReport{
|
||||
WLID: "wlid://cluster-k8s-geriatrix-k8s-demo3/namespace-whisky-app/deployment-whisky4all-shipping",
|
||||
|
||||
@@ -307,7 +307,7 @@ func (hsh *HostSensorHandler) updatePodInListAtomic(ctx context.Context, eventTy
|
||||
}
|
||||
}
|
||||
|
||||
// tearDownNamespace manage the host-scanner deletion.
|
||||
// tearDownHostScanner manage the host-scanner deletion.
|
||||
func (hsh *HostSensorHandler) tearDownHostScanner(namespace string) error {
|
||||
client := hsh.k8sObj.KubernetesClient
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ func (hsh *HostSensorHandler) getKubeProxyInfo(ctx context.Context) ([]hostsenso
|
||||
return hsh.sendAllPodsHTTPGETRequest(ctx, "/kubeProxyInfo", KubeProxyInfo)
|
||||
}
|
||||
|
||||
// getControlPlanInfo returns the list of controlPlaneInfo metadata
|
||||
// getControlPlaneInfo returns the list of controlPlaneInfo metadata
|
||||
func (hsh *HostSensorHandler) getControlPlaneInfo(ctx context.Context) ([]hostsensor.HostSensorDataEnvelope, error) {
|
||||
// loop over pods and port-forward it to each of them
|
||||
return hsh.sendAllPodsHTTPGETRequest(ctx, "/controlPlaneInfo", ControlPlaneInfo)
|
||||
|
||||
@@ -39,7 +39,7 @@ func (lm *LogsMap) isDuplicated(logContent string) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// GgtOccurrence retrieve the number of occurrences logContent has been used.
|
||||
// getOccurrence retrieve the number of occurrences logContent has been used.
|
||||
func (lm *LogsMap) getOccurrence(logContent string) int {
|
||||
lm.Lock()
|
||||
occurrence, ok := lm.usedLogs[logContent]
|
||||
|
||||
@@ -3,7 +3,6 @@ package resourcehandler
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -11,7 +10,7 @@ import (
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -26,7 +25,7 @@ func NewFileResourceHandler() *FileResourceHandler {
|
||||
return &FileResourceHandler{}
|
||||
}
|
||||
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, _ opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
allResources := map[string]workloadinterface.IMetadata{}
|
||||
externalResources := cautils.ExternalResources{}
|
||||
|
||||
@@ -41,15 +40,16 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
for path := range scanInfo.InputPatterns {
|
||||
var workloadIDToSource map[string]reporthandling.Source
|
||||
var workloads []workloadinterface.IMetadata
|
||||
var workloadIDToMappingNodes map[string]cautils.MappingNodes
|
||||
var err error
|
||||
|
||||
if scanInfo.ChartPath != "" && scanInfo.FilePath != "" {
|
||||
workloadIDToSource, workloads, err = getWorkloadFromHelmChart(ctx, scanInfo.ChartPath, scanInfo.FilePath)
|
||||
workloadIDToSource, workloads, workloadIDToMappingNodes, err = getWorkloadFromHelmChart(ctx, scanInfo.InputPatterns[path], scanInfo.ChartPath, scanInfo.FilePath)
|
||||
if err != nil {
|
||||
// We should probably ignore the error so we can continue scanning other charts
|
||||
}
|
||||
} else {
|
||||
workloadIDToSource, workloads, err = getResourcesFromPath(ctx, scanInfo.InputPatterns[path])
|
||||
workloadIDToSource, workloads, workloadIDToMappingNodes, err = getResourcesFromPath(ctx, scanInfo.InputPatterns[path])
|
||||
if err != nil {
|
||||
return nil, allResources, nil, nil, err
|
||||
}
|
||||
@@ -60,6 +60,7 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
|
||||
for k, v := range workloadIDToSource {
|
||||
sessionObj.ResourceSource[k] = v
|
||||
sessionObj.TemplateMapping[k] = workloadIDToMappingNodes[k]
|
||||
}
|
||||
|
||||
// map all resources: map["/apiVersion/version/kind"][]<k8s workloads>
|
||||
@@ -86,7 +87,7 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
// save only relevant resources
|
||||
for i := range mappedResources {
|
||||
if _, ok := k8sResources[i]; ok {
|
||||
ids := []string{}
|
||||
var ids []string
|
||||
for j := range mappedResources[i] {
|
||||
ids = append(ids, mappedResources[i][j].GetID())
|
||||
allResources[mappedResources[i][j].GetID()] = mappedResources[i][j]
|
||||
@@ -105,47 +106,52 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
func (fileHandler *FileResourceHandler) GetCloudProvider() string {
|
||||
return ""
|
||||
}
|
||||
func getWorkloadFromHelmChart(ctx context.Context, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
clonedRepo, err := cloneGitRepo(&helmPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
func getWorkloadFromHelmChart(ctx context.Context, path, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, map[string]cautils.MappingNodes, error) {
|
||||
clonedRepo := cautils.GetClonedPath(path)
|
||||
|
||||
if clonedRepo != "" {
|
||||
defer os.RemoveAll(clonedRepo)
|
||||
// if the repo was cloned, add the workload path to the cloned repo
|
||||
workloadPath = filepath.Join(clonedRepo, workloadPath)
|
||||
} else {
|
||||
// if the repo was not cloned
|
||||
clonedRepo = path
|
||||
}
|
||||
|
||||
// Get repo root
|
||||
repoRoot, gitRepo := extractGitRepo(helmPath)
|
||||
repoRoot, gitRepo := extractGitRepo(clonedRepo)
|
||||
|
||||
helmSourceToWorkloads, helmSourceToChart := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
|
||||
if clonedRepo != "" {
|
||||
workloadPath = clonedRepo + workloadPath
|
||||
}
|
||||
helmSourceToWorkloads, helmSourceToChart, helmSourceToNodes := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
|
||||
wlSource, ok := helmSourceToWorkloads[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("workload %s not found in chart %s", workloadPath, helmPath)
|
||||
return nil, nil, nil, fmt.Errorf("workload %s not found in chart %s", workloadPath, helmPath)
|
||||
}
|
||||
|
||||
if len(wlSource) != 1 {
|
||||
return nil, nil, fmt.Errorf("workload %s found multiple times in chart %s", workloadPath, helmPath)
|
||||
return nil, nil, nil, fmt.Errorf("workload %s found multiple times in chart %s", workloadPath, helmPath)
|
||||
}
|
||||
|
||||
helmChart, ok := helmSourceToChart[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("helmChart not found for workload %s", workloadPath)
|
||||
return nil, nil, nil, fmt.Errorf("helmChart not found for workload %s", workloadPath)
|
||||
}
|
||||
|
||||
templatesNodes, ok := helmSourceToNodes[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, nil, fmt.Errorf("templatesNodes not found for workload %s", workloadPath)
|
||||
}
|
||||
|
||||
workloadSource := getWorkloadSourceHelmChart(repoRoot, helmPath, gitRepo, helmChart)
|
||||
|
||||
workloadIDToSource := make(map[string]reporthandling.Source, 1)
|
||||
workloadIDToNodes := make(map[string]cautils.MappingNodes, 1)
|
||||
workloadIDToSource[wlSource[0].GetID()] = workloadSource
|
||||
workloadIDToNodes[wlSource[0].GetID()] = templatesNodes
|
||||
|
||||
workloads := []workloadinterface.IMetadata{}
|
||||
var workloads []workloadinterface.IMetadata
|
||||
workloads = append(workloads, wlSource...)
|
||||
|
||||
return workloadIDToSource, workloads, nil
|
||||
return workloadIDToSource, workloads, workloadIDToNodes, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -179,16 +185,15 @@ func getWorkloadSourceHelmChart(repoRoot string, source string, gitRepo *cautils
|
||||
}
|
||||
}
|
||||
|
||||
func getResourcesFromPath(ctx context.Context, path string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
workloadIDToSource := make(map[string]reporthandling.Source, 0)
|
||||
workloads := []workloadinterface.IMetadata{}
|
||||
func getResourcesFromPath(ctx context.Context, path string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, map[string]cautils.MappingNodes, error) {
|
||||
workloadIDToSource := make(map[string]reporthandling.Source)
|
||||
workloadIDToNodes := make(map[string]cautils.MappingNodes)
|
||||
var workloads []workloadinterface.IMetadata
|
||||
|
||||
clonedRepo, err := cloneGitRepo(&path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
clonedRepo := cautils.GetClonedPath(path)
|
||||
if clonedRepo != "" {
|
||||
defer os.RemoveAll(clonedRepo)
|
||||
// if the repo was cloned, add the workload path to the cloned repo
|
||||
path = clonedRepo
|
||||
}
|
||||
|
||||
// Get repo root
|
||||
@@ -269,12 +274,16 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
}
|
||||
|
||||
// load resources from helm charts
|
||||
helmSourceToWorkloads, helmSourceToChart := cautils.LoadResourcesFromHelmCharts(ctx, path)
|
||||
helmSourceToWorkloads, helmSourceToChart, helmSourceToNodes := cautils.LoadResourcesFromHelmCharts(ctx, path)
|
||||
for source, ws := range helmSourceToWorkloads {
|
||||
workloads = append(workloads, ws...)
|
||||
helmChart := helmSourceToChart[source]
|
||||
var templatesNodes cautils.MappingNodes
|
||||
if nodes, ok := helmSourceToNodes[source]; ok {
|
||||
templatesNodes = nodes
|
||||
}
|
||||
|
||||
if clonedRepo != "" {
|
||||
if clonedRepo != "" && gitRepo != nil {
|
||||
url, err := gitRepo.GetRemoteUrl()
|
||||
if err != nil {
|
||||
logger.L().Warning("failed to get remote url", helpers.Error(err))
|
||||
@@ -283,21 +292,24 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
helmChart.Path = strings.TrimSuffix(url, ".git")
|
||||
repoRoot = ""
|
||||
source = strings.TrimPrefix(source, fmt.Sprintf("%s/", clonedRepo))
|
||||
templatesNodes.TemplateFileName = source
|
||||
}
|
||||
|
||||
workloadSource := getWorkloadSourceHelmChart(repoRoot, source, gitRepo, helmChart)
|
||||
|
||||
for i := range ws {
|
||||
workloadIDToSource[ws[i].GetID()] = workloadSource
|
||||
workloadIDToNodes[ws[i].GetID()] = templatesNodes
|
||||
}
|
||||
}
|
||||
|
||||
if len(helmSourceToWorkloads) > 0 {
|
||||
if len(helmSourceToWorkloads) > 0 { // && len(helmSourceToNodes) > 0
|
||||
logger.L().Debug("helm templates found in local storage", helpers.Int("helmTemplates", len(helmSourceToWorkloads)), helpers.Int("workloads", len(workloads)))
|
||||
}
|
||||
|
||||
//patch, get value from env
|
||||
// Load resources from Kustomize directory
|
||||
kustomizeSourceToWorkloads, kustomizeDirectoryName := cautils.LoadResourcesFromKustomizeDirectory(ctx, path)
|
||||
kustomizeSourceToWorkloads, kustomizeDirectoryName := cautils.LoadResourcesFromKustomizeDirectory(ctx, path) //?
|
||||
|
||||
// update workloads and workloadIDToSource with workloads from Kustomize Directory
|
||||
for source, ws := range kustomizeSourceToWorkloads {
|
||||
@@ -334,7 +346,7 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
}
|
||||
}
|
||||
|
||||
return workloadIDToSource, workloads, nil
|
||||
return workloadIDToSource, workloads, workloadIDToNodes, nil
|
||||
}
|
||||
|
||||
func extractGitRepo(path string) (string, *cautils.LocalGitRepository) {
|
||||
|
||||
@@ -2,40 +2,14 @@ package resourcehandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
giturl "github.com/kubescape/go-git-url"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
)
|
||||
|
||||
// Clone git repository
|
||||
func cloneGitRepo(path *string) (string, error) {
|
||||
var clonedDir string
|
||||
|
||||
gitURL, err := giturl.NewGitAPI(*path)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Clone git repository if needed
|
||||
logger.L().Start("cloning", helpers.String("repository url", gitURL.GetURL().String()))
|
||||
|
||||
clonedDir, err = cloneRepo(gitURL)
|
||||
if err != nil {
|
||||
logger.L().StopError("failed to clone git repo", helpers.String("url", gitURL.GetURL().String()), helpers.Error(err))
|
||||
return "", fmt.Errorf("failed to clone git repo '%s', %w", gitURL.GetURL().String(), err)
|
||||
}
|
||||
|
||||
*path = filepath.Join(clonedDir, gitURL.GetPath())
|
||||
logger.L().StopSuccess("Done accessing local objects")
|
||||
|
||||
return clonedDir, nil
|
||||
}
|
||||
|
||||
func addWorkloadsToResourcesMap(allResources map[string][]workloadinterface.IMetadata, workloads []workloadinterface.IMetadata) {
|
||||
for i := range workloads {
|
||||
groupVersionResource, err := k8sinterface.GetGroupVersionResource(workloads[i].GetKind())
|
||||
@@ -92,7 +66,7 @@ func findScanObjectResource(mappedResources map[string][]workloadinterface.IMeta
|
||||
|
||||
logger.L().Debug("Single resource scan", helpers.String("resource", resource.GetID()))
|
||||
|
||||
wls := []workloadinterface.IWorkload{}
|
||||
var wls []workloadinterface.IWorkload
|
||||
for _, resources := range mappedResources {
|
||||
for _, r := range resources {
|
||||
if r.GetKind() == resource.GetKind() && r.GetName() == resource.GetName() {
|
||||
|
||||
@@ -114,7 +114,7 @@ func filterRuleMatchesForResource(resourceKind string, matchObjects []reporthand
|
||||
return resourceMap
|
||||
}
|
||||
|
||||
// updateQueryableResourcesMapFromMatch updates the queryableResources map with the relevant resources from the match object.
|
||||
// updateQueryableResourcesMapFromRuleMatchObject updates the queryableResources map with the relevant resources from the match object.
|
||||
// if namespace is not empty, the namespace filter is added to the queryable resources (which are namespaced)
|
||||
// if resourcesFilterMap is not nil, only the resources with value 'true' will be added to the queryable resources
|
||||
func updateQueryableResourcesMapFromRuleMatchObject(match *reporthandling.RuleMatchObjects, resourcesFilterMap map[string]bool, queryableResources QueryableResources, namespace string) {
|
||||
|
||||
@@ -14,11 +14,13 @@ import (
|
||||
|
||||
const (
|
||||
columnSeverity = iota
|
||||
columnRef = iota
|
||||
columnName = iota
|
||||
columnCounterFailed = iota
|
||||
columnCounterAll = iota
|
||||
columnComplianceScore = iota
|
||||
_rowLen = iota
|
||||
controlNameMaxLength = 70
|
||||
)
|
||||
|
||||
func generateRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo []infoStars, verbose bool) []string {
|
||||
@@ -30,8 +32,8 @@ func generateRow(controlSummary reportsummary.IControlSummary, infoToPrintInfo [
|
||||
}
|
||||
|
||||
row[columnSeverity] = getSeverityColumn(controlSummary)
|
||||
if len(controlSummary.GetName()) > 50 {
|
||||
row[columnName] = controlSummary.GetName()[:50] + "..."
|
||||
if len(controlSummary.GetName()) > controlNameMaxLength {
|
||||
row[columnName] = controlSummary.GetName()[:controlNameMaxLength] + "..."
|
||||
} else {
|
||||
row[columnName] = controlSummary.GetName()
|
||||
}
|
||||
@@ -62,8 +64,9 @@ func generateRowPdf(controlSummary reportsummary.IControlSummary, infoToPrintInf
|
||||
}
|
||||
|
||||
row[columnSeverity] = apis.ControlSeverityToString(controlSummary.GetScoreFactor())
|
||||
if len(controlSummary.GetName()) > 50 {
|
||||
row[columnName] = controlSummary.GetName()[:50] + "..."
|
||||
row[columnRef] = controlSummary.GetID()
|
||||
if len(controlSummary.GetName()) > controlNameMaxLength {
|
||||
row[columnName] = controlSummary.GetName()[:controlNameMaxLength] + "..."
|
||||
} else {
|
||||
row[columnName] = controlSummary.GetName()
|
||||
}
|
||||
@@ -144,6 +147,7 @@ func getControlTableHeaders(short bool) []string {
|
||||
headers[0] = "Controls"
|
||||
} else {
|
||||
headers = make([]string, _rowLen)
|
||||
headers[columnRef] = "Control reference"
|
||||
headers[columnName] = "Control name"
|
||||
headers[columnCounterFailed] = "Failed resources"
|
||||
headers[columnCounterAll] = "All resources"
|
||||
|
||||
@@ -2,6 +2,7 @@ package printer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -40,23 +41,28 @@ func Test_generateRowPdf(t *testing.T) {
|
||||
t.Errorf("got %s, want either of these: %s", c[0], "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")
|
||||
}
|
||||
|
||||
// Validating length of control name
|
||||
if len(c[1]) > 53 {
|
||||
t.Errorf("got %s, want %s", c[1], "less than 54 characters")
|
||||
if len(c[2]) > controlNameMaxLength {
|
||||
t.Errorf("got %s, want %s", c[1], fmt.Sprintf("less than %d characters", controlNameMaxLength))
|
||||
}
|
||||
|
||||
// Validating numeric fields
|
||||
_, err := strconv.Atoi(c[2])
|
||||
_, err := strconv.Atoi(c[3])
|
||||
if err != nil {
|
||||
t.Errorf("got %s, want an integer %s", c[2], err)
|
||||
}
|
||||
|
||||
_, err = strconv.Atoi(c[3])
|
||||
_, err = strconv.Atoi(c[4])
|
||||
if err != nil {
|
||||
t.Errorf("got %s, want an integer %s", c[3], err)
|
||||
}
|
||||
|
||||
assert.NotEmpty(t, c[4], "expected a non-empty string")
|
||||
assert.NotEmpty(t, c[5], "expected a non-empty string")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,16 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/grype/grype/presenter"
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "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/prettyprinter/tableprinter/imageprinter"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"k8s.io/utils/strings/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -54,11 +58,41 @@ func (jp *JsonPrinter) Score(score float32) {
|
||||
fmt.Fprintf(os.Stderr, "\nOverall compliance-score (100- Excellent, 0- All failed): %d\n", cautils.Float32ToInt(score))
|
||||
|
||||
}
|
||||
func (jp *JsonPrinter) convertToImageScanSummary(imageScanData []cautils.ImageScanData) (*imageprinter.ImageScanSummary, error) {
|
||||
imageScanSummary := imageprinter.ImageScanSummary{
|
||||
CVEs: []imageprinter.CVE{},
|
||||
PackageScores: map[string]*imageprinter.PackageScore{},
|
||||
MapsSeverityToSummary: map[string]*imageprinter.SeveritySummary{},
|
||||
}
|
||||
|
||||
for i := range imageScanData {
|
||||
if !slices.Contains(imageScanSummary.Images, imageScanData[i].Image) {
|
||||
imageScanSummary.Images = append(imageScanSummary.Images, imageScanData[i].Image)
|
||||
}
|
||||
|
||||
presenterConfig := imageScanData[i].PresenterConfig
|
||||
doc, err := models.NewDocument(clio.Identification{}, presenterConfig.Packages, presenterConfig.Context, presenterConfig.Matches, presenterConfig.IgnoredMatches, presenterConfig.MetadataProvider, nil, presenterConfig.DBStatus)
|
||||
if err != nil {
|
||||
logger.L().Error(fmt.Sprintf("failed to create document for image: %v", imageScanData[i].Image), helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
CVEs := extractCVEs(doc.Matches)
|
||||
imageScanSummary.CVEs = append(imageScanSummary.CVEs, CVEs...)
|
||||
|
||||
setPkgNameToScoreMap(doc.Matches, imageScanSummary.PackageScores)
|
||||
|
||||
setSeverityToSummaryMap(CVEs, imageScanSummary.MapsSeverityToSummary)
|
||||
}
|
||||
|
||||
return &imageScanSummary, nil
|
||||
}
|
||||
|
||||
func (jp *JsonPrinter) ActionPrint(ctx context.Context, opaSessionObj *cautils.OPASessionObj, imageScanData []cautils.ImageScanData) {
|
||||
var err error
|
||||
|
||||
if opaSessionObj != nil {
|
||||
err = printConfigurationsScanning(opaSessionObj, ctx, jp)
|
||||
err = printConfigurationsScanning(opaSessionObj, ctx, imageScanData, jp)
|
||||
} else if imageScanData != nil {
|
||||
err = jp.PrintImageScan(ctx, imageScanData[0].PresenterConfig)
|
||||
} else {
|
||||
@@ -73,16 +107,67 @@ func (jp *JsonPrinter) ActionPrint(ctx context.Context, opaSessionObj *cautils.O
|
||||
printer.LogOutputFile(jp.writer.Name())
|
||||
}
|
||||
|
||||
func printConfigurationsScanning(opaSessionObj *cautils.OPASessionObj, ctx context.Context, jp *JsonPrinter) error {
|
||||
r, err := json.Marshal(FinalizeResults(opaSessionObj))
|
||||
if err != nil {
|
||||
return err
|
||||
func printConfigurationsScanning(opaSessionObj *cautils.OPASessionObj, ctx context.Context, imageScanData []cautils.ImageScanData, jp *JsonPrinter) error {
|
||||
|
||||
if imageScanData != nil {
|
||||
imageScanSummary, err := jp.convertToImageScanSummary(imageScanData)
|
||||
if err != nil {
|
||||
logger.L().Error("failed to convert to image scan summary", helpers.Error(err))
|
||||
return err
|
||||
}
|
||||
opaSessionObj.Report.SummaryDetails.Vulnerabilities.MapsSeverityToSummary = convertToReportSummary(imageScanSummary.MapsSeverityToSummary)
|
||||
opaSessionObj.Report.SummaryDetails.Vulnerabilities.CVESummary = convertToCVESummary(imageScanSummary.CVEs)
|
||||
opaSessionObj.Report.SummaryDetails.Vulnerabilities.PackageScores = convertToPackageScores(imageScanSummary.PackageScores)
|
||||
opaSessionObj.Report.SummaryDetails.Vulnerabilities.Images = imageScanSummary.Images
|
||||
}
|
||||
|
||||
r, err := json.Marshal(FinalizeResults(opaSessionObj))
|
||||
_, err = jp.writer.Write(r)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func convertToPackageScores(packageScores map[string]*imageprinter.PackageScore) map[string]*reportsummary.PackageSummary {
|
||||
convertedPackageScores := make(map[string]*reportsummary.PackageSummary)
|
||||
for pkg, score := range packageScores {
|
||||
convertedPackageScores[pkg] = &reportsummary.PackageSummary{
|
||||
Name: score.Name,
|
||||
Version: score.Version,
|
||||
Score: score.Score,
|
||||
MapSeverityToCVEsNumber: score.MapSeverityToCVEsNumber,
|
||||
}
|
||||
}
|
||||
return convertedPackageScores
|
||||
}
|
||||
|
||||
func convertToCVESummary(cves []imageprinter.CVE) []reportsummary.CVESummary {
|
||||
cveSummary := make([]reportsummary.CVESummary, len(cves))
|
||||
i := 0
|
||||
for _, cve := range cves {
|
||||
var a reportsummary.CVESummary
|
||||
a.Severity = cve.Severity
|
||||
a.ID = cve.ID
|
||||
a.Package = cve.Package
|
||||
a.Version = cve.Version
|
||||
a.FixVersions = cve.FixVersions
|
||||
a.FixedState = cve.FixedState
|
||||
cveSummary[i] = a
|
||||
i++
|
||||
}
|
||||
return cveSummary
|
||||
}
|
||||
|
||||
func convertToReportSummary(input map[string]*imageprinter.SeveritySummary) map[string]*reportsummary.SeveritySummary {
|
||||
output := make(map[string]*reportsummary.SeveritySummary)
|
||||
for key, value := range input {
|
||||
output[key] = &reportsummary.SeveritySummary{
|
||||
NumberOfCVEs: value.NumberOfCVEs,
|
||||
NumberOfFixableCVEs: value.NumberOfFixableCVEs,
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func (jp *JsonPrinter) PrintImageScan(ctx context.Context, scanResults *models.PresenterConfig) error {
|
||||
if scanResults == nil {
|
||||
return fmt.Errorf("no image vulnerability data provided")
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/imageprinter"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -83,3 +85,110 @@ func TestScore_Json(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestConvertToCVESummary(t *testing.T) {
|
||||
cves := []imageprinter.CVE{
|
||||
{
|
||||
Severity: "High",
|
||||
ID: "CVE-2021-1234",
|
||||
Package: "example-package",
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"1.0.1", "1.0.2"},
|
||||
FixedState: "true",
|
||||
},
|
||||
{
|
||||
Severity: "Medium",
|
||||
ID: "CVE-2021-5678",
|
||||
Package: "another-package",
|
||||
Version: "2.0.0",
|
||||
FixVersions: []string{"2.0.1"},
|
||||
FixedState: "false",
|
||||
},
|
||||
}
|
||||
|
||||
want := []reportsummary.CVESummary{
|
||||
{
|
||||
Severity: "High",
|
||||
ID: "CVE-2021-1234",
|
||||
Package: "example-package",
|
||||
Version: "1.0.0",
|
||||
FixVersions: []string{"1.0.1", "1.0.2"},
|
||||
FixedState: "true",
|
||||
},
|
||||
{
|
||||
Severity: "Medium",
|
||||
ID: "CVE-2021-5678",
|
||||
Package: "another-package",
|
||||
Version: "2.0.0",
|
||||
FixVersions: []string{"2.0.1"},
|
||||
FixedState: "false",
|
||||
},
|
||||
}
|
||||
|
||||
got := convertToCVESummary(cves)
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestConvertToPackageScores(t *testing.T) {
|
||||
packageScores := map[string]*imageprinter.PackageScore{
|
||||
"example-package": {
|
||||
Name: "example-package",
|
||||
Version: "1.0.0",
|
||||
Score: 80.0,
|
||||
MapSeverityToCVEsNumber: map[string]int{"High": 2, "Medium": 1},
|
||||
},
|
||||
"another-package": {
|
||||
Name: "another-package",
|
||||
Version: "2.0.0",
|
||||
Score: 60.0,
|
||||
MapSeverityToCVEsNumber: map[string]int{"High": 1, "Medium": 0},
|
||||
},
|
||||
}
|
||||
|
||||
want := map[string]*reportsummary.PackageSummary{
|
||||
"example-package": {
|
||||
Name: "example-package",
|
||||
Version: "1.0.0",
|
||||
Score: 80.0,
|
||||
MapSeverityToCVEsNumber: map[string]int{"High": 2, "Medium": 1},
|
||||
},
|
||||
"another-package": {
|
||||
Name: "another-package",
|
||||
Version: "2.0.0",
|
||||
Score: 60.0,
|
||||
MapSeverityToCVEsNumber: map[string]int{"High": 1, "Medium": 0},
|
||||
},
|
||||
}
|
||||
|
||||
got := convertToPackageScores(packageScores)
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestConvertToReportSummary(t *testing.T) {
|
||||
input := map[string]*imageprinter.SeveritySummary{
|
||||
"High": &imageprinter.SeveritySummary{
|
||||
NumberOfCVEs: 10,
|
||||
NumberOfFixableCVEs: 5,
|
||||
},
|
||||
"Medium": &imageprinter.SeveritySummary{
|
||||
NumberOfCVEs: 5,
|
||||
NumberOfFixableCVEs: 2,
|
||||
},
|
||||
}
|
||||
|
||||
want := map[string]*reportsummary.SeveritySummary{
|
||||
"High": &reportsummary.SeveritySummary{
|
||||
NumberOfCVEs: 10,
|
||||
NumberOfFixableCVEs: 5,
|
||||
},
|
||||
"Medium": &reportsummary.SeveritySummary{
|
||||
NumberOfCVEs: 5,
|
||||
NumberOfFixableCVEs: 2,
|
||||
},
|
||||
}
|
||||
|
||||
got := convertToReportSummary(input)
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
@@ -192,18 +192,21 @@ func (pp *PdfPrinter) printTable(m pdf.Maroto, summaryDetails *reportsummary.Sum
|
||||
}
|
||||
}
|
||||
|
||||
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: 6.0,
|
||||
GridSizes: []uint{1, 5, 2, 2, 2},
|
||||
Size: size,
|
||||
GridSizes: gridSize,
|
||||
},
|
||||
ContentProp: props.TableListContent{
|
||||
Family: consts.Courier,
|
||||
Style: consts.Normal,
|
||||
Size: 6.0,
|
||||
GridSizes: []uint{1, 5, 2, 2, 2},
|
||||
Size: size,
|
||||
GridSizes: gridSize,
|
||||
CellTextColorChangerColumnIndex: 0,
|
||||
CellTextColorChangerFunc: func(cellValue string) color.Color {
|
||||
if cellValue == "Critical" {
|
||||
|
||||
@@ -3,6 +3,7 @@ package prettyprinter
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/configurationprinter"
|
||||
@@ -77,9 +78,8 @@ func (rp *RepoPrinter) getWorkloadScanCommand(ns, kind, name string, source repo
|
||||
}
|
||||
|
||||
if source.FileType == reporthandling.SourceTypeHelmChart {
|
||||
return fmt.Sprintf("%s --chart-path=%s --file-path=%s", cmd, source.HelmPath, fmt.Sprintf("%s/%s", source.Path, source.RelativePath))
|
||||
|
||||
return fmt.Sprintf("%s --chart-path=%s --file-path=%s", cmd, source.HelmPath, filepath.Join(source.Path, source.RelativePath))
|
||||
} else {
|
||||
return fmt.Sprintf("%s --file-path=%s", cmd, fmt.Sprintf("%s/%s", source.Path, source.RelativePath))
|
||||
return fmt.Sprintf("%s --file-path=%s", cmd, filepath.Join(source.Path, source.RelativePath))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package prettyprinter
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
@@ -50,7 +51,18 @@ func TestRepoScan_getWorkloadScanCommand(t *testing.T) {
|
||||
Path: "path",
|
||||
RelativePath: "relativePath",
|
||||
},
|
||||
want: "$ kubescape scan workload kind/name --namespace ns --file-path=path/relativePath",
|
||||
want: "$ kubescape scan workload kind/name --namespace ns --file-path=" + filepath.Join("path", "relativePath"),
|
||||
},
|
||||
{
|
||||
testName: "relative file path",
|
||||
ns: "ns",
|
||||
kind: "kind",
|
||||
name: "name",
|
||||
source: reporthandling.Source{
|
||||
Path: "",
|
||||
RelativePath: "relativePath",
|
||||
},
|
||||
want: "$ kubescape scan workload kind/name --namespace ns --file-path=relativePath",
|
||||
},
|
||||
{
|
||||
testName: "helm path",
|
||||
@@ -63,7 +75,7 @@ func TestRepoScan_getWorkloadScanCommand(t *testing.T) {
|
||||
HelmPath: "helmPath",
|
||||
FileType: "Helm Chart",
|
||||
},
|
||||
want: "$ kubescape scan workload kind/name --namespace ns --chart-path=helmPath --file-path=path/relativePath",
|
||||
want: "$ kubescape scan workload kind/name --namespace ns --chart-path=helmPath --file-path=" + filepath.Join("path", "relativePath"),
|
||||
},
|
||||
{
|
||||
testName: "file path - no namespace",
|
||||
@@ -73,7 +85,7 @@ func TestRepoScan_getWorkloadScanCommand(t *testing.T) {
|
||||
Path: "path",
|
||||
RelativePath: "relativePath",
|
||||
},
|
||||
want: "$ kubescape scan workload kind/name --file-path=path/relativePath",
|
||||
want: "$ kubescape scan workload kind/name --file-path=" + filepath.Join("path", "relativePath"),
|
||||
},
|
||||
{
|
||||
testName: "helm path - no namespace",
|
||||
@@ -85,7 +97,7 @@ func TestRepoScan_getWorkloadScanCommand(t *testing.T) {
|
||||
HelmPath: "helmPath",
|
||||
FileType: "Helm Chart",
|
||||
},
|
||||
want: "$ kubescape scan workload kind/name --chart-path=helmPath --file-path=path/relativePath",
|
||||
want: "$ kubescape scan workload kind/name --chart-path=helmPath --file-path=" + filepath.Join("path", "relativePath"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -160,14 +160,18 @@ func failedPathsToString(control *resourcesresults.ResourceAssociatedControl) []
|
||||
return paths
|
||||
}
|
||||
|
||||
func fixPathsToString(control *resourcesresults.ResourceAssociatedControl) []string {
|
||||
func fixPathsToString(control *resourcesresults.ResourceAssociatedControl, onlyPath bool) []string {
|
||||
var paths []string
|
||||
|
||||
for j := range control.ResourceAssociatedRules {
|
||||
for k := range control.ResourceAssociatedRules[j].Paths {
|
||||
if p := control.ResourceAssociatedRules[j].Paths[k].FixPath.Path; p != "" {
|
||||
v := control.ResourceAssociatedRules[j].Paths[k].FixPath.Value
|
||||
paths = append(paths, fmt.Sprintf("%s=%s", p, v))
|
||||
if onlyPath {
|
||||
paths = append(paths, p)
|
||||
} else {
|
||||
v := control.ResourceAssociatedRules[j].Paths[k].FixPath.Value
|
||||
paths = append(paths, fmt.Sprintf("%s=%s", p, v))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +205,7 @@ func reviewPathsToString(control *resourcesresults.ResourceAssociatedControl) []
|
||||
}
|
||||
|
||||
func AssistedRemediationPathsToString(control *resourcesresults.ResourceAssociatedControl) []string {
|
||||
paths := append(fixPathsToString(control), append(deletePathsToString(control), reviewPathsToString(control)...)...)
|
||||
paths := append(fixPathsToString(control, false), append(deletePathsToString(control), reviewPathsToString(control)...)...)
|
||||
// TODO - deprecate failedPaths once all controls support review/delete paths
|
||||
paths = appendFailedPathsIfNotInPaths(paths, failedPathsToString(control))
|
||||
return paths
|
||||
|
||||
@@ -254,16 +254,16 @@ func TestFixPathsToString(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test case 1: Empty ResourceAssociatedRules
|
||||
actualPaths := fixPathsToString(emptyControl)
|
||||
actualPaths := fixPathsToString(emptyControl, false)
|
||||
assert.Nil(t, actualPaths)
|
||||
|
||||
// Test case 2: Single ResourceAssociatedRule and one ReviewPath
|
||||
actualPaths = fixPathsToString(singleRuleControl)
|
||||
actualPaths = fixPathsToString(singleRuleControl, false)
|
||||
expectedPath := []string{"fix-path1=fix-path-value1"}
|
||||
assert.Equal(t, expectedPath, actualPaths)
|
||||
|
||||
// Test case 3: Multiple ResourceAssociatedRules and multiple ReviewPaths
|
||||
actualPaths = fixPathsToString(multipleRulesControl)
|
||||
actualPaths = fixPathsToString(multipleRulesControl, false)
|
||||
expectedPath = []string{"fix-path2=fix-path-value2", "fix-path3=fix-path-value3"}
|
||||
assert.Equal(t, expectedPath, actualPaths)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package printer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -187,8 +188,10 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
|
||||
run := sarif.NewRunWithInformationURI(toolName, toolInfoURI)
|
||||
basePath := getBasePathFromMetadata(*opaSessionObj)
|
||||
|
||||
for resourceID, result := range opaSessionObj.ResourcesResult {
|
||||
for resourceID, result := range opaSessionObj.ResourcesResult { //
|
||||
if result.GetStatus(nil).IsFailed() {
|
||||
helmChartFileType := false
|
||||
var mappingnodes []map[string]cautils.MappingNode
|
||||
resourceSource := opaSessionObj.ResourceSource[resourceID]
|
||||
filepath := resourceSource.RelativePath
|
||||
|
||||
@@ -197,9 +200,15 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
|
||||
continue
|
||||
}
|
||||
|
||||
// If the fileType is helm chart
|
||||
if templateNodes, ok := opaSessionObj.TemplateMapping[resourceID]; ok {
|
||||
mappingnodes = templateNodes.Nodes
|
||||
helmChartFileType = true
|
||||
}
|
||||
|
||||
rsrcAbsPath := path.Join(basePath, filepath)
|
||||
locationResolver, err := locationresolver.NewFixPathLocationResolver(rsrcAbsPath)
|
||||
if err != nil {
|
||||
locationResolver, err := locationresolver.NewFixPathLocationResolver(rsrcAbsPath) //
|
||||
if err != nil && !helmChartFileType {
|
||||
logger.L().Debug("failed to create location resolver", helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
@@ -208,12 +217,24 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
|
||||
ac := toPin
|
||||
|
||||
if ac.GetStatus(nil).IsFailed() {
|
||||
ctl := opaSessionObj.Report.SummaryDetails.Controls.GetControl(reportsummary.EControlCriteriaID, ac.GetID())
|
||||
location := sp.resolveFixLocation(opaSessionObj, locationResolver, &ac, resourceID)
|
||||
var location locationresolver.Location
|
||||
|
||||
ctl := opaSessionObj.Report.SummaryDetails.Controls.GetControl(reportsummary.EControlCriteriaID, ac.GetID())
|
||||
if helmChartFileType {
|
||||
for _, subfileNodes := range mappingnodes {
|
||||
// first get the failed path, then if cannot find it, use the Fix path, cui it to find the closest error.
|
||||
location, split := resolveFixLocation(subfileNodes, &ac)
|
||||
sp.addRule(run, ctl)
|
||||
r := sp.addResult(run, ctl, filepath, location)
|
||||
collectFixesFromMappingNodes(r, ac, opaSessionObj, resourceID, filepath, rsrcAbsPath, location, subfileNodes, split)
|
||||
}
|
||||
} else {
|
||||
location = sp.resolveFixLocation(opaSessionObj, locationResolver, &ac, resourceID)
|
||||
sp.addRule(run, ctl)
|
||||
r := sp.addResult(run, ctl, filepath, location)
|
||||
collectFixes(ctx, r, ac, opaSessionObj, resourceID, filepath, rsrcAbsPath)
|
||||
}
|
||||
|
||||
sp.addRule(run, ctl)
|
||||
result := sp.addResult(run, ctl, filepath, location)
|
||||
collectFixes(ctx, result, ac, opaSessionObj, resourceID, filepath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,6 +278,56 @@ func (sp *SARIFPrinter) resolveFixLocation(opaSessionObj *cautils.OPASessionObj,
|
||||
return location
|
||||
}
|
||||
|
||||
func getFixPath(ac *resourcesresults.ResourceAssociatedControl, onlyPath bool) string {
|
||||
fixPaths := failedPathsToString(ac)
|
||||
if len(fixPaths) == 0 {
|
||||
fixPaths = fixPathsToString(ac, onlyPath)
|
||||
}
|
||||
var fixPath string
|
||||
if len(fixPaths) > 0 {
|
||||
fixPath = fixPaths[0]
|
||||
}
|
||||
return fixPath
|
||||
}
|
||||
|
||||
func resolveFixLocation(mappingnodes map[string]cautils.MappingNode, ac *resourcesresults.ResourceAssociatedControl) (locationresolver.Location, int) {
|
||||
defaultLocation := locationresolver.Location{Line: 1, Column: 1}
|
||||
fixPath := getFixPath(ac, true)
|
||||
if fixPath == "" {
|
||||
return defaultLocation, -1
|
||||
}
|
||||
location, split := getLocationFromMappingNodes(mappingnodes, fixPath)
|
||||
return location, split
|
||||
}
|
||||
|
||||
func getLocationFromNode(node cautils.MappingNode, path string) locationresolver.Location {
|
||||
line := node.TemplateLineNumber
|
||||
column := (len(strings.Split(path, "."))-1)*2 + 1 //column begins with 1 instead of 0
|
||||
return locationresolver.Location{Line: line, Column: column}
|
||||
}
|
||||
|
||||
func getLocationFromMappingNodes(mappingnodes map[string]cautils.MappingNode, fixPath string) (locationresolver.Location, int) {
|
||||
var location locationresolver.Location
|
||||
// If cannot match any node, return default location
|
||||
location = locationresolver.Location{Line: 1, Column: 1}
|
||||
split := -1
|
||||
if node, ok := mappingnodes[fixPath]; ok {
|
||||
location = getLocationFromNode(node, fixPath)
|
||||
} else {
|
||||
fields := strings.Split(fixPath, ".")
|
||||
for i := len(fields) - 1; i >= 0; i-- {
|
||||
field := fields[:i]
|
||||
closestPath := strings.Join(field, ".")
|
||||
if node, ok := mappingnodes[closestPath]; ok {
|
||||
location = getLocationFromNode(node, closestPath)
|
||||
split = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return location, split
|
||||
}
|
||||
|
||||
func addFix(result *sarif.Result, filepath string, startLine, startColumn, endLine, endColumn int, text string) {
|
||||
// Create a new replacement with the specified start and end lines and columns, and the inserted text.
|
||||
replacement := sarif.NewReplacement(
|
||||
@@ -272,6 +343,15 @@ func addFix(result *sarif.Result, filepath string, startLine, startColumn, endLi
|
||||
sarif.NewSimpleArtifactLocation(filepath),
|
||||
).WithReplacement(replacement)
|
||||
|
||||
// check if the fix is already added
|
||||
for _, fix := range result.Fixes {
|
||||
for _, ac := range fix.ArtifactChanges {
|
||||
if hashArtifactChange(ac) == hashArtifactChange(artifactChange) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the artifact change to the result's fixes.
|
||||
result.AddFix(sarif.NewFix().WithArtifactChanges([]*sarif.ArtifactChange{artifactChange}))
|
||||
}
|
||||
@@ -337,33 +417,34 @@ func collectDiffs(dmp *diffmatchpatch.DiffMatchPatch, diffs []diffmatchpatch.Dif
|
||||
}
|
||||
}
|
||||
|
||||
func collectFixes(ctx context.Context, result *sarif.Result, ac resourcesresults.ResourceAssociatedControl, opaSessionObj *cautils.OPASessionObj, resourceID string, filepath string) {
|
||||
func collectFixes(ctx context.Context, result *sarif.Result, ac resourcesresults.ResourceAssociatedControl, opaSessionObj *cautils.OPASessionObj, resourceID string, filepath string, rsrcAbsPath string) {
|
||||
for _, rule := range ac.ResourceAssociatedRules {
|
||||
if !rule.GetStatus(nil).IsFailed() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, rulePaths := range rule.Paths {
|
||||
if rulePaths.FixPath.Path == "" {
|
||||
fixPath := rulePaths.FixPath.Path
|
||||
if fixPath == "" {
|
||||
continue
|
||||
}
|
||||
// if strings.HasPrefix(rulePaths.FixPath.Value, fixhandler.UserValuePrefix) {
|
||||
// continue
|
||||
// }
|
||||
|
||||
fileAsString, err := fixhandler.GetFileString(rsrcAbsPath)
|
||||
if err != nil {
|
||||
logger.L().Debug("failed to access "+filepath, helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
var fixedYamlString string
|
||||
|
||||
documentIndex, ok := getDocIndex(opaSessionObj, resourceID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
yamlExpression := fixhandler.FixPathToValidYamlExpression(rulePaths.FixPath.Path, rulePaths.FixPath.Value, documentIndex)
|
||||
fileAsString, err := fixhandler.GetFileString(filepath)
|
||||
if err != nil {
|
||||
logger.L().Debug("failed to access "+filepath, helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
yamlExpression := fixhandler.FixPathToValidYamlExpression(fixPath, rulePaths.FixPath.Value, documentIndex)
|
||||
|
||||
fixedYamlString, err := fixhandler.ApplyFixToContent(ctx, fileAsString, yamlExpression)
|
||||
fixedYamlString, err = fixhandler.ApplyFixToContent(ctx, fileAsString, yamlExpression)
|
||||
if err != nil {
|
||||
logger.L().Debug("failed to fix "+filepath+" with "+yamlExpression, helpers.Error(err))
|
||||
continue
|
||||
@@ -376,6 +457,98 @@ func collectFixes(ctx context.Context, result *sarif.Result, ac resourcesresults
|
||||
}
|
||||
}
|
||||
|
||||
func collectFixesFromMappingNodes(result *sarif.Result, ac resourcesresults.ResourceAssociatedControl, opaSessionObj *cautils.OPASessionObj, resourceID string, filepath string, rsrcAbsPath string, location locationresolver.Location, subFileNodes map[string]cautils.MappingNode, split int) {
|
||||
for _, rule := range ac.ResourceAssociatedRules {
|
||||
if !rule.GetStatus(nil).IsFailed() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, rulePaths := range rule.Paths {
|
||||
fixPath := rulePaths.FixPath.Path
|
||||
if fixPath == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
fileAsString, err := fixhandler.GetFileString(rsrcAbsPath)
|
||||
if err != nil {
|
||||
logger.L().Debug("failed to access "+filepath, helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
var fixedYamlString string
|
||||
fixValue := rulePaths.FixPath.Value
|
||||
if split == -1 { //replaceNode
|
||||
node := subFileNodes[fixPath]
|
||||
fixedYamlString = formReplaceFixedYamlString(node, fileAsString, location, fixValue, fixPath)
|
||||
} else { //insertNode
|
||||
maxLineNumber := getTheLocationOfAddPart(split, fixPath, subFileNodes)
|
||||
fixedYamlString = applyFixToContent(split, fixPath, fileAsString, maxLineNumber, fixValue)
|
||||
}
|
||||
|
||||
dmp := diffmatchpatch.New()
|
||||
diffs := dmp.DiffMain(fileAsString, fixedYamlString, false)
|
||||
collectDiffs(dmp, diffs, result, filepath, fileAsString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyFixToContent(split int, fixPath string, fileAsString string, addLine int, value string) string {
|
||||
addLines := make([]string, 0)
|
||||
fields := strings.Split(fixPath, ".")
|
||||
for i := split; i < len(fields); i++ {
|
||||
field := fields[i]
|
||||
var addedLine string
|
||||
if i != len(fields)-1 {
|
||||
addedLine = strings.Repeat(" ", (i*2)) + field + ":"
|
||||
} else {
|
||||
addedLine = strings.Repeat(" ", (i*2)) + field + ": " + value
|
||||
}
|
||||
addLines = append(addLines, addedLine)
|
||||
}
|
||||
fixedYamlString := formAddFixedYamlString(fileAsString, addLine, addLines)
|
||||
|
||||
return fixedYamlString
|
||||
}
|
||||
|
||||
func formReplaceFixedYamlString(node cautils.MappingNode, fileAsString string, location locationresolver.Location, fixValue string, fixPath string) string {
|
||||
replcaedValue := node.Value
|
||||
yamlLines := strings.Split(fileAsString, "\n")
|
||||
if replcaedValue == "" {
|
||||
yamlLines[location.Line] = yamlLines[location.Line] + " # This is the suggested modification, the value for " + fixPath + " is " + fixValue + "\n"
|
||||
} else {
|
||||
replacedLine := "# This is the suggested modification\n" + yamlLines[location.Line]
|
||||
newLine := strings.Replace(replacedLine, replcaedValue, fixValue, -1)
|
||||
yamlLines[location.Line] = newLine
|
||||
}
|
||||
fixedYamlString := strings.Join(yamlLines, "\n")
|
||||
return fixedYamlString
|
||||
}
|
||||
|
||||
func formAddFixedYamlString(fileAsString string, addLine int, addLines []string) string {
|
||||
yamlLines := strings.Split(fileAsString, "\n")
|
||||
newYamlLines := append(yamlLines[:addLine], "# This is the suggested modification")
|
||||
newYamlLines = append(newYamlLines, addLines...)
|
||||
yamlLines = strings.Split(fileAsString, "\n")
|
||||
newYamlLines = append(newYamlLines, yamlLines[addLine:]...)
|
||||
fixedYamlString := strings.Join(newYamlLines, "\n")
|
||||
return fixedYamlString
|
||||
}
|
||||
|
||||
func getTheLocationOfAddPart(split int, fixPath string, mappingnodes map[string]cautils.MappingNode) int {
|
||||
fields := strings.Split(fixPath, ".")
|
||||
field := fields[:split]
|
||||
closestPath := strings.Join(field, ".")
|
||||
maxLineNumber := -1
|
||||
for k, v := range mappingnodes {
|
||||
if strings.Index(k, closestPath) == 0 {
|
||||
if v.TemplateLineNumber > maxLineNumber {
|
||||
maxLineNumber = v.TemplateLineNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxLineNumber
|
||||
}
|
||||
|
||||
func getDocIndex(opaSessionObj *cautils.OPASessionObj, resourceID string) (int, bool) {
|
||||
resource := opaSessionObj.AllResources[resourceID]
|
||||
localworkload, ok := resource.(*localworkload.LocalWorkload)
|
||||
@@ -410,3 +583,7 @@ func getBasePathFromMetadata(opaSessionObj cautils.OPASessionObj) string {
|
||||
func (sp *SARIFPrinter) generateRemediationMessage(control reportsummary.IControlSummary) string {
|
||||
return fmt.Sprintf("Remediation: %s", control.GetRemediation())
|
||||
}
|
||||
func hashArtifactChange(artifactChange *sarif.ArtifactChange) [32]byte {
|
||||
acJson, _ := json.Marshal(artifactChange)
|
||||
return sha256.Sum256(acJson)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
const indicator = "†"
|
||||
|
||||
// finalizeV2Report finalize the results objects by copying data from map to lists
|
||||
// FinalizeResults finalize the results objects by copying data from map to lists
|
||||
func FinalizeResults(data *cautils.OPASessionObj) *reporthandlingv2.PostureReport {
|
||||
report := reporthandlingv2.PostureReport{
|
||||
SummaryDetails: data.Report.SummaryDetails,
|
||||
|
||||
@@ -76,7 +76,7 @@ func (report *ReportEventReceiver) Submit(ctx context.Context, opaSessionObj *ca
|
||||
}
|
||||
|
||||
if err := report.prepareReport(opaSessionObj); err != nil {
|
||||
return fmt.Errorf("failed to submit scan results. url: '%s', reason: %s", report.getReportUrl(), err.Error())
|
||||
return fmt.Errorf("failed to submit scan results. reason: %s", err.Error())
|
||||
}
|
||||
|
||||
logger.L().Debug("", helpers.String("account ID", report.GetAccountID()))
|
||||
@@ -249,7 +249,7 @@ func (report *ReportEventReceiver) sendReport(postureReport *reporthandlingv2.Po
|
||||
report.tenantConfig.DeleteCredentials()
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s, %v:%s", report.getReportUrl(), err, strResponse)
|
||||
return fmt.Errorf("%w:%s", err, strResponse)
|
||||
}
|
||||
|
||||
// message is taken only from last report
|
||||
|
||||
@@ -146,7 +146,7 @@ func ValidatePrinter(scanType cautils.ScanTypes, scanContext cautils.ScanningCon
|
||||
if printFormat == printer.SARIFFormat {
|
||||
// supported types for SARIF
|
||||
switch scanContext {
|
||||
case cautils.ContextDir, cautils.ContextFile, cautils.ContextGitLocal:
|
||||
case cautils.ContextDir, cautils.ContextFile, cautils.ContextGitLocal, cautils.ContextGitRemote:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("format \"%s\" is only supported when scanning local files", printFormat)
|
||||
|
||||
@@ -14,30 +14,30 @@ import (
|
||||
|
||||
type DummyReporter struct{}
|
||||
|
||||
func (dr *DummyReporter) Submit(_ context.Context, opaSessionObj *cautils.OPASessionObj) error {
|
||||
func (dr *DummyReporter) Submit(_ context.Context, _ *cautils.OPASessionObj) error {
|
||||
return nil
|
||||
}
|
||||
func (dr *DummyReporter) SetTenantConfig(tenantConfig cautils.ITenantConfig) {}
|
||||
func (dr *DummyReporter) DisplayMessage() {}
|
||||
func (dr *DummyReporter) GetURL() string { return "" }
|
||||
func (dr *DummyReporter) SetTenantConfig(_ cautils.ITenantConfig) {}
|
||||
func (dr *DummyReporter) DisplayMessage() {}
|
||||
func (dr *DummyReporter) GetURL() string { return "" }
|
||||
|
||||
type SpyPrinter struct {
|
||||
ActionPrintCalls int
|
||||
ScoreCalls int
|
||||
}
|
||||
|
||||
func (sp *SpyPrinter) SetWriter(_ context.Context, outputFile string) {}
|
||||
func (sp *SpyPrinter) PrintNextSteps() {}
|
||||
func (sp *SpyPrinter) ActionPrint(_ context.Context, opaSessionObj *cautils.OPASessionObj, _ []cautils.ImageScanData) {
|
||||
func (sp *SpyPrinter) SetWriter(_ context.Context, _ string) {}
|
||||
func (sp *SpyPrinter) PrintNextSteps() {}
|
||||
func (sp *SpyPrinter) ActionPrint(_ context.Context, _ *cautils.OPASessionObj, _ []cautils.ImageScanData) {
|
||||
sp.ActionPrintCalls += 1
|
||||
}
|
||||
func (sp *SpyPrinter) Score(score float32) {
|
||||
func (sp *SpyPrinter) Score(_ float32) {
|
||||
sp.ScoreCalls += 1
|
||||
}
|
||||
|
||||
func TestResultsHandlerHandleResultsPrintsResultsToUI(t *testing.T) {
|
||||
reporter := &DummyReporter{}
|
||||
printers := []printer.IPrinter{}
|
||||
var printers []printer.IPrinter
|
||||
uiPrinter := &SpyPrinter{}
|
||||
fakeScanData := &cautils.OPASessionObj{
|
||||
Report: &reporthandlingv2.PostureReport{
|
||||
@@ -50,7 +50,8 @@ func TestResultsHandlerHandleResultsPrintsResultsToUI(t *testing.T) {
|
||||
rh := NewResultsHandler(reporter, printers, uiPrinter)
|
||||
rh.SetData(fakeScanData)
|
||||
|
||||
rh.HandleResults(context.TODO())
|
||||
err := rh.HandleResults(context.TODO())
|
||||
assert.NoError(t, err)
|
||||
|
||||
want := 1
|
||||
got := uiPrinter.ActionPrintCalls
|
||||
@@ -147,12 +148,6 @@ func TestValidatePrinter(t *testing.T) {
|
||||
format: printer.SARIFFormat,
|
||||
expectErr: errors.New("format \"sarif\" is only supported when scanning local files"),
|
||||
},
|
||||
{
|
||||
name: "sarif format for remote url context should return error",
|
||||
scanContext: cautils.ContextGitURL,
|
||||
format: printer.SARIFFormat,
|
||||
expectErr: errors.New("format \"sarif\" is only supported when scanning local files"),
|
||||
},
|
||||
{
|
||||
name: "sarif format for local dir context should not return error",
|
||||
scanContext: cautils.ContextDir,
|
||||
@@ -240,7 +235,7 @@ func TestNewPrinter(t *testing.T) {
|
||||
version: defaultVersion,
|
||||
},
|
||||
{
|
||||
name: "Prettry printer",
|
||||
name: "Pretty printer",
|
||||
format: "pretty-printer",
|
||||
viewType: "control",
|
||||
version: defaultVersion,
|
||||
@@ -259,8 +254,8 @@ func TestNewPrinter(t *testing.T) {
|
||||
FormatVersion: tt.version,
|
||||
View: tt.viewType,
|
||||
}
|
||||
printer := NewPrinter(ctx, tt.format, scanInfo, "my-cluster")
|
||||
assert.NotNil(t, printer)
|
||||
p := NewPrinter(ctx, tt.format, scanInfo, "my-cluster")
|
||||
assert.NotNil(t, p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
BIN
docs/img/kcd-amsterdam-rabo.jpg
Normal file
BIN
docs/img/kcd-amsterdam-rabo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 558 KiB |
@@ -14,23 +14,19 @@ The features serve different stages of the workflow of the users:
|
||||
The items in the Kubescape roadmap are split into 3 major groups based on the feature planning maturity:
|
||||
|
||||
* [Planning](#planning-) - we have tickets open for these issues with a more or less clear vision of design.
|
||||
* [Backlog](#backlog-) - features that were discussed at a high level but are not ready for development.
|
||||
* [Backlog](#backlog-) - features that were discussed at a high level but are not ready for development.
|
||||
* [Wishlist](#wishlist-) - features that we are dreaming of in 😀 and want to push them gradually forward.
|
||||
|
||||
|
||||
## Planning 👷
|
||||
|
||||
* ### Storing scan results in cluster
|
||||
* ### eBPF based anomaly detection in workloads
|
||||
|
||||
We want the Kubescape scan results (both cluster and image scan) to be stored in the cluster locally as `CRD`s. This will lead to an easier integration with results by other projects as well as with scripting via `kubectl`. Along with this, the image scan based controls will be able to avoid accessing external resources for image vulnerability scan results.
|
||||
The introduction of runtime anomaly detection using eBPF (extended Berkeley Packet Filter) events marks an addition to the Kubescape project's development roadmap. This feature aims to leverage the high-performance monitoring capabilities of eBPF to detect abnormal behavior within Kubernetes workloads in real-time. By capturing and analyzing eBPF events, Kubescape will be able to identify deviations from application profiles, such as unexpected network connections, unauthorized process executions, or unusual system calls, which could indicate a security breach. This anomaly detection mechanism is designed to operate with minimal overhead, ensuring that security monitoring does not compromise system performance.
|
||||
|
||||
* ### Vulnerability prioritization based on workload file activity
|
||||
* ### Enriching Vulnerability scan results with advanced prioritization data sources
|
||||
|
||||
Implementing an eBPF agent (based on Falco or Tracee) which tracks file activity in workloads to prioritize container image vulnerabilities.
|
||||
|
||||
* ### Prioritization engine using MITRE Attack matrix based attack chains
|
||||
|
||||
Create a security issue prioritization engine that scores resources based on control based attack chains. All Kubescape controls can be arranged into attack categories of the MITRE Attack matrix. The Attack matrix categories can be connected to each other based on a theoretical attack (ie. you can't have privilege escalation without initial access). Each of the Kubescape controls is to be categorized in these system and Kubescape will calculate a priority score based on the interconnections between failed controls.
|
||||
Integrating EPSS (Exploit Prediction Scoring System) and CISA-KEV (Known Exploited Vulnerabilities) metrics into Kubescape's CLI and Operator vulnerability scan results represents a significant enhancement in the project's roadmap. This integration aims to enrich the vulnerability management process by providing more contextual and predictive insights into the security risks associated with Kubernetes clusters. By leveraging EPSS scores, Kubescape will offer predictions on the likelihood of a vulnerability being exploited, enabling users to prioritize remediations based on risk rather than just vulnerability presence. The addition of CISA-KEV metrics further enhances this capability by flagging vulnerabilities that are actively being exploited in the wild, as identified by the Cybersecurity and Infrastructure Security Agency (CISA). This dual approach ensures that Kubescape users are not only informed about the vulnerabilities in their environments but are also equipped with critical information on which vulnerabilities to remediate first, based on their exploitability and active exploitation trends. This strategic enhancement to Kubescape's vulnerability scan results will provide users with a powerful tool for making informed, risk-based security decisions in their Kubernetes environments.
|
||||
|
||||
* ### Integration with image registries
|
||||
|
||||
@@ -39,7 +35,7 @@ The items in the Kubescape roadmap are split into 3 major groups based on the fe
|
||||
* ### Kubescape CLI control over cluster operations
|
||||
|
||||
Add functionality to Kubescape CLI to trigger operations in Kubescape cluster components (example: trigger image scans, etc.)
|
||||
|
||||
|
||||
* ### Git integration for pull requests
|
||||
|
||||
Create insightful GitHub actions for Kubescape.
|
||||
@@ -91,14 +87,14 @@ The items in the Kubescape roadmap are split into 3 major groups based on the fe
|
||||
|
||||
## Completed features 🎓
|
||||
|
||||
* Kubelet configuration validation
|
||||
* Kubelet configuration validation
|
||||
* API server configuration validation
|
||||
* Image vulnerability scanning based controls
|
||||
* Image vulnerability scanning based controls
|
||||
* Assisted remediation (telling where/what to fix)
|
||||
* Integration with Prometheus
|
||||
* Configuration of controls (customizing rules for a given environment)
|
||||
* Installation in the cluster for continuous monitoring
|
||||
* Host scanner
|
||||
* Host scanner
|
||||
* Cloud vendor API integration
|
||||
* Custom exceptions
|
||||
* Custom frameworks
|
||||
|
||||
29
examples/helm_chart_mapping_node/Chart.yaml
Normal file
29
examples/helm_chart_mapping_node/Chart.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: v2
|
||||
name: kubescape
|
||||
description:
|
||||
Kubescape is the first open-source tool for testing if Kubernetes is deployed securely according to multiple frameworks
|
||||
regulatory, customized company policies and DevSecOps best practices, such as the [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo) and the [MITRE ATT&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) .
|
||||
Kubescape scans K8s clusters, YAML files, and HELM charts, and detect misconfigurations and software vulnerabilities at early stages of the CI/CD pipeline and provides a risk score instantly and risk trends over time.
|
||||
Kubescape integrates natively with other DevOps tools, including Jenkins, CircleCI and Github workflows.
|
||||
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 1.0.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "v1.0.128"
|
||||
62
examples/helm_chart_mapping_node/templates/_helpers.tpl
Normal file
62
examples/helm_chart_mapping_node/templates/_helpers.tpl
Normal file
@@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "kubescape.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "kubescape.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "kubescape.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "kubescape.labels" -}}
|
||||
helm.sh/chart: {{ include "kubescape.chart" . }}
|
||||
{{ include "kubescape.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "kubescape.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "kubescape.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "kubescape.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "kubescape.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
10
examples/helm_chart_mapping_node/templates/clusterrole.yaml
Normal file
10
examples/helm_chart_mapping_node/templates/clusterrole.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "list", "describe"]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubescape.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
|
||||
|
||||
14
examples/helm_chart_mapping_node/templates/configmap.yaml
Normal file
14
examples/helm_chart_mapping_node/templates/configmap.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.configMap.create -}}
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}-configmap
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
data:
|
||||
config.json: |
|
||||
{
|
||||
"customerGUID": "{{ .Values.configMap.params.customerGUID }}",
|
||||
"clusterName": "{{ .Values.configMap.params.clusterName }}"
|
||||
}
|
||||
{{- end }}
|
||||
28
examples/helm_chart_mapping_node/templates/cronjob.yaml
Normal file
28
examples/helm_chart_mapping_node/templates/cronjob.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
spec:
|
||||
schedule: "{{ .Values.schedule }}"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}/{{ .Values.image.imageName }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command: ["/bin/sh", "-c"]
|
||||
args: ["kubescape scan framework nsa --submit"]
|
||||
volumeMounts:
|
||||
- name: kubescape-config-volume
|
||||
mountPath: /root/.kubescape/config.json
|
||||
subPath: config.json
|
||||
restartPolicy: OnFailure
|
||||
serviceAccountName: {{ include "kubescape.serviceAccountName" . }}
|
||||
volumes:
|
||||
- name: kubescape-config-volume
|
||||
configMap:
|
||||
name: {{ include "kubescape.fullname" . }}-configmap
|
||||
11
examples/helm_chart_mapping_node/templates/role.yaml
Normal file
11
examples/helm_chart_mapping_node/templates/role.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "list", "describe"]
|
||||
|
||||
16
examples/helm_chart_mapping_node/templates/rolebinding.yaml
Normal file
16
examples/helm_chart_mapping_node/templates/rolebinding.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ include "kubescape.fullname" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubescape.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "kubescape.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "kubescape.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "kubescape.serviceAccountName" . }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
74
examples/helm_chart_mapping_node/values.yaml
Normal file
74
examples/helm_chart_mapping_node/values.yaml
Normal file
@@ -0,0 +1,74 @@
|
||||
# Default values for kubescape.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
# -- Frequency of running the scan
|
||||
# ┌────────────── timezone (optional)
|
||||
# | ┌───────────── minute (0 - 59)
|
||||
# | │ ┌───────────── hour (0 - 23)
|
||||
# | │ │ ┌───────────── day of the month (1 - 31)
|
||||
# | │ │ │ ┌───────────── month (1 - 12)
|
||||
# | │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
|
||||
# | │ │ │ │ │ 7 is also Sunday on some systems)
|
||||
# | │ │ │ │ │
|
||||
# | │ │ │ │ │
|
||||
# UTC * * * * *
|
||||
schedule: "* * 1 * *"
|
||||
|
||||
# -- Image and version to deploy
|
||||
image:
|
||||
repository: quay.io/armosec
|
||||
imageName: kubescape
|
||||
pullPolicy: Always
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: latest
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# -- Service account that runs the scan and has permissions to view the cluster
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: "kubescape-discovery"
|
||||
|
||||
# -- ARMO customer information
|
||||
configMap:
|
||||
create: false
|
||||
params:
|
||||
customerGUID: <MyGUID>
|
||||
clusterName: <MyK8sClusterName>
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
# -- Default resources for running the service in cluster
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
241
go.mod
241
go.mod
@@ -6,54 +6,53 @@ toolchain go1.21.6
|
||||
|
||||
require (
|
||||
github.com/adrg/xdg v0.4.0
|
||||
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc
|
||||
github.com/anchore/grype v0.74.2
|
||||
github.com/anchore/stereoscope v0.0.1
|
||||
github.com/anchore/syft v0.101.1
|
||||
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65
|
||||
github.com/anchore/grype v0.77.1
|
||||
github.com/anchore/stereoscope v0.0.3-0.20240423181235-8b297badafd5
|
||||
github.com/anchore/syft v1.3.0
|
||||
github.com/armosec/armoapi-go v0.0.330
|
||||
github.com/armosec/utils-go v0.0.57
|
||||
github.com/armosec/utils-k8s-go v0.0.26
|
||||
github.com/briandowns/spinner v1.23.0
|
||||
github.com/chainguard-dev/git-urls v1.0.2
|
||||
github.com/distribution/distribution v2.8.3+incompatible
|
||||
github.com/docker/distribution v2.8.3+incompatible
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/enescakir/emoji v1.0.0
|
||||
github.com/francoispqt/gojay v1.2.13
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/google/go-containerregistry v0.19.0
|
||||
github.com/go-git/go-git/v5 v5.12.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/json-iterator/go v1.1.12
|
||||
github.com/jwalton/gchalk v1.3.0
|
||||
github.com/kubescape/backend v0.0.18
|
||||
github.com/kubescape/go-git-url v0.0.27
|
||||
github.com/kubescape/backend v0.0.20
|
||||
github.com/kubescape/go-git-url v0.0.30
|
||||
github.com/kubescape/go-logger v0.0.22
|
||||
github.com/kubescape/k8s-interface v0.0.161
|
||||
github.com/kubescape/opa-utils v0.0.277
|
||||
github.com/kubescape/k8s-interface v0.0.166
|
||||
github.com/kubescape/opa-utils v0.0.281
|
||||
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520
|
||||
github.com/kubescape/regolibrary v1.0.315
|
||||
github.com/kubescape/regolibrary/v2 v2.0.1
|
||||
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
|
||||
github.com/mikefarah/yq/v4 v4.29.1
|
||||
github.com/olekukonko/tablewriter v0.0.6-0.20230417144759-edd1a71a5576
|
||||
github.com/open-policy-agent/opa v0.61.0
|
||||
github.com/open-policy-agent/opa v0.63.0
|
||||
github.com/owenrumney/go-sarif/v2 v2.2.0
|
||||
github.com/project-copacetic/copacetic v0.0.0-00010101000000-000000000000
|
||||
github.com/schollz/progressbar/v3 v3.13.0
|
||||
github.com/sergi/go-diff v1.3.1
|
||||
github.com/sigstore/cosign/v2 v2.2.3
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
github.com/sigstore/cosign/v2 v2.2.4
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.opentelemetry.io/otel v1.22.0
|
||||
go.opentelemetry.io/otel/metric v1.22.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.opentelemetry.io/otel v1.24.0
|
||||
go.opentelemetry.io/otel/metric v1.24.0
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||
golang.org/x/mod v0.15.0
|
||||
golang.org/x/term v0.17.0
|
||||
golang.org/x/mod v0.17.0
|
||||
golang.org/x/term v0.19.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.2
|
||||
helm.sh/helm/v3 v3.14.4
|
||||
k8s.io/api v0.29.2
|
||||
k8s.io/apimachinery v0.29.2
|
||||
k8s.io/client-go v0.29.2
|
||||
@@ -65,21 +64,21 @@ require (
|
||||
require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.111.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go v0.112.1 // indirect
|
||||
cloud.google.com/go/compute v1.25.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/container v1.29.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
cloud.google.com/go/storage v1.35.1 // indirect
|
||||
cloud.google.com/go/container v1.33.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.6 // indirect
|
||||
cloud.google.com/go/storage v1.39.1 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.1.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v2 v2.4.0 // indirect
|
||||
@@ -91,10 +90,10 @@ require (
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0 // indirect
|
||||
github.com/DataDog/zstd v1.4.5 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
@@ -102,7 +101,7 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.4 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
||||
github.com/a8m/envsubst v1.3.0 // indirect
|
||||
github.com/acobaugh/osrelease v0.1.0 // indirect
|
||||
@@ -120,11 +119,12 @@ require (
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/aliyun/credentials-go v1.3.1 // indirect
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b // indirect
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 // indirect
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a // indirect
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 // indirect
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 // indirect
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240312213626-055233e539b4 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antchfx/xmlquery v1.3.17 // indirect
|
||||
github.com/antchfx/xpath v1.2.4 // indirect
|
||||
@@ -135,24 +135,24 @@ require (
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230726112157-167ba4f2faeb // indirect
|
||||
github.com/armosec/gojay v1.2.15 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.50.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go v1.51.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.20.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/eks v1.28.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.21.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect
|
||||
github.com/aws/smithy-go v1.20.1 // indirect
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
@@ -168,22 +168,22 @@ require (
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.9.1 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.10.0 // indirect
|
||||
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/containerd v1.7.12 // indirect
|
||||
github.com/containerd/containerd v1.7.14 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.2 // indirect
|
||||
github.com/containerd/ttrpc v1.2.3 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.9.0 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.10.0 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.1 // indirect
|
||||
github.com/cpuguy83/go-docker v0.2.1 // indirect
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect
|
||||
@@ -193,9 +193,10 @@ require (
|
||||
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
|
||||
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/cli v24.0.7+incompatible // indirect
|
||||
github.com/docker/docker v25.0.1+incompatible // indirect
|
||||
github.com/distribution/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/cli v26.1.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v26.1.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
@@ -204,6 +205,7 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/elliotchance/orderedmap v1.5.0 // indirect
|
||||
github.com/elliotchance/phpserialize v1.4.0 // indirect
|
||||
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
|
||||
@@ -215,26 +217,27 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/github/go-spdx/v2 v2.2.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.10.0 // indirect
|
||||
github.com/glebarez/sqlite v1.11.0 // indirect
|
||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.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.1 // 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-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.22.0 // indirect
|
||||
github.com/go-openapi/errors v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/loads v0.21.5 // indirect
|
||||
github.com/go-openapi/runtime v0.27.1 // indirect
|
||||
github.com/go-openapi/spec v0.20.13 // indirect
|
||||
github.com/go-openapi/strfmt v0.22.0 // indirect
|
||||
github.com/go-openapi/swag v0.22.9 // indirect
|
||||
github.com/go-openapi/validate v0.22.4 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-piv/piv-go v1.11.0 // indirect
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/go-test/deep v1.1.0 // indirect
|
||||
@@ -245,29 +248,29 @@ require (
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.7 // 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/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
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/licensecheck v0.3.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.3 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.4 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
@@ -289,12 +292,12 @@ require (
|
||||
github.com/jwalton/go-supportscolor v1.1.0 // indirect
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f // indirect
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422 // indirect
|
||||
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075 // indirect
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230517124904-b97c85e63254 // indirect
|
||||
github.com/knqyf263/go-rpmdb v0.1.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
@@ -303,7 +306,6 @@ require (
|
||||
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/matttproud/golang_protobuf_extensions/v2 v2.0.0 // 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
|
||||
@@ -316,10 +318,11 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/buildkit v0.12.5 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/patternmatcher v0.5.0 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/moby/sys/user v0.1.0 // indirect
|
||||
@@ -332,13 +335,14 @@ require (
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/oleiade/reflections v1.0.1 // indirect
|
||||
github.com/olvrng/ujson v1.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
@@ -356,39 +360,39 @@ require (
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/pquerna/cachecontrol v0.2.0 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.51.1 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
|
||||
github.com/saferwall/pe v1.4.8 // 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
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
||||
github.com/samber/lo v1.38.1 // indirect
|
||||
github.com/sassoftware/go-rpmutils v0.2.0 // indirect
|
||||
github.com/sassoftware/go-rpmutils v0.3.0 // indirect
|
||||
github.com/sassoftware/relic v7.2.1+incompatible // indirect
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sigstore/fulcio v1.4.3 // indirect
|
||||
github.com/sigstore/rekor v1.3.4 // indirect
|
||||
github.com/sigstore/sigstore v1.8.1 // indirect
|
||||
github.com/sigstore/timestamp-authority v1.2.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/sigstore/fulcio v1.4.5 // indirect
|
||||
github.com/sigstore/rekor v1.3.6 // indirect
|
||||
github.com/sigstore/sigstore v1.8.3 // indirect
|
||||
github.com/sigstore/timestamp-authority v1.2.2 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spdx/tools-golang v0.5.3 // indirect
|
||||
github.com/spdx/tools-golang v0.5.4 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.18.2 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.1.7 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect
|
||||
github.com/stripe/stripe-go/v74 v74.28.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.11.5 // indirect
|
||||
@@ -414,7 +418,7 @@ require (
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 // indirect
|
||||
github.com/wagoodman/go-presenter v0.0.0-20211015174752-f9c01afc824b // indirect
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 // indirect
|
||||
github.com/xanzy/go-gitlab v0.96.0 // indirect
|
||||
github.com/xanzy/go-gitlab v0.102.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
@@ -425,56 +429,55 @@ require (
|
||||
github.com/yashtewari/glob-intersection v0.2.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.0 // indirect
|
||||
github.com/zeebo/errs v1.3.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.step.sm/crypto v0.42.1 // indirect
|
||||
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.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.19.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
gonum.org/v1/gonum v0.9.1 // indirect
|
||||
google.golang.org/api v0.159.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
|
||||
google.golang.org/api v0.172.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gorm.io/gorm v1.25.5 // indirect
|
||||
gorm.io/gorm v1.25.10 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.29.0 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/klog/v2 v2.120.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
||||
modernc.org/libc v1.29.0 // indirect
|
||||
modernc.org/libc v1.49.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/sqlite v1.28.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.29.8 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.15.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/release-utils v0.7.7 // indirect
|
||||
@@ -488,6 +491,8 @@ replace github.com/olekukonko/tablewriter => github.com/kubescape/tablewriter v0
|
||||
// TODO(anubhav06): Remove this once we have a release of copacetic with the support for patching kubescape image scan results.
|
||||
replace github.com/project-copacetic/copacetic => github.com/anubhav06/copacetic v0.0.0-20230821175613-0a7915a62e10
|
||||
|
||||
replace github.com/anchore/stereoscope => github.com/matthyx/stereoscope v0.0.0-20240227133833-a9e97778940b
|
||||
replace github.com/anchore/stereoscope => github.com/matthyx/stereoscope v0.0.0-20240426103125-b762a3538c32
|
||||
|
||||
replace github.com/google/go-containerregistry => github.com/matthyx/go-containerregistry v0.0.0-20240227132928-63ceb71ae0b9
|
||||
|
||||
replace github.com/docker/distribution v2.8.3+incompatible => github.com/docker/distribution v2.8.2+incompatible
|
||||
|
||||
@@ -10,55 +10,54 @@ require (
|
||||
github.com/armosec/armoapi-go v0.0.330
|
||||
github.com/armosec/utils-go v0.0.57
|
||||
github.com/armosec/utils-k8s-go v0.0.26
|
||||
github.com/go-openapi/runtime v0.27.1
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/kubescape/backend v0.0.18
|
||||
github.com/kubescape/backend v0.0.20
|
||||
github.com/kubescape/go-logger v0.0.22
|
||||
github.com/kubescape/k8s-interface v0.0.161
|
||||
github.com/kubescape/kubescape/v3 v3.0.0-00010101000000-000000000000
|
||||
github.com/kubescape/opa-utils v0.0.277
|
||||
github.com/kubescape/k8s-interface v0.0.166
|
||||
github.com/kubescape/kubescape/v3 v3.0.4
|
||||
github.com/kubescape/opa-utils v0.0.281
|
||||
github.com/kubescape/storage v0.0.20
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.45.0
|
||||
go.opentelemetry.io/otel v1.22.0
|
||||
go.opentelemetry.io/otel v1.24.0
|
||||
k8s.io/apimachinery v0.29.2
|
||||
k8s.io/client-go v0.29.2
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
)
|
||||
|
||||
require (
|
||||
go.opentelemetry.io/otel/trace v1.22.0
|
||||
go.opentelemetry.io/otel/trace v1.24.0
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.19.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.111.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go v0.112.1 // indirect
|
||||
cloud.google.com/go/compute v1.25.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/container v1.29.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
cloud.google.com/go/storage v1.35.1 // indirect
|
||||
cloud.google.com/go/container v1.33.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.6 // indirect
|
||||
cloud.google.com/go/storage v1.39.1 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.1.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v2 v2.4.0 // indirect
|
||||
@@ -70,10 +69,10 @@ require (
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0 // indirect
|
||||
github.com/DataDog/zstd v1.4.5 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
@@ -81,7 +80,7 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.4 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
||||
github.com/a8m/envsubst v1.3.0 // indirect
|
||||
github.com/acobaugh/osrelease v0.1.0 // indirect
|
||||
@@ -99,16 +98,17 @@ require (
|
||||
github.com/alibabacloud-go/tea-utils v1.4.5 // indirect
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/aliyun/credentials-go v1.3.1 // indirect
|
||||
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc // indirect
|
||||
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65 // indirect
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b // indirect
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 // indirect
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a // indirect
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 // indirect
|
||||
github.com/anchore/grype v0.74.2 // indirect
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 // indirect
|
||||
github.com/anchore/stereoscope v0.0.1 // indirect
|
||||
github.com/anchore/syft v0.101.1 // indirect
|
||||
github.com/anchore/grype v0.77.1 // indirect
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240312213626-055233e539b4 // indirect
|
||||
github.com/anchore/stereoscope v0.0.3-0.20240423181235-8b297badafd5 // indirect
|
||||
github.com/anchore/syft v1.3.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antchfx/xmlquery v1.3.17 // indirect
|
||||
github.com/antchfx/xpath v1.2.4 // indirect
|
||||
@@ -119,24 +119,24 @@ require (
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230726112157-167ba4f2faeb // indirect
|
||||
github.com/armosec/gojay v1.2.15 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.50.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go v1.51.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.20.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/eks v1.28.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.21.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect
|
||||
github.com/aws/smithy-go v1.20.1 // indirect
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
@@ -154,22 +154,22 @@ require (
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chainguard-dev/git-urls v1.0.2 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.9.1 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.10.0 // indirect
|
||||
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/containerd v1.7.12 // indirect
|
||||
github.com/containerd/containerd v1.7.14 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.2 // indirect
|
||||
github.com/containerd/ttrpc v1.2.3 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.9.0 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.10.0 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.1 // indirect
|
||||
github.com/cpuguy83/go-docker v0.2.1 // indirect
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect
|
||||
@@ -179,11 +179,11 @@ require (
|
||||
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
|
||||
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/distribution v2.8.3+incompatible // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/cli v24.0.7+incompatible // indirect
|
||||
github.com/distribution/distribution v2.8.2+incompatible // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/cli v26.1.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v25.0.1+incompatible // indirect
|
||||
github.com/docker/docker v26.1.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
@@ -192,6 +192,7 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/elliotchance/orderedmap v1.5.0 // indirect
|
||||
github.com/elliotchance/phpserialize v1.4.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/enescakir/emoji v1.0.0 // indirect
|
||||
@@ -205,26 +206,27 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/github/go-spdx/v2 v2.2.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.10.0 // indirect
|
||||
github.com/glebarez/sqlite v1.11.0 // indirect
|
||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.11.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.12.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.1 // 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-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.22.0 // indirect
|
||||
github.com/go-openapi/errors v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/loads v0.21.5 // indirect
|
||||
github.com/go-openapi/spec v0.20.13 // indirect
|
||||
github.com/go-openapi/strfmt v0.22.0 // indirect
|
||||
github.com/go-openapi/swag v0.22.9 // indirect
|
||||
github.com/go-openapi/validate v0.22.4 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-piv/piv-go v1.11.0 // indirect
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/go-test/deep v1.1.0 // indirect
|
||||
@@ -235,30 +237,30 @@ require (
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.7 // 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/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.1 // indirect
|
||||
github.com/google/go-github/v55 v55.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/licensecheck v0.3.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.3 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.4 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
@@ -283,15 +285,15 @@ require (
|
||||
github.com/jwalton/go-supportscolor v1.1.0 // indirect
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f // indirect
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422 // indirect
|
||||
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075 // indirect
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230517124904-b97c85e63254 // indirect
|
||||
github.com/kubescape/go-git-url v0.0.27 // indirect
|
||||
github.com/knqyf263/go-rpmdb v0.1.0 // indirect
|
||||
github.com/kubescape/go-git-url v0.0.30 // indirect
|
||||
github.com/kubescape/rbac-utils v0.0.21-0.20230806101615-07e36f555520 // indirect
|
||||
github.com/kubescape/regolibrary v1.0.315 // indirect
|
||||
github.com/kubescape/regolibrary/v2 v2.0.1 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
@@ -303,7 +305,6 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // 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
|
||||
@@ -317,10 +318,11 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/buildkit v0.12.5 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/patternmatcher v0.5.0 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/moby/sys/user v0.1.0 // indirect
|
||||
@@ -333,15 +335,16 @@ require (
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/oleiade/reflections v1.0.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.6-0.20230417144759-edd1a71a5576 // indirect
|
||||
github.com/olvrng/ujson v1.1.0 // indirect
|
||||
github.com/open-policy-agent/opa v0.61.0 // indirect
|
||||
github.com/open-policy-agent/opa v0.63.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
@@ -361,43 +364,43 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/pquerna/cachecontrol v0.2.0 // indirect
|
||||
github.com/project-copacetic/copacetic v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.51.1 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
|
||||
github.com/saferwall/pe v1.4.8 // 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
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
||||
github.com/samber/lo v1.38.1 // indirect
|
||||
github.com/sassoftware/go-rpmutils v0.2.0 // indirect
|
||||
github.com/sassoftware/go-rpmutils v0.3.0 // indirect
|
||||
github.com/sassoftware/relic v7.2.1+incompatible // indirect
|
||||
github.com/schollz/progressbar/v3 v3.13.0 // indirect
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sigstore/cosign/v2 v2.2.3 // indirect
|
||||
github.com/sigstore/fulcio v1.4.3 // indirect
|
||||
github.com/sigstore/rekor v1.3.4 // indirect
|
||||
github.com/sigstore/sigstore v1.8.1 // indirect
|
||||
github.com/sigstore/timestamp-authority v1.2.1 // indirect
|
||||
github.com/sigstore/cosign/v2 v2.2.4 // indirect
|
||||
github.com/sigstore/fulcio v1.4.5 // indirect
|
||||
github.com/sigstore/rekor v1.3.6 // indirect
|
||||
github.com/sigstore/sigstore v1.8.3 // indirect
|
||||
github.com/sigstore/timestamp-authority v1.2.2 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spdx/tools-golang v0.5.3 // indirect
|
||||
github.com/spdx/tools-golang v0.5.4 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cobra v1.8.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.1.7 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect
|
||||
github.com/stripe/stripe-go/v74 v74.28.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.11.5 // indirect
|
||||
@@ -423,7 +426,7 @@ require (
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 // indirect
|
||||
github.com/wagoodman/go-presenter v0.0.0-20211015174752-f9c01afc824b // indirect
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 // indirect
|
||||
github.com/xanzy/go-gitlab v0.96.0 // indirect
|
||||
github.com/xanzy/go-gitlab v0.102.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
@@ -434,36 +437,36 @@ require (
|
||||
github.com/yashtewari/glob-intersection v0.2.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.0 // indirect
|
||||
github.com/zeebo/errs v1.3.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.step.sm/crypto v0.42.1 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
go.step.sm/crypto v0.44.2 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
gonum.org/v1/gonum v0.9.1 // indirect
|
||||
google.golang.org/api v0.159.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
|
||||
google.golang.org/api v0.172.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect
|
||||
@@ -471,16 +474,16 @@ require (
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/gorm v1.25.5 // indirect
|
||||
helm.sh/helm/v3 v3.14.2 // indirect
|
||||
gorm.io/gorm v1.25.10 // indirect
|
||||
helm.sh/helm/v3 v3.14.4 // indirect
|
||||
k8s.io/api v0.29.2 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.29.0 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/klog/v2 v2.120.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
||||
modernc.org/libc v1.29.0 // indirect
|
||||
modernc.org/libc v1.49.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/sqlite v1.28.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.29.8 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.15.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
@@ -495,3 +498,5 @@ replace github.com/olekukonko/tablewriter => github.com/kubescape/tablewriter v0
|
||||
|
||||
// TODO(anubhav06): Remove this once we have a release of copacetic with the support for patching kubescape image scan results.
|
||||
replace github.com/project-copacetic/copacetic => github.com/anubhav06/copacetic v0.0.0-20230821175613-0a7915a62e10
|
||||
|
||||
replace github.com/docker/distribution v2.8.3+incompatible => github.com/docker/distribution v2.8.2+incompatible
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/utils-go/boolutils"
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -63,8 +64,8 @@ func scan(ctx context.Context, scanInfo *cautils.ScanInfo, scanID string) (*repo
|
||||
ks := core.NewKubescape()
|
||||
|
||||
spanScan.AddEvent("scanning metadata",
|
||||
trace.WithAttributes(attribute.String("version", cautils.BuildNumber)),
|
||||
trace.WithAttributes(attribute.String("build", cautils.Client)),
|
||||
trace.WithAttributes(attribute.String("version", versioncheck.BuildNumber)),
|
||||
trace.WithAttributes(attribute.String("build", versioncheck.Client)),
|
||||
trace.WithAttributes(attribute.String("scanID", scanInfo.ScanID)),
|
||||
trace.WithAttributes(attribute.Bool("scanAll", scanInfo.ScanAll)),
|
||||
trace.WithAttributes(attribute.Bool("HostSensorEnabled", scanInfo.HostSensorEnabled.GetBool())),
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/metrics"
|
||||
"github.com/kubescape/kubescape/v3/httphandler/docs"
|
||||
handlerequestsv1 "github.com/kubescape/kubescape/v3/httphandler/handlerequests/v1"
|
||||
@@ -69,7 +69,7 @@ func SetupHTTPListener() error {
|
||||
|
||||
server.Handler = rtr
|
||||
|
||||
logger.L().Info("Started Kubescape server", helpers.String("port", getPort()), helpers.String("version", cautils.BuildNumber))
|
||||
logger.L().Info("Started Kubescape server", helpers.String("port", getPort()), helpers.String("version", versioncheck.BuildNumber))
|
||||
|
||||
servePprof()
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"github.com/kubescape/backend/pkg/servicediscovery"
|
||||
servicediscoveryv2 "github.com/kubescape/backend/pkg/servicediscovery/v2"
|
||||
"github.com/kubescape/backend/pkg/utils"
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/go-logger/zaplogger"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
"github.com/kubescape/kubescape/v3/httphandler/config"
|
||||
_ "github.com/kubescape/kubescape/v3/httphandler/docs"
|
||||
@@ -41,7 +41,7 @@ func main() {
|
||||
// to enable otel, set OTEL_COLLECTOR_SVC=otel-collector:4317
|
||||
if otelHost, present := os.LookupEnv("OTEL_COLLECTOR_SVC"); present {
|
||||
ctx = logger.InitOtel("kubescape",
|
||||
os.Getenv(cautils.BuildNumber),
|
||||
os.Getenv(versioncheck.BuildNumber),
|
||||
config.GetAccount(),
|
||||
clusterName,
|
||||
url.URL{Host: otelHost})
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/grype/grype"
|
||||
"github.com/anchore/grype/grype/db"
|
||||
"github.com/anchore/grype/grype/grypeerr"
|
||||
@@ -24,7 +23,7 @@ import (
|
||||
"github.com/anchore/grype/grype/store"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/syft"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -93,36 +92,15 @@ func validateDBLoad(loadErr error, status *db.Status) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type packagesOptions struct {
|
||||
options.Output `yaml:",inline" mapstructure:",squash"`
|
||||
options.Config `yaml:",inline" mapstructure:",squash"`
|
||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func defaultPackagesOptions() *packagesOptions {
|
||||
defaultCatalogOpts := options.DefaultCatalog()
|
||||
|
||||
// TODO(matthyx): assess this value
|
||||
defaultCatalogOpts.Parallelism = 4
|
||||
|
||||
return &packagesOptions{
|
||||
Output: options.DefaultOutput(),
|
||||
UpdateCheck: options.DefaultUpdateCheck(),
|
||||
Catalog: defaultCatalogOpts,
|
||||
}
|
||||
}
|
||||
|
||||
func getProviderConfig(creds RegistryCredentials) pkg.ProviderConfig {
|
||||
syftCreds := []image.RegistryCredentials{{Username: creds.Username, Password: creds.Password}}
|
||||
regOpts := &image.RegistryOptions{
|
||||
Credentials: syftCreds,
|
||||
}
|
||||
syftOpts := defaultPackagesOptions()
|
||||
pc := pkg.ProviderConfig{
|
||||
SyftProviderConfig: pkg.SyftProviderConfig{
|
||||
RegistryOptions: regOpts,
|
||||
SBOMOptions: syftOpts.Catalog.ToSBOMConfig(clio.Identification{}),
|
||||
SBOMOptions: syft.DefaultCreateSBOMConfig(),
|
||||
},
|
||||
SynthesisConfig: pkg.SynthesisConfig{
|
||||
GenerateMissingCPEs: true,
|
||||
|
||||
Reference in New Issue
Block a user