Skip to content

Support for Custom S3 Services with a Custom Root CA #297

@rfelber

Description

@rfelber

As secureCodeBox operations user i would like to integrate and configure custom S3 based persistence services instead of public available services like AWS Buckets, GCP Storage or DO.

Is your feature request related to a problem? Please describe.

By now it is already possible to configure a custom S3 Backend as documented here:

But one feature is missing in the case of custom/internal S3 Services. It must be possible to add and configure custom root CA's for all secureCodeBox Components (Operator, Scanner, Hooks,...) to ensure a valid TLS based connection, if the custom S3 Service uses non public avaliable certificates.

Describe the solution you'd like

Implement a configuration Option for all HelmCharts to add a custom Root CA based on a given configMap containing the CA Certificate.

SCB Components involved here:

Implementation Hints:

Regarding the parseDefinition and ScanCompletionHook CRDs we have already implemented the possibility for ENV, Mount and FileMount configurations in the corresponding SCB CRD and controller. Additional informations are documented in issue #212.

What is missing here is to add this configuration option to all Scanner and Hooks HelmChart by default. The following hints will guide you through some necessary steps:

Hook Hints

Existing CRD ScanCompletionHook Definition

type ScanCompletionHookSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Defines weather the hook should be able to change the findings or is run in a read only mode.
Type HookType `json:"type"`
// Image is the container image for the hooks kubernetes job
Image string `json:"image,omitempty"`
// ImagePullSecrets used to access private hooks images
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
// 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
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
// Env allows to specify environment vars for the hooks container.
Env []corev1.EnvVar `json:"env,omitempty"`
// Volumes allows to specify volumes for the hooks container.
Volumes []corev1.Volume `json:"volumes,omitempty"`
// VolumeMounts allows to specify volume mounts for the hooks container.
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
// ServiceAccountName Name of the serviceAccount Name used. Should only be used if your hook needs specifc RBAC Access. Otherwise the hook is run using a "scan-completion-hook" service account. The service account should have at least "get" rights on scans.execution.securecodebox.io, and "get" & "patch" scans.execution.securecodebox.io/status
ServiceAccountName *string `json:"serviceAccountName,omitempty"`
// TTLSecondsAfterFinished configures the ttlSecondsAfterFinished field for the created hook job
// +nullable
TTLSecondsAfterFinished *int32 `json:"ttlSecondsAfterFinished,omitempty"`
}

Example Hook HelmChart Value Configuration:

The following code shows an example how the missing configuration option should look like (for all existing hook charts). Based on https://github.com/secureCodeBox/secureCodeBox/blob/main/hooks/declarative-subsequent-scans/values.yaml

# example Hook configuration values
hookJob:
  # hookJob.ttlSecondsAfterFinished -- seconds after which the kubernetes job for the hook will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/
  ttlSecondsAfterFinished: null
  # hookJob.env -- Optional environment variables mapped into each scanJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
  env: []
  # hookJob.envFrom -- Optional mount environment variables from configMaps or secrets (see: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#configure-all-key-value-pairs-in-a-secret-as-container-environment-variables)
  envFrom: []
  # hookJob.extraVolumes -- Optional Volumes mapped into each hookJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumes:
    - name: ca-workdir
      emptyDir: {}
  # hookJob.extraVolumeMounts -- Optional VolumeMounts mapped into each hookJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumeMounts:
    - mountPath: /etc/ssl/
      name: ca-workdir

Example Hook HelmChart Template implementation:

based on: https://github.com/secureCodeBox/secureCodeBox/blob/main/hooks/declarative-subsequent-scans/templates/declerative-subsequent-scans-hook.yaml

apiVersion: "execution.securecodebox.io/v1"
kind: ScanCompletionHook
metadata:
  name: {{ include "declarative-subsequent-scans.fullname" . }}
spec:
  type: ReadOnly
  image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.Version }}"
  ttlSecondsAfterFinished: {{ .Values.hookJob.ttlSecondsAfterFinished }}
  serviceAccountName: declarative-combined-scans
  env:  {{ include " .Values.hookJob.env" . }}
  volumes:  {{ include " .Values.hookJob.extraVolumes" . }}
  volumeMounts:  {{ include " .Values.hookJob.extraVolumeMounts" . }}

Parser Hints

