diff --git a/.templates/new-scanner/.gitignore b/.templates/new-scanner/.gitignore new file mode 100644 index 0000000000..2783dbcddf --- /dev/null +++ b/.templates/new-scanner/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +*.tar diff --git a/.templates/new-scanner/.helm-docs.gotmpl b/.templates/new-scanner/.helm-docs.gotmpl new file mode 100644 index 0000000000..d50837d0dc --- /dev/null +++ b/.templates/new-scanner/.helm-docs.gotmpl @@ -0,0 +1,31 @@ +{{- /* +SPDX-FileCopyrightText: 2021 iteratec GmbH + +SPDX-License-Identifier: Apache-2.0 +*/ -}} + +{{- define "extra.docsSection" -}} +--- +title: "new-scanner" +category: "scanner" +type: "Network" +state: "released" +appVersion: "{{ template "chart.appVersion" . }}" +usecase: "NEW SCANNER USECASE" +--- + +ADD A [LOGO]() HERE! + +{{- end }} + +{{- define "extra.dockerDeploymentSection" -}} +## Supported Tags +- `latest` (represents the latest stable release build) +- tagged releases, e.g. `{{ template "chart.appVersion" . }}` +{{- end }} + +{{- define "extra.chartAboutSection" -}} +## What is new-scanner? + +Please write some information about the new scanner. +{{- end }} diff --git a/.templates/new-scanner/.helmignore b/.templates/new-scanner/.helmignore new file mode 100644 index 0000000000..fb9c1d2d6f --- /dev/null +++ b/.templates/new-scanner/.helmignore @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# Node.js files +node_modules/* +package.json +package-lock.json +src/* +config/* +Dockerfile +.dockerignore +*.tar +parser/* +scanner/* +integration-tests/* +examples/* +docs/* +Makefile diff --git a/.templates/new-scanner/Chart.yaml b/.templates/new-scanner/Chart.yaml new file mode 100644 index 0000000000..1fbbaa7dc5 --- /dev/null +++ b/.templates/new-scanner/Chart.yaml @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: v2 +name: new-scanner +description: A Helm chart for the new-scanner security Scanner that integrates with the secureCodeBox. + +type: application +# version - gets automatically set to the secureCodeBox release version when the helm charts gets published +version: v3.1.0-alpha1 +appVersion: "" # Set appVersion +kubeVersion: ">=v1.11.0-0" + +keywords: + - security + - new-scanner + - scanner + - secureCodeBox +home: https://docs.securecodebox.io/docs/scanners/new-scanner +icon: https://docs.securecodebox.io/img/integrationIcons/new-scanner.svg # Upload new icon +sources: + - https://github.com/secureCodeBox/secureCodeBox +maintainers: + - name: iteratec GmbH + email: secureCodeBox@iteratec.com diff --git a/.templates/new-scanner/Makefile b/.templates/new-scanner/Makefile new file mode 100644 index 0000000000..40ae26bf37 --- /dev/null +++ b/.templates/new-scanner/Makefile @@ -0,0 +1,12 @@ +#!/usr/bin/make -f +# +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 +# + +include_guard = set +scanner = new-scanner +custom_scanner = set + +include ../../scanners.mk diff --git a/.templates/new-scanner/README.md b/.templates/new-scanner/README.md new file mode 100644 index 0000000000..6895361b65 --- /dev/null +++ b/.templates/new-scanner/README.md @@ -0,0 +1,49 @@ +--- +title: "new-scanner" +category: "scanner" +type: "Network" +state: "released" +appVersion: "" +usecase: "NEW SCANNER USECASE" +--- + +ADD A [LOGO]() HERE! + + + + +

+ License Apache-2.0 + GitHub release (latest SemVer) + OWASP Incubator Project + Artifact HUB + GitHub Repo stars + Twitter Follower +

+ +## What is new-scanner? + +Please write some information about the new scanner. + +## Deployment +The new-scanner chart can be deployed via helm: + +```bash +# Install HelmChart (use -n to configure another namespace) +helm upgrade --install new-scanner secureCodeBox/new-scanner +``` + diff --git a/.templates/new-scanner/cascading-rules/.gitkeep b/.templates/new-scanner/cascading-rules/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.templates/new-scanner/docs/.gitkeep b/.templates/new-scanner/docs/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.templates/new-scanner/examples/localhost/scan.yaml b/.templates/new-scanner/examples/localhost/scan.yaml new file mode 100644 index 0000000000..50d74e0cf7 --- /dev/null +++ b/.templates/new-scanner/examples/localhost/scan.yaml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "new-scanner-localhost" +spec: + scanType: "new-scanner" + parameters: + # Note: Localhost here isn't "your" localhost, but the scanner container. + # This container doesn't have any ports open... + - localhost diff --git a/.templates/new-scanner/parser/.dockerignore b/.templates/new-scanner/parser/.dockerignore new file mode 100644 index 0000000000..8d754920ee --- /dev/null +++ b/.templates/new-scanner/parser/.dockerignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +node_modules/ diff --git a/.templates/new-scanner/parser/Dockerfile b/.templates/new-scanner/parser/Dockerfile new file mode 100644 index 0000000000..857051eff5 --- /dev/null +++ b/.templates/new-scanner/parser/Dockerfile @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +# No additional dependencies +ARG namespace +ARG baseImageTag +FROM ${namespace:-securecodebox}/parser-sdk-nodejs:${baseImageTag:-latest} +WORKDIR /home/app/parser-wrapper/parser/ +COPY --chown=app:app ./parser.js ./parser.js + +# Additional packages +# ARG namespace +# ARG baseImageTag +# FROM node:14-alpine as build +# RUN mkdir -p /home/app +# WORKDIR /home/app +# COPY package.json package-lock.json ./ +# RUN npm ci --production +# +# FROM ${namespace:-securecodebox}/parser-sdk-nodejs:${baseImageTag:-latest} +# WORKDIR /home/app/parser-wrapper/parser/ +# COPY --from=build --chown=app:app /home/app/node_modules/ ./node_modules/ +# COPY --chown=app:app ./parser.js ./parser.js diff --git a/.templates/new-scanner/parser/__testFiles__/empty.json b/.templates/new-scanner/parser/__testFiles__/empty.json new file mode 100644 index 0000000000..0d4f101c7a --- /dev/null +++ b/.templates/new-scanner/parser/__testFiles__/empty.json @@ -0,0 +1,2 @@ +[ +] diff --git a/.templates/new-scanner/parser/__testFiles__/example.com.json b/.templates/new-scanner/parser/__testFiles__/example.com.json new file mode 100644 index 0000000000..2a7fbcca4f --- /dev/null +++ b/.templates/new-scanner/parser/__testFiles__/example.com.json @@ -0,0 +1,3 @@ +[ +{"target":"http://example.com"} +] diff --git a/.templates/new-scanner/parser/parser.js b/.templates/new-scanner/parser/parser.js new file mode 100644 index 0000000000..038f350123 --- /dev/null +++ b/.templates/new-scanner/parser/parser.js @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2021 iteratec GmbH +// +// SPDX-License-Identifier: Apache-2.0 + +async function parse(fileContent) { + const targets = parseResultFile(fileContent); + return transformToFindings(targets); +} + +function transformToFindings(targets) { + + const targetFindings = []; + + // Code to transform the scanner results to scb findings + + return [...targetFindings]; +} + +/** + * Parses a given new-scanner result file and extracts all targets + * @param {*} fileContent + */ +function parseResultFile(fileContent) { + let targetList = []; + + for(const rawTarget of fileContent) { + // Code to transform raw target findings to usable js format + // If scanner is only able to output xml files, you have to transform them first (look at nmap parser for example) + } + return targetList; +} + +module.exports.parse = parse; diff --git a/.templates/new-scanner/parser/parser.test.js b/.templates/new-scanner/parser/parser.test.js new file mode 100644 index 0000000000..7454c613fa --- /dev/null +++ b/.templates/new-scanner/parser/parser.test.js @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2021 iteratec GmbH +// +// SPDX-License-Identifier: Apache-2.0 + +const fs = require("fs"); +const util = require("util"); + +const { + validateParser, +} = require("@securecodebox/parser-sdk-nodejs/parser-utils"); + +// eslint-disable-next-line security/detect-non-literal-fs-filename +const readFile = util.promisify(fs.readFile); + +const { parse } = require("./parser"); + +test("should properly parse new-scanner json file", async () => { + const fileContent = JSON.parse( + await readFile(__dirname + "/__testFiles__/example.com.json", { + encoding: "utf8", + }) + ); + const findings = await parse(fileContent); + // validate findings + await expect(validateParser(findings)).resolves.toBeUndefined(); + expect(findings).toMatchInlineSnapshot(); +}); + +test("should properly parse empty json file", async () => { + const fileContent = JSON.parse( + await readFile(__dirname + "/__testFiles__/empty.json", { + encoding: "utf8", + }) + ); + const findings = await parse(fileContent); + // validate findings + await expect(validateParser(findings)).resolves.toBeUndefined(); + expect(findings).toMatchInlineSnapshot(); +}); diff --git a/.templates/new-scanner/scanner/Dockerfile b/.templates/new-scanner/scanner/Dockerfile new file mode 100644 index 0000000000..ef0552d604 --- /dev/null +++ b/.templates/new-scanner/scanner/Dockerfile @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +# Write your dockerfile for the scanner new-scanner here +# Alternatively, you can use an existing image from docker-hub diff --git a/.templates/new-scanner/templates/cascading-rules.yaml b/.templates/new-scanner/templates/cascading-rules.yaml new file mode 100644 index 0000000000..97dd683b66 --- /dev/null +++ b/.templates/new-scanner/templates/cascading-rules.yaml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +# We only want to import the default cascading rules if they are enabled +{{ if .Values.cascadingRules.enabled }} +# The CascadingRules are not directly in the /templates directory as their curly bracket syntax clashes with helms templates ... :( +# We import them as raw files to avoid these clashes as escaping them is even more messy +{{ range $path, $_ := .Files.Glob "cascading-rules/*" }} +# Include File +{{ $.Files.Get $path }} +# Separate multiple files +--- +{{ end }} +{{ end }} diff --git a/.templates/new-scanner/templates/new-scanner-parse-definition.yaml b/.templates/new-scanner/templates/new-scanner-parse-definition.yaml new file mode 100644 index 0000000000..b2e8d0a628 --- /dev/null +++ b/.templates/new-scanner/templates/new-scanner-parse-definition.yaml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: ParseDefinition +metadata: + name: "new-scanner-json" +spec: + image: "{{ .Values.parser.image.repository }}:{{ .Values.parser.image.tag | default .Chart.Version }}" + imagePullPolicy: {{ .Values.parser.image.pullPolicy }} + ttlSecondsAfterFinished: {{ .Values.parser.ttlSecondsAfterFinished }} + env: + {{- toYaml .Values.parser.env | nindent 4 }} diff --git a/.templates/new-scanner/templates/new-scanner-scan-type.yaml b/.templates/new-scanner/templates/new-scanner-scan-type.yaml new file mode 100644 index 0000000000..bcc15a1c2c --- /dev/null +++ b/.templates/new-scanner/templates/new-scanner-scan-type.yaml @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: ScanType +metadata: + name: "new-scanner{{ .Values.scanner.nameAppend | default ""}}" +spec: + extractResults: + type: new-scanner-json + location: "/home/securecodebox/new-scanner-results.json" + jobTemplate: + spec: + {{- if .Values.scanner.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.scanner.ttlSecondsAfterFinished }} + {{- end }} + backoffLimit: {{ .Values.scanner.backoffLimit }} + {{- if .Values.scanner.activeDeadlineSeconds }} + activeDeadlineSeconds: {{ .Values.scanner.activeDeadlineSeconds }} + {{- end }} + template: + spec: + restartPolicy: OnFailure + containers: + - name: new-scanner + image: "{{ .Values.scanner.image.repository }}:{{ .Values.scanner.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.scanner.image.pullPolicy }} + command: + - "new-scanner" + - "/home/securecodebox/new-scanner-results.json" # Replace output command + resources: + {{- toYaml .Values.scanner.resources | nindent 16 }} + securityContext: + {{- toYaml .Values.scanner.securityContext | nindent 16 }} + env: + {{- toYaml .Values.scanner.env | nindent 16 }} + volumeMounts: + {{- toYaml .Values.scanner.extraVolumeMounts | nindent 16 }} + {{- if .Values.scanner.extraContainers }} + {{- toYaml .Values.scanner.extraContainers | nindent 12 }} + {{- end }} + volumes: + {{- toYaml .Values.scanner.extraVolumes | nindent 12 }} diff --git a/.templates/new-scanner/values.yaml b/.templates/new-scanner/values.yaml new file mode 100644 index 0000000000..be49b8636f --- /dev/null +++ b/.templates/new-scanner/values.yaml @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +parser: + image: + # parser.image.repository -- Parser image repository + repository: docker.io/securecodebox/scanner-new-scanner + # parser.image.tag -- Parser image tag + # @default -- defaults to the charts version + tag: null + # -- Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + pullPolicy: IfNotPresent + + # parser.ttlSecondsAfterFinished -- seconds after which the kubernetes job for the parser will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ttlSecondsAfterFinished: null + # parser.env -- Optional environment variables mapped into each parseJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) + env: [] + +scanner: + image: + # scanner.image.repository -- Container Image to run the scan + repository: docker.io/securecodebox/scanner-new-scanner + # scanner.image.tag -- defaults to the charts appVersion + tag: null + # -- Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + pullPolicy: IfNotPresent + + # scanner.nameAppend -- append a string to the default scantype name. + nameAppend: null + + # -- seconds after which the kubernetes job for the scanner will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ttlSecondsAfterFinished: null + # -- There are situations where you want to fail a scan Job after some amount of time. To do so, set activeDeadlineSeconds to define an active deadline (in seconds) when considering a scan Job as failed. (see: https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup) + activeDeadlineSeconds: null + # -- There are situations where you want to fail a scan Job after some amount of retries due to a logical error in configuration etc. To do so, set backoffLimit to specify the number of retries before considering a scan Job as failed. (see: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy) + # @default -- 3 + backoffLimit: 3 + + # scanner.resources -- CPU/memory resource requests/limits (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) + resources: {} + # resources: + # requests: + # memory: "256Mi" + # cpu: "250m" + # limits: + # memory: "512Mi" + # cpu: "500m" + + # scanner.env -- Optional environment variables mapped into each scanJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) + env: [] + + # scanner.extraVolumes -- Optional Volumes mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/) + extraVolumes: [] + + # scanner.extraVolumeMounts -- Optional VolumeMounts mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/) + extraVolumeMounts: [] + + # scanner.extraContainers -- Optional additional Containers started with each scanJob (see: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) + extraContainers: [] + + # scanner.securityContext -- Optional securityContext set on scanner container (see: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) + securityContext: + # scanner.securityContext.runAsNonRoot -- Enforces that the scanner image is run as a non root user + runAsNonRoot: true + # scanner.securityContext.readOnlyRootFilesystem -- Prevents write access to the containers file system + readOnlyRootFilesystem: true + # scanner.securityContext.allowPrivilegeEscalation -- Ensure that users privileges cannot be escalated + allowPrivilegeEscalation: false + # scanner.securityContext.privileged -- Ensures that the scanner container is not run in privileged mode + privileged: false + capabilities: + drop: + # scanner.securityContext.capabilities.drop[0] -- This drops all linux privileges from the container. + - all + +cascadingRules: + # cascadingRules.enabled -- Enables or disables the installation of the default cascading rules for this scanner + enabled: true diff --git a/Makefile b/Makefile index c3c04cf671..87ef02800f 100644 --- a/Makefile +++ b/Makefile @@ -147,6 +147,20 @@ demo-apps-docs: .PHONY: docs docs: readme hook-docs scanner-docs operator-docs auto-discovery-docs demo-apps-docs +.PHONY: create-new-scanner +create-new-scanner: ## Creates templates for a new scanner, pass NAME=NEW-SCANNER +ifdef NAME + @mkdir scanners/$(NAME) ; \ + rsync -a ./.templates/new-scanner/ ./scanners/$(NAME) ; \ + echo "Copied template files to new directory ./scanners/$(NAME)"; \ + cd scanners/$(NAME) ; \ + find . -type f -exec sed -i 's/new-scanner/$(NAME)/g' {} + ; \ + mv "./templates/new-scanner-parse-definition.yaml" "templates/$(NAME)-parse-definition.yaml" ; \ + mv "./templates/new-scanner-scan-type.yaml" "templates/$(NAME)-scan-type.yaml" ; +else + @echo "Scanner name not defined, please provide via make create-new-scanner NAME=NEW-SCANNER"; +endif + .PHONY: help: ## Display this help screen. @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \