diff --git a/charts/harbor-scanner-trivy/.helmignore b/charts/harbor-scanner-trivy/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/charts/harbor-scanner-trivy/.helmignore @@ -0,0 +1,22 @@ +# 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/ diff --git a/charts/harbor-scanner-trivy/Chart.yaml b/charts/harbor-scanner-trivy/Chart.yaml new file mode 100644 index 00000000..6fa41c03 --- /dev/null +++ b/charts/harbor-scanner-trivy/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +name: harbor-scanner-trivy +version: 0.1.0 +appVersion: "v0.1.0-rc3" +description: Trivy as a plug-in vulnerability scanner in the Harbor registry +keywords: + - scanner + - harbor + - vulnerability +sources: +- https://github.com/aquasecurity/harbor-scanner-trivy diff --git a/charts/harbor-scanner-trivy/README.md b/charts/harbor-scanner-trivy/README.md new file mode 100644 index 00000000..d9fb0256 --- /dev/null +++ b/charts/harbor-scanner-trivy/README.md @@ -0,0 +1,109 @@ +# Harbor Scanner Trivy + +Trivy as a plug-in vulnerability scanner in the Harbor registry. + +## TL;DR; + +### Without TLS + +``` +$ helm install --name harbor-scanner-trivy \ + --namespace harbor \ + . +``` + +### With TLS + +1. Generate certificate and private key files: + ``` + $ openssl genrsa -out tls.key 2048 + $ openssl req -new -x509 \ + -key tls.key \ + -out tls.crt \ + -days 365 \ + -subj /CN=harbor-scanner-trivy.harbor + ``` +2. Install the `harbor-scanner-trivy` chart: + ``` + $ helm install --name harbor-scanner-trivy \ + --namespace harbor \ + --set service.port=8443 \ + --set scanner.api.tlsEnabled=true \ + --set scanner.api.tlsCertificate="`cat tls.crt`" \ + --set scanner.api.tlsKey="`cat tls.key`" \ + . + ``` + +## Introduction + +This chart bootstraps a scanner adapter deployment on a [Kubernetes](http://kubernetes.io) cluster using the +[Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 2.11+ or Helm 3+ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +``` +$ helm install --name my-release . +``` + +The command deploys scanner adapter on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) +section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list`. + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +``` +$ helm delete --purge my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Parameters + +The following table lists the configurable parameters of the scanner adapter chart and their default values. + +| Parameter | Description | Default | +|-------------------------------|-------------------------------------------------------------------------|----------------| +| `image.registry` | Image registry | `docker.io` | +| `image.repository` | Image name | `aquasec/harbor-scanner-trivy` | +| `image.tag` | Image tag | `{TAG_NAME}` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `replicaCount` | Number of scanner adapter Pods to run | `1` | +| `scanner.logLevel` | The standard logger logs entries with that level or anything above it | `info` | +| `scanner.api.tlsEnabled` | The flag to enable or disable TLS for HTTP | `true` | +| `scanner.api.tlsCertificate` | The absolute path to the x509 certificate file | | +| `scanner.api.tlsKey` | The absolute path to the x509 private key file | | +| `scanner.api.readTimeout` | The maximum duration for reading the entire request, including the body | `15s` | +| `scanner.api.writeTimeout` | The maximum duration before timing out writes of the response | `15s` | +| `scanner.trivy.cacheDir` | Trivy cache directory | `/root/.cache/trivy` | +| `scanner.trivy.reportsDir` | Trivy reports directory | `/root/.cache/reports` | +| `scanner.trivy.debugMode` | The flag to enable or disable Trivy debug mode | `false` | +| `scanner.trivy.vulnType` | Comma-separated list of vulnerability types. Possible values `os` and `library` | `os` | +| `scanner.trivy.severity` | Comma-separated list of vulnerabilities severities to be displayed. | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` | +| `scanner.trivy.ignoreUnfixed` | The flag to display only fixed vulnerabilities. | `false` | +| `scanner.store.redisURL` | Redis server URI for a redis store | `redis://harbor-harbor-redis:6379` | +| `scanner.store.scanJobTTL` | The time to live for persisting scan jobs and associated scan reports | `1h` | +| `scanner.jobQueue.redisURL` | Redis server URI for a jobs queue | `redis://harbor-harbor-redis:6379` | +| `service.type` | Kubernetes service type | `LoadBalancer` | +| `service.port` | Kubernetes service port | `8443` | + + +The above parameters map to the env variables defined in [harbor-scanner-trivy](https://github.com/aquasecurity/harbor-scanner-trivy#configuration). + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +``` +$ helm install --name my-release \ + --namespace my-namespace \ + --set service.port=9090 \ + . +``` diff --git a/charts/harbor-scanner-trivy/templates/NOTES.txt b/charts/harbor-scanner-trivy/templates/NOTES.txt new file mode 100644 index 00000000..d1278f26 --- /dev/null +++ b/charts/harbor-scanner-trivy/templates/NOTES.txt @@ -0,0 +1,2 @@ +You should be able to access your scanner adapter installation within +the cluster at {{ if .Values.scanner.api.tlsEnabled }}https{{ else }}http{{ end }}://{{ include "harbor-scanner-trivy.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.port }} diff --git a/charts/harbor-scanner-trivy/templates/_helpers.tpl b/charts/harbor-scanner-trivy/templates/_helpers.tpl new file mode 100644 index 00000000..4280c0f9 --- /dev/null +++ b/charts/harbor-scanner-trivy/templates/_helpers.tpl @@ -0,0 +1,55 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "harbor-scanner-trivy.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 "harbor-scanner-trivy.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 "harbor-scanner-trivy.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "harbor-scanner-trivy.labels" -}} +app.kubernetes.io/name: {{ include "harbor-scanner-trivy.name" . }} +helm.sh/chart: {{ include "harbor-scanner-trivy.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Return the proper imageRef as used by the container template spec. +*/}} +{{- define "harbor-scanner-trivy.imageRef" -}} +{{- $registryName := .Values.image.registry -}} +{{- $repositoryName := .Values.image.repository -}} +{{- $tag := .Values.image.tag | toString -}} +{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} diff --git a/charts/harbor-scanner-trivy/templates/secret-tls.yaml b/charts/harbor-scanner-trivy/templates/secret-tls.yaml new file mode 100644 index 00000000..4307735f --- /dev/null +++ b/charts/harbor-scanner-trivy/templates/secret-tls.yaml @@ -0,0 +1,12 @@ +{{- if .Values.scanner.api.tlsEnabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "harbor-scanner-trivy.fullname" . }}-tls + labels: +{{ include "harbor-scanner-trivy.labels" . | indent 4 }} +type: kubernetes.io/tls +data: + tls.crt: {{ required "TLS certificate required!" .Values.scanner.api.tlsCertificate | b64enc | quote }} + tls.key: {{ required "TLS key required!" .Values.scanner.api.tlsKey | b64enc | quote }} +{{- end }} diff --git a/charts/harbor-scanner-trivy/templates/service.yaml b/charts/harbor-scanner-trivy/templates/service.yaml new file mode 100644 index 00000000..263cbaac --- /dev/null +++ b/charts/harbor-scanner-trivy/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "harbor-scanner-trivy.fullname" . }} + labels: +{{ include "harbor-scanner-trivy.labels" . | indent 4 }} +spec: + type: {{ .Values.service.type }} + selector: + app.kubernetes.io/name: {{ include "harbor-scanner-trivy.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + ports: + - name: api-server + protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} diff --git a/charts/harbor-scanner-trivy/templates/statefulset.yaml b/charts/harbor-scanner-trivy/templates/statefulset.yaml new file mode 100644 index 00000000..b1288fd7 --- /dev/null +++ b/charts/harbor-scanner-trivy/templates/statefulset.yaml @@ -0,0 +1,109 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "harbor-scanner-trivy.fullname" . }} + labels: +{{ include "harbor-scanner-trivy.labels" . | indent 4 }} +spec: + serviceName: {{ include "harbor-scanner-trivy.fullname" . }} + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "harbor-scanner-trivy.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + spec: + resources: + requests: + storage: {{ .Values.persistence.size }} + accessModes: + - {{ .Values.persistence.accessMode }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "harbor-scanner-trivy.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: main + image: {{ template "harbor-scanner-trivy.imageRef" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: "SCANNER_LOG_LEVEL" + value: {{ .Values.scanner.logLevel | quote }} + - name: "SCANNER_API_SERVER_ADDR" + value: ":{{ .Values.service.port }}" + - name: "SCANNER_API_SERVER_READ_TIMEOUT" + value: {{ .Values.scanner.api.readTimeout | quote }} + - name: "SCANNER_API_SERVER_WRITE_TIMEOUT" + value: {{ .Values.scanner.api.writeTimeout | quote }} + - name: "SCANNER_TRIVY_CACHE_DIR" + value: {{ .Values.scanner.trivy.cacheDir | quote }} + - name: "SCANNER_TRIVY_REPORTS_DIR" + value: {{ .Values.scanner.trivy.reportsDir | quote }} + - name: "SCANNER_TRIVY_DEBUG_MODE" + value: {{ .Values.scanner.trivy.debugMode | quote }} + - name: "SCANNER_TRIVY_VULN_TYPE" + value: {{ .Values.scanner.trivy.vulnType | quote }} + - name: "SCANNER_TRIVY_SEVERITY" + value: {{ .Values.scanner.trivy.severity | quote }} + - name: "SCANNER_TRIVY_IGNORE_UNFIXED" + value: {{ .Values.scanner.trivy.ignoreUnfixed | quote }} + - name: "SCANNER_STORE_REDIS_URL" + value: {{ .Values.scanner.store.redisURL | quote }} + - name: "SCANNER_STORE_REDIS_SCAN_JOB_TTL" + value: {{ .Values.scanner.store.scanJobTTL | quote }} + - name: "SCANNER_JOB_QUEUE_REDIS_URL" + value: {{ .Values.scanner.jobQueue.redisURL | quote }} + {{- if .Values.scanner.api.tlsEnabled }} + - name: "SCANNER_API_SERVER_TLS_CERTIFICATE" + value: "/certs/tls.crt" + - name: "SCANNER_API_SERVER_TLS_KEY" + value: "/certs/tls.key" + {{- end }} + ports: + - name: api-server + containerPort: {{ .Values.service.port }} + livenessProbe: + httpGet: + scheme: {{ if .Values.scanner.api.tlsEnabled }}HTTPS{{ else }}HTTP{{ end }} + path: /probe/healthy + port: api-server + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + readinessProbe: + httpGet: + scheme: {{ if .Values.scanner.api.tlsEnabled }}HTTPS{{ else }}HTTP{{ end }} + path: /probe/ready + port: api-server + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + volumeMounts: + {{- if .Values.persistence.enabled }} + - mountPath: /root/.cache + name: data + {{- end }} + {{- if .Values.scanner.api.tlsEnabled }} + - mountPath: /certs + name: certs + readOnly: true + {{- end }} + {{- if .Values.resources }} + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- end }} + volumes: + {{- if .Values.scanner.api.tlsEnabled }} + - name: certs + secret: + secretName: {{ include "harbor-scanner-trivy.fullname" . }}-tls + {{- end }} diff --git a/charts/harbor-scanner-trivy/values.yaml b/charts/harbor-scanner-trivy/values.yaml new file mode 100644 index 00000000..04b9f4bb --- /dev/null +++ b/charts/harbor-scanner-trivy/values.yaml @@ -0,0 +1,49 @@ +nameOverride: "" +fullnameOverride: "" + +image: + registry: docker.io + repository: aquasec/harbor-scanner-trivy + tag: 0.1.0-rc3 + pullPolicy: IfNotPresent + +replicaCount: 1 + +persistence: + enabled: true + storageClass: "standard" + accessMode: ReadWriteOnce + size: 5Gi + +resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: 1 + memory: 1Gi + +scanner: + logLevel: info + api: + tlsEnabled: false + tlsCertificate: "" + tlsKey: "" + readTimeout: 15s + writeTimeout: 15s + trivy: + cacheDir: "/root/.cache/trivy" + reportsDir: "/root/.cache/reports" + debugMode: false + vulnType: "os" + severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" + ignoreUnfixed: false + store: + redisURL: "redis://harbor-harbor-redis:6379" + scanJobTTL: "1h" + jobQueue: + redisURL: "redis://harbor-harbor-redis:6379" + +service: + type: LoadBalancer + port: 8080