Existing CRD parseType Definition

// ParseDefinitionSpec defines the desired state of ParseDefinition
type ParseDefinitionSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Image is the reference to the parser container image which ca transform the raw scan report into findings
Image string `json:"image,omitempty"`
// ImagePullSecrets used to access private parser images
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
// 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
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
// TTLSecondsAfterFinished configures the ttlSecondsAfterFinished field for the created parse job
// +nullable
TTLSecondsAfterFinished *int32 `json:"ttlSecondsAfterFinished,omitempty"`
// Env allows to specify environment vars for the parser container.
Env []corev1.EnvVar `json:"env,omitempty"`
// Volumes allows to specify volumes for the parser container.
Volumes []corev1.Volume `json:"volumes,omitempty"`
// VolumeMounts allows to specify volume mounts for the parser container.
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
}

Example Scanner HelmChart Value Configuration:

The following code shows an example how the missing configuration option should look like (for all existing scanner charts). Based on: https://github.com/secureCodeBox/secureCodeBox/blob/main/scanners/amass/values.yaml

# example Scanner (Parser) configuration values
parseJob:
  # parseJob.ttlSecondsAfterFinished -- seconds after which the kubernetes job for the hook will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/
  ttlSecondsAfterFinished: null
  # parseJob.env -- Optional environment variables mapped into each scanJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
  env: []
  # parseJob.envFrom -- Optional mount environment variables from configMaps or secrets (see: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#configure-all-key-value-pairs-in-a-secret-as-container-environment-variables)
  envFrom: []
  # parseJob.extraVolumes -- Optional Volumes mapped into each hookJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumes:
    - name: ca-workdir
      emptyDir: {}
  # parseJob.extraVolumeMounts -- Optional VolumeMounts mapped into each hookJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumeMounts:
    - mountPath: /etc/ssl/
      name: ca-workdir

Example Parser HelmChart Template implementation:

based on https://github.com/secureCodeBox/secureCodeBox/blob/main/scanners/amass/templates/amass-parse-definition.yaml:

apiVersion: "execution.securecodebox.io/v1"
kind: ParseDefinition
metadata:
  name: "amass-jsonl"
spec:
  handlesResultsType: amass-jsonl
  image: "{{ .Values.parserImage.repository }}:{{ .Values.parserImage.tag | default .Chart.Version }}"
  ttlSecondsAfterFinished: {{ .Values.parseJob.ttlSecondsAfterFinished }}
  env:  {{ include " .Values.parseJob.env" . }}
  volumes:  {{ include " .Values.parseJob.extraVolumes" . }}
  volumeMounts:  {{ include " .Values.parseJob.extraVolumeMounts" . }}

Operator and Lurcher Hints

The following code shows an example how the missing configuration option should look like for the operator and lurcher:

# example Lurcher configuration values
lurcher:
  # lurcher.env -- Optional environment variables mapped into the lurcher (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
  env: []
  # lurcher.envFrom -- Optional mount environment variables from configMaps or secrets (see: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#configure-all-key-value-pairs-in-a-secret-as-container-environment-variables)
  envFrom: []
  # lurcher.extraVolumes -- Optional Volumes mapped into the lurcher (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumes:
    - name: ca-workdir
      emptyDir: {}
  # lurcher.extraVolumeMounts -- Optional VolumeMounts mapped into the lurcher (see: https://kubernetes.io/docs/concepts/storage/volumes/)
  extraVolumeMounts:
    - mountPath: /etc/ssl/
      name: ca-workdir

# example Operator configuration values
# env -- Optional environment variables mapped into the operator (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
env: []
# envFrom -- Optional mount environment variables from configMaps or secrets (see: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#configure-all-key-value-pairs-in-a-secret-as-container-environment-variables)
envFrom: []
# volumes -- Optional Volumes mapped into the operator (see: https://kubernetes.io/docs/concepts/storage/volumes/)
volumes:
  - name: ca-workdir
    emptyDir: {}
# volumeMounts -- Optional VolumeMounts mapped into the operator (see: https://kubernetes.io/docs/concepts/storage/volumes/)
volumeMounts:
  - mountPath: /etc/ssl/
    name: ca-workdir

Describe alternatives you've considered

none

Additional context

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestpersistenceImplement or update a persistence store

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions