diff --git a/charts/scan-controller/.helmignore b/charts/scan-controller/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/scan-controller/.helmignore @@ -0,0 +1,23 @@ +# 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 +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/scan-controller/Chart.yaml b/charts/scan-controller/Chart.yaml new file mode 100644 index 0000000..aca040b --- /dev/null +++ b/charts/scan-controller/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: scan-controller +description: A Helm chart for Kubernetes + +# 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: 0.0.0-alpha.1 + +# 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: "2023.9-14019" diff --git a/charts/scan-controller/templates/_helpers.tpl b/charts/scan-controller/templates/_helpers.tpl new file mode 100644 index 0000000..e4ee412 --- /dev/null +++ b/charts/scan-controller/templates/_helpers.tpl @@ -0,0 +1,64 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "scan-controller.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 "scan-controller.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 "scan-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "scan-controller.labels" -}} +helm.sh/chart: {{ include "scan-controller.chart" . }} +{{ include "scan-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "scan-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "scan-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Renders a value that contains template. +Usage: +{{ include "scan-controller.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "scan-controller.tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/scan-controller/templates/controller-env-secret.yaml b/charts/scan-controller/templates/controller-env-secret.yaml new file mode 100644 index 0000000..6cc2471 --- /dev/null +++ b/charts/scan-controller/templates/controller-env-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "scan-controller.fullname" . }}-env +type: Opaque +data: + BSEE_WEB_SERVER_URL: {{ .Values.configuration.apiKey | b64enc }} + BSEE_HOSTED_SCANNING_MACHINE_API_KEY: {{ .Values.configuration.apiKey | b64enc }} + BSEE_HOSTED_SCAN_JOB_TEMPLATE: {{ include "scan-controller.tplvalues.render" ( dict "value" .Values.scanner.jobTemplate "context" $) | b64enc }} + BSEE_MAX_SCAN_CONCURRENCY: {{ .Values.configuration.maxConcurrency | quote | b64enc }} \ No newline at end of file diff --git a/charts/scan-controller/templates/deployment.yaml b/charts/scan-controller/templates/deployment.yaml new file mode 100644 index 0000000..a6d1b13 --- /dev/null +++ b/charts/scan-controller/templates/deployment.yaml @@ -0,0 +1,87 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "scan-controller.fullname" . }} + labels: + {{- include "scan-controller.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "scan-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "scan-controller.selectorLabels" . | nindent 8 }} + annotations: + checksum/controller-env-secret: {{ $controllerEnvSec := include (print $.Template.BasePath "/controller-env-secret.yaml") . | fromYaml }}{{ $controllerEnvSec.data | toYaml | sha256sum }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccount: {{ include "scan-controller.fullname" . }} + serviceAccountName: {{ include "scan-controller.fullname" . }} + securityContext: + fsGroup: 100000 + fsGroupChangePolicy: OnRootMismatch + containers: + - name: scan-controller + securityContext: + runAsUser: 100000 + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + privileged: false + capabilities: + drop: + - ALL + image: "{{ default .Values.global.image.registry .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }}" + envFrom: + - secretRef: + name: {{ include "scan-controller.fullname" . }}-env + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + ports: + - name: management + containerPort: 8078 + protocol: TCP + startupProbe: + httpGet: + port: management + path: /health/readiness + failureThreshold: 60 + periodSeconds: 5 + timeoutSeconds: 2 + livenessProbe: + httpGet: + port: management + path: /health/liveness + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 2 + successThreshold: 1 + readinessProbe: + httpGet: + port: management + path: /health/readiness + failureThreshold: 1 + periodSeconds: 10 + timeoutSeconds: 2 + successThreshold: 1 + resources: + limits: + memory: 128Mi + requests: + cpu: 200m + memory: 128Mi + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/scan-controller/templates/extra-deploy.yaml b/charts/scan-controller/templates/extra-deploy.yaml new file mode 100644 index 0000000..9e4221f --- /dev/null +++ b/charts/scan-controller/templates/extra-deploy.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "scan-controller.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} \ No newline at end of file diff --git a/charts/scan-controller/templates/rbac.yaml b/charts/scan-controller/templates/rbac.yaml new file mode 100644 index 0000000..8a020a0 --- /dev/null +++ b/charts/scan-controller/templates/rbac.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{include "scan-controller.fullname" .}} +rules: + - apiGroups: [""] + resources: ["pods", "pods/log"] + verbs: ["get", "watch", "list"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{include "scan-controller.fullname" .}} +subjects: + - kind: ServiceAccount + name: {{include "scan-controller.fullname" .}} + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: {{include "scan-controller.fullname" .}} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/scan-controller/templates/scanner-env-secret.yaml b/charts/scan-controller/templates/scanner-env-secret.yaml new file mode 100644 index 0000000..50f110a --- /dev/null +++ b/charts/scan-controller/templates/scanner-env-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "scan-controller.fullname" . }}-scanner-env +type: Opaque +data: + BSEE_WEB_SERVER_URL: {{ .Values.configuration.apiKey | b64enc }} + BSEE_HOSTED_SCANNING_MACHINE_API_KEY: {{ .Values.configuration.apiKey | b64enc }} \ No newline at end of file diff --git a/charts/scan-controller/templates/serviceaccount.yaml b/charts/scan-controller/templates/serviceaccount.yaml new file mode 100644 index 0000000..c389430 --- /dev/null +++ b/charts/scan-controller/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "scan-controller.fullname" . }} + labels: + {{- include "scan-controller.labels" . | nindent 4 }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "scan-controller.fullname" . }}-scanner + labels: + {{- include "scan-controller.labels" . | nindent 4 }} +automountServiceAccountToken: false diff --git a/charts/scan-controller/values.yaml b/charts/scan-controller/values.yaml new file mode 100644 index 0000000..6cdddce --- /dev/null +++ b/charts/scan-controller/values.yaml @@ -0,0 +1,101 @@ +# Default values for scan-controller. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +global: + image: + registry: public.ecr.aws + +configuration: + apiKey: "" + enterpriseUrl: "" + maxConcurrency: "20" + +controller: + image: + registry: "" + repository: portswigger/scan-controller + pullPolicy: Always + tag: "" + nodeSelector: {} + tolerations: [] + affinity: {} + +scanner: + image: + registry: "" + repository: portswigger/portswigger-hosted-scan + tag: "" + nodeSelector: {} + tolerations: [] + affinity: {} + + jobTemplate: | + apiVersion: batch/v1 + kind: Job + metadata: + name: scan + labels: + app.kubernetes.io/component: scanner + app.kubernetes.io/part-of: bsee + spec: + backoffLimit: 0 + ttlSecondsAfterFinished: 60 + template: + metadata: + labels: + app.kubernetes.io/component: scanner + app.kubernetes.io/part-of: bsee + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "false" + karpenter.sh/do-not-evict: "true" + spec: + serviceAccount: {{ include "scan-controller.fullname" . }}-scanner + serviceAccountName: {{ include "scan-controller.fullname" . }}-scanner + automountServiceAccountToken: false + containers: + - name: scan-container + env: + - name: JAVA_OPTS + value: -Xms512m -Xmx512m + - name: BURP_JAVA_OPTS + value: -XX:InitialRAMPercentage=75 -XX:MaxRAMPercentage=75 + envFrom: + - secretRef: + name: {{ include "scan-controller.fullname" . }}-scanner-env + image: "{{ default .Values.global.image.registry .Values.scanner.image.registry }}/{{ .Values.scanner.image.repository }}:{{ .Values.scanner.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + resources: + limits: + memory: 8Gi + requests: + cpu: 2 + memory: 8Gi + securityContext: + runAsUser: 100000 + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + privileged: false + capabilities: + drop: + - ALL + restartPolicy: Never + terminationGracePeriodSeconds: 30 + {{- with .Values.scanner.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scanner.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scanner.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + +extraDeploy: []