diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 566c975f04..8f6b776a7d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -825,6 +825,23 @@ jobs: # This steps should include Integration tests which are not related to a Specific Scanner + # ---- Gerneral Testing | Findings Validation ---- + + - name: "Parser should fail on invalid Findings" + run: | + helm -n integration-tests install test-scan ./scanners/test-scan/ \ + --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-test-scan" \ + --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-test-scan" \ + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" \ + --set="parser.env[1].name=PRODUCE_INVALID_FINDINGS" \ + --set-string="parser.env[1].value=true" + cd tests/integration/ + npx jest --ci --color generic/findings-validation.test.js + helm -n integration-tests uninstall test-scan + # ---- General Testing | ReadAndWrite Hook ---- - name: "Throws NoScanDefinition Error Integration Tests" @@ -847,7 +864,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-test-scan" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-test-scan" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" + --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color generic/read-write-hook.test.js helm -n integration-tests uninstall test-scan update-category update-severity @@ -860,7 +879,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-test-scan" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-test-scan" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" + --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" helm -n integration-tests install http-webhook ./demo-targets/http-webhook helm -n integration-tests install ro-hook ./hooks/generic-webhook/ \ --set="hook.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/hook-generic-webhook" \ @@ -899,7 +920,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-gitleaks" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-gitleaks" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/gitleaks.test.js @@ -911,7 +934,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-kube-hunter" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-kube-hunter" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/kube-hunter.test.js @@ -926,7 +951,9 @@ jobs: --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-kubeaudit" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="kubeauditScope=cluster" + --set="kubeauditScope=cluster" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/kubeaudit.test.js kubectl delete namespace kubeaudit-tests @@ -940,7 +967,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-ncrack" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-ncrack" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/ncrack.test.js @@ -953,7 +982,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-nikto" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-nikto" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/nikto.test.js @@ -966,7 +997,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-nmap" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-nmap" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/nmap.test.js @@ -978,7 +1011,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-test-scan" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-test-scan" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" + --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" helm -n integration-tests install http-webhook ./demo-targets/http-webhook --wait helm -n integration-tests install notification-hook ./hooks/notification --values tests/integration/hooks/__testFiles__/notification-values.yaml \ @@ -996,7 +1031,9 @@ jobs: kubectl -n integration-tests delete scans --all helm -n integration-tests install ssh-scan ./scanners/ssh-scan/ \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-ssh-scan" + --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-ssh-scan" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/ssh-scan.test.js @@ -1007,7 +1044,9 @@ jobs: kubectl -n integration-tests delete scans --all helm -n integration-tests install sslyze ./scanners/sslyze/ \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-sslyze" + --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-sslyze" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/sslyze.test.js @@ -1018,7 +1057,9 @@ jobs: kubectl -n integration-tests delete scans --all helm -n integration-tests install wpscan ./scanners/wpscan/ \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-wpscan" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/wpscan.test.js @@ -1029,7 +1070,9 @@ jobs: kubectl -n integration-tests delete scans --all helm -n integration-tests install zap ./scanners/zap/ \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ - --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-zap" + --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-zap" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" cd tests/integration/ npx jest --ci --color scanner/zap.test.js @@ -1044,7 +1087,9 @@ jobs: --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-zap" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-zap-advanced" \ - --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" + --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" kubectl apply -f ./scanners/zap-advanced/examples/integration-tests/scantype-configMap.yaml -n integration-tests cd tests/integration/ npx jest --ci --color scanner/zap-advanced.test.js @@ -1065,7 +1110,9 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-nmap" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-nmap" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" # Install ncrack printf "root\nadmin\n" > users.txt printf "THEPASSWORDYOUCREATED\n123456\npassword\n" > passwords.txt @@ -1075,6 +1122,8 @@ jobs: --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-ncrack" \ --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" \ --values - scanner: extraVolumes: @@ -1110,11 +1159,15 @@ jobs: --set="scanner.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/scanner-nmap" \ --set="scanner.image.tag=sha-$(git rev-parse --short HEAD)" \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-nmap" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" # Install sslyze helm -n cascading-tests install sslyze ./scanners/sslyze/ --wait \ --set="parser.image.repository=docker.io/${{ env.DOCKER_NAMESPACE }}/parser-sslyze" \ - --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" + --set="parser.image.tag=sha-$(git rev-parse --short HEAD)" \ + --set="parser.env[0].name=CRASH_ON_FAILED_VALIDATION" \ + --set-string="parser.env[0].value=true" # Actually run the tests cd tests/integration/ npx jest --ci --color scanner/cascade-nmap-sslyze.test.js diff --git a/parser-sdk/nodejs/Dockerfile b/parser-sdk/nodejs/Dockerfile index aa37dec5a3..9ec956b7cb 100644 --- a/parser-sdk/nodejs/Dockerfile +++ b/parser-sdk/nodejs/Dockerfile @@ -14,6 +14,7 @@ WORKDIR /home/app/parser-wrapper/ COPY --from=build --chown=app:app /home/app/node_modules/ ./node_modules/ COPY --chown=app:app ./parser-wrapper.js ./parser-wrapper.js COPY --chown=app:app ./parser-utils.js ./parser-utils.js +COPY --chown=app:app ./findings-schema.json ./findings-schema.json USER 1001 ENV NODE_ENV ${NODE_ENV:-production} ENTRYPOINT ["node", "/home/app/parser-wrapper/parser-wrapper.js"] diff --git a/parser-sdk/nodejs/parser-wrapper.js b/parser-sdk/nodejs/parser-wrapper.js index ea7b8d94b0..14a3a95c9a 100644 --- a/parser-sdk/nodejs/parser-wrapper.js +++ b/parser-sdk/nodejs/parser-wrapper.js @@ -135,13 +135,15 @@ async function main() { console.log("Adding UUIDs and Dates to the findings"); const findingsWithIdsAndDates = addIdsAndDates(findings); - console.log("Validating Findings"); + const crash_on_failed_validation = process.env["CRASH_ON_FAILED_VALIDATION"] === "true" + console.log("Validating Findings. Environment variable CRASH_ON_FAILED_VALIDATION is set to %s", crash_on_failed_validation); try { - await validate(findings); + await validate(findingsWithIdsAndDates); + console.log("The Findings were successfully validated") } catch (error) { - console.error("Findings Validation failed with error:"); + console.error("The Findings Validation failed with error(s):"); console.error(error); - if (process.env["CRASH_ON_FAILED_VALIDATION"] === "true") { + if (crash_on_failed_validation) { process.exit(1); } } diff --git a/scanners/test-scan/parser/parser.js b/scanners/test-scan/parser/parser.js index df84292b1f..4cbce4c981 100644 --- a/scanners/test-scan/parser/parser.js +++ b/scanners/test-scan/parser/parser.js @@ -3,32 +3,16 @@ // SPDX-License-Identifier: Apache-2.0 async function parse() { + if (process.env["PRODUCE_INVALID_FINDINGS"] === "true") + return getInvalidFindings() + else + return getValidFindings() +} + +function getInvalidFindings(){ return [ { - name: "Test read-write-hook service", - description: `Port is using protocol.`, - category: "Open Port", - location: `tcp://rw-hook-test:80`, - osi_layer: "NETWORK", - severity: "INFORMATIONAL", - attributes: { - port: 80, - state: "Open", - ip_address: "host ip address", - mac_address: "hostInfo.mac", - protocol: "openPort.protocol", - hostname: "hostInfo.hostname", - method: "openPort.method", - operating_system: "hostInfo.osNmap", - service: "openPort.service", - serviceProduct: "openPort.serviceProduct", - serviceVersion: "openPort.serviceVersion", - scripts: "openPort.scriptOutputs", - }, - }, - { - name: `Host: hostname`, - category: "Host", + //missing name and category to be a valid finding description: "Found a host", location: "hostname", severity: "INFORMATIONAL", @@ -38,7 +22,46 @@ async function parse() { hostname: "hostname", operating_system: "osNmap", }, + } + ] +} + +function getValidFindings(){ + return [{ + name: "Test read-write-hook service", + description: `Port is using protocol.`, + category: "Open Port", + location: `tcp://rw-hook-test:80`, + osi_layer: "NETWORK", + severity: "INFORMATIONAL", + attributes: { + port: 80, + state: "Open", + ip_address: "host ip address", + mac_address: "hostInfo.mac", + protocol: "openPort.protocol", + hostname: "hostInfo.hostname", + method: "openPort.method", + operating_system: "hostInfo.osNmap", + service: "openPort.service", + serviceProduct: "openPort.serviceProduct", + serviceVersion: "openPort.serviceVersion", + scripts: "openPort.scriptOutputs", + }, + }, + { + name: `Host: hostname`, + category: "Host", + description: "Found a host", + location: "hostname", + severity: "INFORMATIONAL", + osi_layer: "NETWORK", + attributes: { + ip_address: "ip address", + hostname: "hostname", + operating_system: "osNmap", }, + }, ]; } diff --git a/tests/integration/generic/findings-validation.test.js b/tests/integration/generic/findings-validation.test.js new file mode 100644 index 0000000000..3382493928 --- /dev/null +++ b/tests/integration/generic/findings-validation.test.js @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2021 iteratec GmbH +// +// SPDX-License-Identifier: Apache-2.0 + +const { scan } = require("../helpers"); + +jest.retryTimes(3); + +test( + "Parser must fail on invalid findings", + async () => { + await expect( + scan("invalid-findings-test-scan", "test-scan", [], 90) + ).rejects.toThrow( + `Scan failed with description "Failed to run the Parser. This is likely a Bug, we would like to know about. Please open up a Issue on GitHub."` + ); + }, + 3 * 60 * 1000 +);