From 3ee7680c8e78b8f3746a75d5ac94b27bf7bf4247 Mon Sep 17 00:00:00 2001 From: Kuruyia <8174691+Kuruyia@users.noreply.github.com> Date: Tue, 21 Nov 2023 10:27:38 +0100 Subject: [PATCH 01/11] feat: expose the HTTP port in the service --- README.md | 11 ++++++--- templates/deployment.yaml | 6 ++--- templates/service.yaml | 10 +++++--- tests/deployment_http_port_test.yaml | 20 +++++++++------- tests/service_http_port_test.yaml | 36 ++++++++++++++++++++++++++++ tests/values-test.yaml | 23 +++++++++++++----- values.yaml | 23 +++++++++++++----- 7 files changed, 99 insertions(+), 30 deletions(-) create mode 100644 tests/service_http_port_test.yaml diff --git a/README.md b/README.md index d4b53e3..6266765 100644 --- a/README.md +++ b/README.md @@ -214,9 +214,14 @@ chart and deletes the release. | redisDependencyEnabled | bool | `true` | Install redis as a depending chart | | replicaCount | int | `2` | If autoscaling is disabled this will define the number of pods to run | | service.annotations | object | `{}` | Annotations to add to the service | -| service.name | string | `"https"` | Configure passbolt service port name | -| service.port | int | `443` | Configure passbolt service port | -| service.targetPort | int | `443` | Configure passbolt service targetPort | +| service.ports | object | `{"http":{"name":"http","port":80,"targetPort":80},"https":{"name":"https","port":443,"targetPort":443}}` | Configure the service ports | +| service.ports.http.name | string | `"http"` | Configure passbolt HTTP service port name | +| service.ports.http.port | int | `80` | Configure passbolt HTTP service port | +| service.ports.http.targetPort | int | `80` | Configure passbolt HTTP service targetPort | +| service.ports.https | object | `{"name":"https","port":443,"targetPort":443}` | Configure the HTTPS port | +| service.ports.https.name | string | `"https"` | Configure passbolt HTTPS service port name | +| service.ports.https.port | int | `443` | Configure passbolt HTTPS service port | +| service.ports.https.targetPort | int | `443` | Configure passbolt HTTPS service targetPort | | service.type | string | `"ClusterIP"` | Configure passbolt service type | | serviceAccount.annotations | object | `{}` | Annotations to add to the service account | | serviceAccount.create | bool | `true` | Specifies whether a service account should be created | diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 841b85a..3719134 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -46,7 +46,7 @@ spec: args: - "-c" - | - set -e + set -e client="{{- include "passbolt.databaseClient" . }}" {{- if or ( eq .Values.app.database.kind "mysql" ) ( eq .Values.app.database.kind "mariadb" ) }} cat <<-EOF > /tmp/defaultsfile.cnf @@ -104,10 +104,10 @@ spec: imagePullPolicy: {{ .Values.app.image.pullPolicy }} ports: - name: https - containerPort: {{ .Values.service.targetPort }} + containerPort: {{ .Values.service.ports.https.targetPort }} protocol: TCP - name: http - containerPort: 80 + containerPort: {{ .Values.service.ports.http.targetPort }} protocol: TCP livenessProbe: {{- toYaml .Values.livenessProbe | nindent 12 }} diff --git a/templates/service.yaml b/templates/service.yaml index 250fbd9..e7f938a 100644 --- a/templates/service.yaml +++ b/templates/service.yaml @@ -19,9 +19,13 @@ metadata: spec: type: {{ .Values.service.type }} ports: - - port: {{ .Values.service.port | default 443 }} - targetPort: {{ .Values.service.targetPort | default 443 }} + - port: {{ .Values.service.ports.https.port | default 443 }} + targetPort: {{ .Values.service.ports.https.targetPort | default 443 }} protocol: TCP - name: {{ .Values.service.name | default "https" }} + name: {{ .Values.service.ports.https.name | default "https" }} + - port: {{ .Values.service.ports.http.port | default 80 }} + targetPort: {{ .Values.service.ports.http.targetPort | default 80 }} + protocol: TCP + name: {{ .Values.service.ports.http.name | default "http" }} selector: {{- include "passbolt-library.selectorLabels" . | nindent 4 }} diff --git a/tests/deployment_http_port_test.yaml b/tests/deployment_http_port_test.yaml index 3b9a01e..b3e8670 100644 --- a/tests/deployment_http_port_test.yaml +++ b/tests/deployment_http_port_test.yaml @@ -5,22 +5,24 @@ release: values: - values-test.yaml tests: - - it: should match port with the one in values + - it: should match ports with the ones in values templates: - deployment.yaml set: - service.targetPort: 5000 - redis.auth.enabled: true - redis.replica.replicaCount: 2 - autoscaling.enabled: false - app.cache.redis.sentinelProxy.enabled: false - app.cache.redis.sentinelProxy.image.repository: haproxy - app.cache.redis.sentinelProxy.image.tag: latest + service.ports.https.targetPort: 5443 + service.ports.http.targetPort: 5080 asserts: - contains: path: spec.template.spec.containers[0].ports content: name: https - containerPort: 5000 + containerPort: 5443 + count: 1 + any: true + - contains: + path: spec.template.spec.containers[0].ports + content: + name: http + containerPort: 5080 count: 1 any: true diff --git a/tests/service_http_port_test.yaml b/tests/service_http_port_test.yaml new file mode 100644 index 0000000..2ff6a4b --- /dev/null +++ b/tests/service_http_port_test.yaml @@ -0,0 +1,36 @@ +--- +suite: service ports +release: + name: test +values: + - values-test.yaml +tests: + - it: should match ports with the ones in values + templates: + - service.yaml + set: + service.ports.https.port: 5443 + service.ports.https.targetPort: 5443 + service.ports.https.name: myhttps + service.ports.http.port: 5080 + service.ports.http.targetPort: 5080 + service.ports.http.name: myhttp + asserts: + - contains: + path: spec.ports + content: + port: 5443 + targetPort: 5443 + protocol: TCP + name: myhttps + count: 1 + any: true + - contains: + path: spec.ports + content: + port: 5080 + targetPort: 5080 + protocol: TCP + name: myhttp + count: 1 + any: true diff --git a/tests/values-test.yaml b/tests/values-test.yaml index 11d0569..e2a3b93 100644 --- a/tests/values-test.yaml +++ b/tests/values-test.yaml @@ -243,14 +243,25 @@ podSecurityContext: {} service: # -- Configure passbolt service type type: ClusterIP - # -- Configure passbolt service port - port: 443 - # -- Configure passbolt service targetPort - targetPort: 443 - # -- Configure passbolt service port name - name: https # -- Annotations to add to the service annotations: {} + # -- Configure the service ports + ports: + # -- Configure the HTTPS port + https: + # -- Configure passbolt HTTPS service port + port: 443 + # -- Configure passbolt HTTPS service targetPort + targetPort: 443 + # -- Configure passbolt HTTPS service port name + name: https + http: + # -- Configure passbolt HTTP service port + port: 80 + # -- Configure passbolt HTTP service targetPort + targetPort: 80 + # -- Configure passbolt HTTP service port name + name: http ingress: # -- Enable passbolt ingress diff --git a/values.yaml b/values.yaml index 2bbb085..3d053b5 100644 --- a/values.yaml +++ b/values.yaml @@ -324,14 +324,25 @@ podSecurityContext: service: # -- Configure passbolt service type type: ClusterIP - # -- Configure passbolt service port - port: 443 - # -- Configure passbolt service targetPort - targetPort: 443 - # -- Configure passbolt service port name - name: https # -- Annotations to add to the service annotations: {} + # -- Configure the service ports + ports: + # -- Configure the HTTPS port + https: + # -- Configure passbolt HTTPS service port + port: 443 + # -- Configure passbolt HTTPS service targetPort + targetPort: 443 + # -- Configure passbolt HTTPS service port name + name: https + http: + # -- Configure passbolt HTTP service port + port: 80 + # -- Configure passbolt HTTP service targetPort + targetPort: 80 + # -- Configure passbolt HTTP service port name + name: http tls: # -- Generates a secret with a self-signed cerfificate that is injected on ingress and passbolt container From 3214755542d88a49dcd586af4450d6df64b99a27 Mon Sep 17 00:00:00 2001 From: Kuruyia <8174691+Kuruyia@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:43:59 +0100 Subject: [PATCH 02/11] feat: use list instead of string for extra volumes and extra volume mounts --- README.md | 4 ++-- templates/deployment.yaml | 6 +++--- tests/values-test.yaml | 4 ++-- values.yaml | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d4b53e3..f9e3069 100644 --- a/README.md +++ b/README.md @@ -124,8 +124,8 @@ chart and deletes the release. | autoscaling.minReplicas | int | `1` | Configure autoscaling minimum replicas | | autoscaling.targetCPUUtilizationPercentage | int | `80` | Configure autoscaling target CPU uptilization percentage | | cronJobEmail | object | `{"enabled":true,"extraPodLabels":{},"schedule":"* * * * *"}` | Enable email cron | -| extraVolumeMounts | string | `""` | Add additional volume mounts, e.g. for overwriting config files | -| extraVolumes | string | `""` | Add additional volumes, e.g. for overwriting config files | +| extraVolumeMounts | list | `[]` | Add additional volume mounts, e.g. for overwriting config files | +| extraVolumes | list | `[]` | Add additional volumes, e.g. for overwriting config files | | fullnameOverride | string | `""` | Value to override the whole fullName | | global.imagePullSecrets | list | `[]` | | | global.imageRegistry | string | `""` | | diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 841b85a..17843d3 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -46,7 +46,7 @@ spec: args: - "-c" - | - set -e + set -e client="{{- include "passbolt.databaseClient" . }}" {{- if or ( eq .Values.app.database.kind "mysql" ) ( eq .Values.app.database.kind "mariadb" ) }} cat <<-EOF > /tmp/defaultsfile.cnf @@ -152,7 +152,7 @@ spec: readOnly: true {{- end }} {{- with .Values.extraVolumeMounts }} - {{- tpl . $ | nindent 12 }} + {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.app.resources | nindent 12 }} @@ -211,5 +211,5 @@ spec: secretName: {{ $Name }}-sec-redis-proxy {{- end -}} {{- with .Values.extraVolumes }} - {{- tpl . $ | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} diff --git a/tests/values-test.yaml b/tests/values-test.yaml index 11d0569..8c2557e 100644 --- a/tests/values-test.yaml +++ b/tests/values-test.yaml @@ -280,7 +280,7 @@ tolerations: [] affinity: {} # -- Add additional volumes, e.g. for overwriting config files -extraVolumes: "" +extraVolumes: [] # -- Add additional volume mounts, e.g. for overwriting config files -extraVolumeMounts: "" +extraVolumeMounts: [] diff --git a/values.yaml b/values.yaml index 2bbb085..478a904 100644 --- a/values.yaml +++ b/values.yaml @@ -369,7 +369,7 @@ tolerations: [] affinity: {} # -- Add additional volumes, e.g. for overwriting config files -extraVolumes: "" +extraVolumes: [] # -- Add additional volume mounts, e.g. for overwriting config files -extraVolumeMounts: "" +extraVolumeMounts: [] From 832ffb02486a826f0ef2ba1d0530cd6c883730cf Mon Sep 17 00:00:00 2001 From: Cyril Jouve Date: Fri, 15 Dec 2023 16:26:03 +0100 Subject: [PATCH 03/11] use static names for pod internal references (container, volume) --- templates/cronjob-proc-email.yaml | 21 ++++++++---------- templates/deployment.yaml | 28 ++++++++++++------------ templates/job-create-gpg.yaml | 6 ++--- templates/job-create-jwt.yaml | 6 ++--- tests/cronjobs_redis_sidecar_test.yaml | 6 ++--- tests/deployment_gpg_secret_test.yaml | 8 +++---- tests/deployment_redis_sidecar_test.yaml | 4 ++-- 7 files changed, 38 insertions(+), 41 deletions(-) diff --git a/templates/cronjob-proc-email.yaml b/templates/cronjob-proc-email.yaml index f027117..0697913 100644 --- a/templates/cronjob-proc-email.yaml +++ b/templates/cronjob-proc-email.yaml @@ -30,7 +30,7 @@ spec: runAsUser: 33 fsGroup: 33 containers: - - name: {{ $fullName }} + - name: proc-email image: {{ include "passbolt.image" (dict "imageRoot" .Values.app.image "global" .Values.global) }} imagePullPolicy: {{ .Values.app.image.pullPolicy }} command: @@ -57,13 +57,13 @@ spec: {{- toYaml . | nindent 16 }} {{- end }} volumeMounts: - - name: {{ $Name }}-vol-success + - name: vol-success mountPath: /tmp/pod - - name: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} + - name: sec-gpg mountPath: {{ .Values.gpgPath }} readOnly: true {{- if .Values.app.cache.redis.sentinelProxy.enabled }} - - name: {{ $fullName }}-redisproxy + - name: redisproxy image: {{ include "passbolt.image" (dict "imageRoot" .Values.app.cache.redis.sentinelProxy.image "global" .Values.global) }} imagePullPolicy: {{ .Values.app.cache.redis.sentinelProxy.pullPolicy }} command: @@ -75,26 +75,23 @@ spec: REDIS_PROXY_PID=$? while true; do if [ -f "/tmp/pod/success" ]; then kill $REDIS_PROXY_PID; sleep 5; exit 0; fi; done volumeMounts: - - name: {{ $Name }}-vol-success + - name: vol-success mountPath: /tmp/pod - mountPath: "/usr/local/etc/haproxy/haproxy.cfg" subPath: haproxy.cfg - name: {{ $fullName }}-sec-redis-proxy + name: sec-redis-proxy readOnly: true resources: {{- toYaml .Values.redisProxyResources | nindent 16 }} {{- end }} volumes: - - name: {{ $Name }}-vol-success + - name: vol-success emptyDir: {} - - name: {{ $fullName }}-sec-gcs - secret: - secretName: {{ $Name }}-sec-gcs - - name: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} + - name: sec-gpg secret: secretName: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} {{- if .Values.app.cache.redis.sentinelProxy.enabled }} - - name: {{ $fullName }}-sec-redis-proxy + - name: sec-redis-proxy secret: secretName: {{ $Name }}-sec-redis-proxy {{- end -}} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 8d74714..1755efc 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -95,7 +95,7 @@ spec: {{- end }} {{- end }} containers: - - name: {{ $fullName }} + - name: passbolt command: - "/bin/bash" args: @@ -135,23 +135,23 @@ spec: {{- if .Values.app.cache.redis.enabled }} - mountPath: "/etc/passbolt/app.php" subPath: app.php - name: {{ $Name }}-cm-app-php + name: cm-app-php readOnly: true {{- end }} - mountPath: /etc/ssl/certs/passbolt - name: {{ $fullName }}-sec-tls + name: sec-tls readOnly: true - - name: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} + - name: sec-gpg mountPath: {{ .Values.gpgPath }} readOnly: true {{- if .Values.subscriptionKey }} - - name: {{ $fullName }}-sec-subscription + - name: sec-subscription mountPath: {{ quote .Values.subscription_keyPath }} subPath: subscription_key.txt readOnly: true {{- end }} {{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} - - name: {{ $fullName }}-sec-jwt + - name: sec-jwt mountPath: {{ quote .Values.jwtPath }} readOnly: true {{- end }} @@ -161,13 +161,13 @@ spec: resources: {{- toYaml .Values.app.resources | nindent 12 }} {{- if .Values.app.cache.redis.sentinelProxy.enabled }} - - name: {{ $fullName }}-redisproxy + - name: redisproxy image: {{ include "passbolt.image" (dict "imageRoot" .Values.app.cache.redis.sentinelProxy.image "global" .Values.global) }} imagePullPolicy: {{ .Values.app.cache.redis.sentinelProxy.pullPolicy }} volumeMounts: - mountPath: "/usr/local/etc/haproxy/haproxy.cfg" subPath: haproxy.cfg - name: {{ $fullName }}-sec-redis-proxy + name: sec-redis-proxy readOnly: true resources: {{- toYaml .Values.app.cache.redis.sentinelProxy.resources | nindent 12 }} @@ -185,19 +185,19 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} volumes: - - name: {{ $fullName }}-sec-tls + - name: sec-tls secret: secretName: {{ include "passbolt.container.tls.secretName" (dict "name" $Name "ingressTLS" .Values.ingress.tls "globalTLS" $.Values.tls ) }} - - name: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} + - name: sec-gpg secret: secretName: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} {{- if .Values.app.cache.redis.enabled }} - configMap: name: {{ $Name }}-cm-app-php - name: {{ $Name }}-cm-app-php + name: cm-app-php {{- end }} {{- if .Values.subscriptionKey }} - - name: {{ $fullName }}-sec-subscription + - name: sec-subscription secret: secretName: {{ $Name }}-sec-subscription items: @@ -205,12 +205,12 @@ spec: path: subscription_key.txt {{- end }} {{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} - - name: {{ $fullName }}-sec-jwt + - name: sec-jwt secret: secretName: {{ $Name }}-sec-jwt {{- end }} {{- if .Values.app.cache.redis.sentinelProxy.enabled }} - - name: {{ $fullName }}-sec-redis-proxy + - name: sec-redis-proxy secret: secretName: {{ $Name }}-sec-redis-proxy {{- end -}} diff --git a/templates/job-create-gpg.yaml b/templates/job-create-gpg.yaml index 73a86eb..746858b 100644 --- a/templates/job-create-gpg.yaml +++ b/templates/job-create-gpg.yaml @@ -26,7 +26,7 @@ spec: serviceAccountName: {{ $Name }}-sa-{{ $action }} restartPolicy: OnFailure containers: - - name: {{ $fullName }} + - name: create-gpg-keys image: {{ include "passbolt.image" (dict "imageRoot" .Values.app.image "global" .Values.global) }} imagePullPolicy: {{ .Values.app.image.pullPolicy }} command: @@ -89,9 +89,9 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} volumeMounts: - - name: {{ $fullName }}-vol-success + - name: vol-success mountPath: /tmp/pod volumes: - - name: {{ $fullName }}-vol-success + - name: vol-success emptyDir: {} {{- end }} diff --git a/templates/job-create-jwt.yaml b/templates/job-create-jwt.yaml index e35b5f7..c458fcd 100644 --- a/templates/job-create-jwt.yaml +++ b/templates/job-create-jwt.yaml @@ -30,7 +30,7 @@ spec: serviceAccountName: {{ $Name }}-sa-{{ $action }} restartPolicy: OnFailure containers: - - name: {{ $fullName }} + - name: create-jwt-keys image: {{ include "passbolt.image" (dict "imageRoot" .Values.app.image "global" .Values.global) }} imagePullPolicy: {{ .Values.app.image.pullPolicy }} command: @@ -67,9 +67,9 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} volumeMounts: - - name: {{ $fullName }}-vol-success + - name: vol-success mountPath: /tmp/pod volumes: - - name: {{ $fullName }}-vol-success + - name: vol-success emptyDir: {} {{- end }} diff --git a/tests/cronjobs_redis_sidecar_test.yaml b/tests/cronjobs_redis_sidecar_test.yaml index 3dd4bc1..4cc14b1 100644 --- a/tests/cronjobs_redis_sidecar_test.yaml +++ b/tests/cronjobs_redis_sidecar_test.yaml @@ -61,7 +61,7 @@ tests: - contains: path: spec.jobTemplate.spec.template.spec.volumes content: - name: test-passbolt-vol-success + name: vol-success count: 1 any: true @@ -79,7 +79,7 @@ tests: - contains: path: spec.jobTemplate.spec.template.spec.volumes content: - name: test-passbolt-sec-gpg + name: sec-gpg secret: secretName: test-passbolt-sec-gpg count: 1 @@ -100,7 +100,7 @@ tests: - contains: path: spec.jobTemplate.spec.template.spec.volumes content: - name: my-gpg-secret + name: sec-gpg secret: secretName: my-gpg-secret count: 1 diff --git a/tests/deployment_gpg_secret_test.yaml b/tests/deployment_gpg_secret_test.yaml index 15c6c0b..90952e8 100644 --- a/tests/deployment_gpg_secret_test.yaml +++ b/tests/deployment_gpg_secret_test.yaml @@ -12,13 +12,13 @@ tests: - contains: path: spec.template.spec.containers[0].volumeMounts content: - name: test-passbolt-sec-gpg + name: sec-gpg count: 1 any: true - contains: path: spec.template.spec.volumes content: - name: test-passbolt-sec-gpg + name: sec-gpg secret: secretName: test-passbolt-sec-gpg count: 1 @@ -33,13 +33,13 @@ tests: - contains: path: spec.template.spec.containers[0].volumeMounts content: - name: my-gpg-secret + name: sec-gpg count: 1 any: true - contains: path: spec.template.spec.volumes content: - name: my-gpg-secret + name: sec-gpg secret: secretName: my-gpg-secret count: 1 diff --git a/tests/deployment_redis_sidecar_test.yaml b/tests/deployment_redis_sidecar_test.yaml index b8f65ae..73b8dae 100644 --- a/tests/deployment_redis_sidecar_test.yaml +++ b/tests/deployment_redis_sidecar_test.yaml @@ -23,7 +23,7 @@ tests: volumeMounts: - mountPath: "/usr/local/etc/haproxy/haproxy.cfg" subPath: haproxy.cfg - name: test-passbolt-depl-srv-sec-redis-proxy + name: sec-redis-proxy readOnly: true - it: should have only one redis sidecar and mount its configuration @@ -44,7 +44,7 @@ tests: volumeMounts: - mountPath: "/usr/local/etc/haproxy/haproxy.cfg" subPath: haproxy.cfg - name: test-passbolt-depl-srv-sec-redis-proxy + name: sec-redis-proxy readOnly: true count: 1 any: true From a6c070281e90938c562d8ba24d86545a093600aa Mon Sep 17 00:00:00 2001 From: Kuruyia <8174691+Kuruyia@users.noreply.github.com> Date: Sat, 23 Dec 2023 10:20:17 +0100 Subject: [PATCH 04/11] fix: update http port in other resources --- templates/NOTES.txt | 2 +- templates/ingress.yaml | 2 +- tests/ingress_service_port_test.yaml | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/ingress_service_port_test.yaml diff --git a/templates/NOTES.txt b/templates/NOTES.txt index e47a921..46834a9 100644 --- a/templates/NOTES.txt +++ b/templates/NOTES.txt @@ -13,7 +13,7 @@ NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "passbolt-library.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "passbolt-library.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} + echo http://$SERVICE_IP:{{ .Values.service.ports.http.port }} {{- else if contains "ClusterIP" .Values.service.type }} export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "passbolt-library.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") diff --git a/templates/ingress.yaml b/templates/ingress.yaml index 94d792d..fa9be02 100644 --- a/templates/ingress.yaml +++ b/templates/ingress.yaml @@ -3,7 +3,7 @@ {{- $action := "common" -}} {{- $Name := include "passbolt-library.fullname" . -}} {{- $fullName := printf "%s-%s-%s" $Name $type $action -}} -{{- $svcPort := .Values.service.port -}} +{{- $svcPort := .Values.service.ports.http.port -}} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} diff --git a/tests/ingress_service_port_test.yaml b/tests/ingress_service_port_test.yaml new file mode 100644 index 0000000..e490e1b --- /dev/null +++ b/tests/ingress_service_port_test.yaml @@ -0,0 +1,21 @@ +--- +suite: ingress service port +release: + name: test +values: + - values-test.yaml +tests: + - it: should set the port of the backend to the configured HTTP port + templates: + - ingress.yaml + set: + service.ports.http.port: 5080 + ingress.enabled: true + asserts: + - isSubset: + path: spec.rules[0].http.paths[0].backend.service + content: + name: test-passbolt + port: + number: 5080 + any: true From 2f42e18366dc66f3dfb657c113214a2103d244dd Mon Sep 17 00:00:00 2001 From: Christophe Aubry Date: Tue, 27 Feb 2024 09:04:54 +0100 Subject: [PATCH 05/11] Allow use of alternate postgresql port The PostgreSQL port can be different than the standard one, especially when using an external service. Signed-off-by: Christophe Aubry --- templates/deployment.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 7a52c00..621e1fa 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -70,11 +70,11 @@ spec: apt update apt install -y postgresql-client cat <<-EOF > /tmp/.pgpass - ${DATASOURCES_DEFAULT_HOST}:5432:*:${DATASOURCES_DEFAULT_USERNAME}:${DATASOURCES_DEFAULT_PASSWORD} + ${DATASOURCES_DEFAULT_HOST}:${DATASOURCES_DEFAULT_PORT}:*:${DATASOURCES_DEFAULT_USERNAME}:${DATASOURCES_DEFAULT_PASSWORD} EOF chmod 600 /tmp/.pgpass export PGPASSFILE='/tmp/.pgpass' - while ! ${client} -h ${DATASOURCES_DEFAULT_HOST} ; do + while ! ${client} -h ${DATASOURCES_DEFAULT_HOST} -p ${DATASOURCES_DEFAULT_PORT} ; do echo "Waiting for postgresql database connection..." sleep 2 done @@ -82,6 +82,8 @@ spec: env: - name: DATASOURCES_DEFAULT_HOST value: {{ include "passbolt.databaseServiceName" . }} + - name: DATASOURCES_DEFAULT_PORT + value: {{ .Values.passboltEnv.plain.DATASOURCES_DEFAULT_PORT | quote }} {{- with .Values.passboltEnv.extraEnv }} {{- toYaml . | nindent 12 }} {{- end }} From 8266fd6224607b2da63e8e2d0185bebc43bc8bb1 Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Figueira Date: Thu, 11 Apr 2024 10:11:05 +0200 Subject: [PATCH 06/11] Render database port using a helper to handle all of the options --- templates/_helpers.tpl | 19 +++++++++++++++++++ templates/deployment.yaml | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index cc91c9c..6acf025 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -80,6 +80,25 @@ Render the value of the database service {{- end }} {{- end }} +{{/* +Render the value of the database port +*/}} +{{- define "passbolt.databasePort" -}} +{{- if and ( eq .Values.mariadbDependencyEnabled true ) (or ( eq .Values.app.database.kind "mariadb") ( eq .Values.app.database.kind "mysql") ) }} +{{- if eq .Values.mariadb.architecture "replication" }} +{{- default 3306 .Values.passboltEnv.plain.DATASOURCES_DEFAULT_PORT | quote }} +{{- else }} +{{- default ( printf "%s-%s" .Release.Name "mariadb" ) .Values.passboltEnv.plain.DATASOURCES_DEFAULT_HOST | quote }} +{{- end -}} +{{- else if and ( eq .Values.postgresqlDependencyEnabled true ) ( eq .Values.app.database.kind "postgresql" ) }} +{{- default 5432 .Values.passboltEnv.plain.DATASOURCES_DEFAULT_PORT | quote }} +{{- else if ( hasKey .Values.passboltEnv.plain "DATASOURCES_DEFAULT_PORT" ) -}} +{{- printf "%s" .Values.passboltEnv.plain.DATASOURCES_DEFAULT_PORT }} +{{- else }} +{{- fail "DATASOURCES_DEFAULT_PORT can't be empty when mariadbDependencyEnabled and postgresqlDependencyEnabled are disabled"}} +{{- end }} +{{- end }} + {{/* Show error message if the user didn't set the needed values during upgrade */}} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 621e1fa..9f11762 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -83,7 +83,7 @@ spec: - name: DATASOURCES_DEFAULT_HOST value: {{ include "passbolt.databaseServiceName" . }} - name: DATASOURCES_DEFAULT_PORT - value: {{ .Values.passboltEnv.plain.DATASOURCES_DEFAULT_PORT | quote }} + value: {{ include "passbolt.databasePort" . }} {{- with .Values.passboltEnv.extraEnv }} {{- toYaml . | nindent 12 }} {{- end }} From 63828b784531beb904786dd935f179f56f1e68e3 Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Date: Wed, 24 Apr 2024 15:13:57 +0000 Subject: [PATCH 07/11] PB-32541-add-integration-tests --- .github/workflows/push_pr_main.yaml | 14 ++- .gitignore | 7 ++ .gitlab-ci.yml | 27 +++++- .helmignore | 9 +- README.md | 31 ++++++- README.md.gotmpl | 31 ++++++- run_tests.sh | 93 +++++++++++++++++++ templates/tests/integration-script.yaml | 12 +++ templates/tests/integration-tests-runner.yaml | 52 +++++++++++ templates/tests/integration-tests.yaml | 16 ++++ templates/tests/role.yaml | 16 ++++ templates/tests/rolebind.yaml | 14 +++ .../fixtures/create-cluster-with-passbolt.sh | 66 +++++++++++++ tests/integration/fixtures/gpg.sh | 22 +++++ .../fixtures/install_dependencies.sh | 87 +++++++++++++++++ tests/integration/fixtures/kind-config.yaml | 17 ++++ tests/integration/fixtures/log.sh | 15 +++ tests/integration/fixtures/passbolt.sh | 71 ++++++++++++++ tests/integration/fixtures/testing.yaml | 21 +++++ tests/integration/run_integration_tests.sh | 59 ++++++++++++ .../tests/create_and_decrypt_test.sh | 17 ++++ .../tests/create_and_fill_folder_test.sh | 34 +++++++ .../tests/create_and_remove_password_test.sh | 19 ++++ .../create_share_and_decrypt_password_test.sh | 24 +++++ 24 files changed, 764 insertions(+), 10 deletions(-) create mode 100644 run_tests.sh create mode 100644 templates/tests/integration-script.yaml create mode 100644 templates/tests/integration-tests-runner.yaml create mode 100644 templates/tests/integration-tests.yaml create mode 100644 templates/tests/role.yaml create mode 100644 templates/tests/rolebind.yaml create mode 100644 tests/integration/fixtures/create-cluster-with-passbolt.sh create mode 100644 tests/integration/fixtures/gpg.sh create mode 100644 tests/integration/fixtures/install_dependencies.sh create mode 100644 tests/integration/fixtures/kind-config.yaml create mode 100644 tests/integration/fixtures/log.sh create mode 100644 tests/integration/fixtures/passbolt.sh create mode 100644 tests/integration/fixtures/testing.yaml create mode 100644 tests/integration/run_integration_tests.sh create mode 100644 tests/integration/tests/create_and_decrypt_test.sh create mode 100644 tests/integration/tests/create_and_fill_folder_test.sh create mode 100644 tests/integration/tests/create_and_remove_password_test.sh create mode 100644 tests/integration/tests/create_share_and_decrypt_password_test.sh diff --git a/.github/workflows/push_pr_main.yaml b/.github/workflows/push_pr_main.yaml index 370609a..5b268c6 100644 --- a/.github/workflows/push_pr_main.yaml +++ b/.github/workflows/push_pr_main.yaml @@ -21,7 +21,7 @@ jobs: uses: ./.github/actions/setup_helm - name: Run linter - run: helm lint + run: bash run_tests.sh --lint unit-test: name: Unit Tests @@ -37,4 +37,14 @@ jobs: run: helm plugin install https://github.com/helm-unittest/helm-unittest.git - name: Run unit tests - run: helm unittest --color . + run: bash run_tests.sh --unit + + integration-test: + name: Integration Tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run integration tests + run: bash run_tests.sh --integration diff --git a/.gitignore b/.gitignore index 5810f33..c600b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ charts/* values-sec.yaml *.vim +secret.asc +public.asc +passbolt +mkcert +helm +kubectl +kind diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index afc09fa..04af5aa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,12 @@ +variables: + DOCKER_HOST: tcp://docker:2375 + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + +services: + - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:dind + alias: docker + stages: - test - deploy @@ -5,26 +14,34 @@ stages: lint Helm Charts: image: - name: registry.gitlab.com/passbolt/passbolt-ci-docker-images/helm:latest + name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/alpine/helm entrypoint: ["/bin/sh", "-c"] stage: test script: - helm dependency update - - helm lint . + - bash run_tests.sh --lint test Helm Charts: image: - name: registry.gitlab.com/passbolt/passbolt-ci-docker-images/helm:latest + name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/alpine/helm entrypoint: ["/bin/sh", "-c"] stage: test script: - helm dependency update - helm plugin install https://github.com/helm-unittest/helm-unittest - - helm unittest --color -d . + - bash run_tests.sh --unit + +integration Tests Helm Charts: + image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:dind + script: + - | + apk update && apk add -U curl bash + sleep 10 # Wait for docker service + bash run_tests.sh --integration publish: stage: publish - image: registry.gitlab.com/passbolt/passbolt-ci-docker-images/helm:latest + image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/alpine/helm variables: REPO_BUCKET: "download.passbolt.com" REPO_DIR: "charts" diff --git a/.helmignore b/.helmignore index 3bcd421..2818acb 100644 --- a/.helmignore +++ b/.helmignore @@ -22,4 +22,11 @@ # Gitlab .gitlab-ci.yml .gitlab-ci/ -tests/ +./tests/ +./templates/tests/ +./spec/ +kind +helm +kubectl +passbolt +mkcert diff --git a/README.md b/README.md index eb2843a..b5fa928 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,36 @@ chart and deletes the release. | tls.autogenerate | bool | `true` | Generates a secret with a self-signed cerfificate that is injected on ingress and passbolt container | | tolerations | list | `[]` | Configure passbolt deployment tolerations | -## Updating REAME.md +## Running tests + +In order to run the available tests, you can run the `run_tests.sh` script on the root of the project. This script runs both the unit and the integration tests. + +``` +$ bash run_tests.sh -h +Run the available tests for passbolt helm charts + +Syntax: run_tests.sh [options] +run_tests.sh with no arguments will run all of the available tests. + +options: +-h|--help Show this message. +-l|--lint Run helm lint. +-u|--unit Run helm unittest tests. +-i|--integration Run integration tests. +-no-clean Skip cleaning step. + +``` + +### Unit tests + +We rely on [helm unitttest](https://github.com/helm-unittest/helm-unittest) framework, so if you want to run it on your own, follow the installation steps in their [docs](https://github.com/helm-unittest/helm-unittest?tab=readme-ov-file#install). + +### Integration tests + +The integration tests code is under the `spec`. There are a list of tools that are required locally to run the integration tests ([kind](https://github.com/kubernetes-sigs/kind), [helm](https://github.com/helm/helm), [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl), [mkcert](https://github.com/FiloSottile/mkcert) and [passbolt go cli](https://github.com/passbolt/go-passbolt-cli)) +and they will be downloaded during the tests execution if they are not installed in the system. + +## Updating README.md We rely on the [helm-docs](https://github.com/norwoodj/helm-docs) helm plugin and [mdformat](https://github.com/executablebooks/mdformat) with [mdformat-tables](https://github.com/executablebooks/mdformat-tables) to generate and format the README.md on each release diff --git a/README.md.gotmpl b/README.md.gotmpl index 4d7fd1b..4c90ddb 100644 --- a/README.md.gotmpl +++ b/README.md.gotmpl @@ -103,7 +103,36 @@ chart and deletes the release. {{ template "chart.valuesSection" . }} -## Updating REAME.md +## Running tests + +In order to run the available tests, you can run the `run_tests.sh` script on the root of the project. This script runs both the unit and the integration tests. + +``` +$ bash run_tests.sh -h +Run the available tests for passbolt helm charts + +Syntax: run_tests.sh [options] +run_tests.sh with no arguments will run all of the available tests. + +options: +-h|--help Show this message. +-l|--lint Run helm lint. +-u|--unit Run helm unittest tests. +-i|--integration Run integration tests. +-no-clean Skip cleaning step. + +``` + +### Unit tests + +We rely on [helm unitttest](https://github.com/helm-unittest/helm-unittest) framework, so if you want to run it on your own, follow the installation steps in their [docs](https://github.com/helm-unittest/helm-unittest?tab=readme-ov-file#install). + +### Integration tests + +The integration tests code is under the `tests/integration`. There are a list of tools that are required locally to run the integration tests ([kind](https://github.com/kubernetes-sigs/kind), [helm](https://github.com/helm/helm), [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl), [mkcert](https://github.com/FiloSottile/mkcert) and [passbolt go cli](https://github.com/passbolt/go-passbolt-cli)) +and they will be downloaded during the tests execution if they are not installed in the system. Even though, there is a cleaning step that runs at the end of the execution to clean the directory. + +## Updating README.md We rely on the [helm-docs](https://github.com/norwoodj/helm-docs) helm plugin and [mdformat](https://github.com/executablebooks/mdformat) with [mdformat-tables](https://github.com/executablebooks/mdformat-tables) to generate and format the README.md on each release diff --git a/run_tests.sh b/run_tests.sh new file mode 100644 index 0000000..6036a8f --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +set -eo pipefail + +RUN_UNIT=false +RUN_LINT=false +RUN_INTEGRATION=false +RUN_ALL=true +CLEAN_INTEGRATION_ASSETS=true + +function run_linter { + if [[ "$RUN_LINT" == "true" || "$RUN_ALL" == "true" ]]; then + helm lint . + fi +} + +function run_unit_tests { + if [[ "$RUN_UNIT" == "true" || "$RUN_ALL" == "true" ]]; then + helm unittest --color . + fi +} + +function run_integration_tests { + if [[ "$RUN_INTEGRATION" == "true" || "$RUN_ALL" == "true" ]]; then + source tests/integration/fixtures/install_dependencies.sh + installDependencies + bash tests/integration/fixtures/create-cluster-with-passbolt.sh + "$HELM_BINARY" test --logs passbolt -n default + fi +} + +function clean_integration_assets { + if [[ "$RUN_INTEGRATION" == "true" ]] || [[ "$RUN_ALL" == "true" ]] && [[ "$CLEAN_INTEGRATION_ASSETS" == "true" ]]; then + echo Cleaning integration testing assets... + rm -f helm kubectl kind mkcerts passbolt + fi +} + +function showHelp { + echo "Run the available tests for passbolt helm charts" + echo + echo "Syntax: $0 [options]" + echo "$0 with no arguments will run all of the available tests." + echo + echo "options:" + echo "-h|--help Show this message." + echo "-l|--lint Run helm lint." + echo "-u|--unit Run helm unittest tests." + echo "-i|--integration Run integration tests." + echo "-no-clean Skip cleaning step." + echo + exit 0 +} + +function run_all { + run_linter + run_unit_tests + run_integration_tests + clean_integration_assets +} + +while [[ $# -gt 0 ]]; do + case $1 in + -h | --help) + showHelp + ;; + -l | --lint) + RUN_ALL=false + RUN_LINT=true + shift + ;; + -u | --unit) + RUN_ALL=false + RUN_UNIT=true + shift + ;; + -i | --integration) + RUN_ALL=false + RUN_INTEGRATION=true + shift + ;; + --no-clean) + CLEAN_INTEGRATION_ASSETS=false + shift + ;; + *) + echo "Unknown argurment $1" + shift + ;; + esac +done + +run_all diff --git a/templates/tests/integration-script.yaml b/templates/tests/integration-script.yaml new file mode 100644 index 0000000..2432565 --- /dev/null +++ b/templates/tests/integration-script.yaml @@ -0,0 +1,12 @@ +{{- if ( and .Values.integrationTests .Values.integrationTests.enabled ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Release.Name }}-integration-script" + labels: + {{- include "passbolt-library.labels" . | nindent 4 }} + {{- include "passbolt-library.selectorLabels" . | nindent 4 }} +data: + run_tests.sh: | + {{- .Files.Get "tests/integration/run_integration_tests.sh" | nindent 4 }} +{{- end }} diff --git a/templates/tests/integration-tests-runner.yaml b/templates/tests/integration-tests-runner.yaml new file mode 100644 index 0000000..c938844 --- /dev/null +++ b/templates/tests/integration-tests-runner.yaml @@ -0,0 +1,52 @@ +{{- if ( and .Values.integrationTests .Values.integrationTests.enabled ) }} +apiVersion: v1 +kind: Pod +metadata: + name: "passbolt-integration-tests-runner" + annotations: + "helm.sh/hook": test +spec: + #serviceAccountName: -sa-common + containers: + - name: tests + image: alpine + command: ["/bin/sh"] + args: + - -c + - | + set -e + apk update && apk add -U curl bash jq gpg gpg-agent + cd + bash /tests/run_tests.sh + env: + - name: TESTS_DEBUG + value: {{ quote .Values.integrationTests.debug }} + volumeMounts: + - name: integration-tests-runner + mountPath: "/tests/run_tests.sh" + subPath: run_tests.sh + readOnly: true + - mountPath: /mkcert + name: mkcert + readOnly: true + - name: integration-tests + mountPath: "/tests/tests" + readOnly: true + - name: integration-fixtures + mountPath: "/tests/fixtures" + readOnly: true + restartPolicy: Never + volumes: + - name: integration-tests-runner + configMap: + name: "{{ .Release.Name }}-integration-script" + - name: integration-tests + configMap: + name: "{{ .Release.Name }}-integration-tests" + - name: integration-fixtures + configMap: + name: "{{ .Release.Name }}-integration-fixtures" + - name: mkcert + secret: + secretName: "{{ .Values.integrationTests.certificatesSecret }}" +{{- end }} diff --git a/templates/tests/integration-tests.yaml b/templates/tests/integration-tests.yaml new file mode 100644 index 0000000..02cc569 --- /dev/null +++ b/templates/tests/integration-tests.yaml @@ -0,0 +1,16 @@ +{{- if ( and .Values.integrationTests .Values.integrationTests.enabled ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Release.Name }}-integration-tests" +data: +{{ (.Files.Glob "tests/integration/tests/*_test.sh").AsConfig | indent 2 }} +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Release.Name }}-integration-fixtures" +data: +{{ (.Files.Glob "tests/integration/fixtures/*.sh").AsConfig | indent 2 }} +{{- end }} diff --git a/templates/tests/role.yaml b/templates/tests/role.yaml new file mode 100644 index 0000000..c7a619d --- /dev/null +++ b/templates/tests/role.yaml @@ -0,0 +1,16 @@ +{{- if ( and .Values.integrationTests .Values.integrationTests.enabled ) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: "{{ .Release.Name}}-tests-role" +rules: + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "delete"] + - apiGroups: ["", "extensions", "apps"] + resources: ["deployments", "pods", "pods/attach", "pods/exec", "pods/log"] + verbs: ["list", "get", "watch", "create", "update", "patch", "delete"] +{{- end }} diff --git a/templates/tests/rolebind.yaml b/templates/tests/rolebind.yaml new file mode 100644 index 0000000..4fe4c8c --- /dev/null +++ b/templates/tests/rolebind.yaml @@ -0,0 +1,14 @@ +{{- if ( and .Values.integrationTests .Values.integrationTests.enabled ) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: "{{ .Release.Name}}-test-binding" +subjects: + - kind: ServiceAccount + name: default + namespace: default +roleRef: + kind: ClusterRole + name: "{{ .Release.Name}}-tests-role" + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/tests/integration/fixtures/create-cluster-with-passbolt.sh b/tests/integration/fixtures/create-cluster-with-passbolt.sh new file mode 100644 index 0000000..70e6e86 --- /dev/null +++ b/tests/integration/fixtures/create-cluster-with-passbolt.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# + +set -eo pipefail + +KIND_CLUSTER_CONFIG_FILE="tests/integration/fixtures/kind-config.yaml" +HELM_TESTING_VALUES="tests/integration/fixtures/testing.yaml" +KIND_CLUSTER_NAME="charts-passbolt-integration" +K8S_LOCAL_TLS_SECRET="local-tls-secret" +SSL_KEY_PATH="/tmp/ssl.key" +SSL_CERT_PATH="/tmp/ssl.crt" + +function createKindCluster { + echo "Creating kind cluster: $KIND_CLUSTER_NAME" + "$KIND_BINARY" create cluster --config "$KIND_CLUSTER_CONFIG_FILE" --name "$KIND_CLUSTER_NAME" +} + +function installNginxIngress { + "$KUBECTL_BINARY" apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + "$KUBECTL_BINARY" rollout status deployment ingress-nginx-controller --timeout=120s -n ingress-nginx +} + +function installPassboltChart { + if [[ ! -z "$GITLAB_CI" || ! -z "$GITHUB_WORKFLOW" ]]; then + "$HELM_BINARY" repo add bitnami https://charts.bitnami.com/bitnami + "$HELM_BINARY" repo add passbolt-library https://download.passbolt.com/charts/passbolt-library + "$HELM_BINARY" dependency build + fi + "$HELM_BINARY" install passbolt . -f $HELM_TESTING_VALUES -n default --set integrationTests.debug="$DEBUG" + "$KUBECTL_BINARY" rollout status deployment passbolt-depl-srv --timeout=120s -n default +} + +function createAndInstallSSLCertificates { + local domain="${1-passbolt.local}" + local ssl_key_path="$SSL_KEY_PATH" + local ssl_cert_path="$SSL_CERT_PATH" + "$MKCERT_BINARY" -install + "$MKCERT_BINARY" -cert-file "$ssl_cert_path" -key-file "$ssl_key_path" "$domain" + "$KUBECTL_BINARY" create secret generic mkcert-ca \ + --from-file=rootCA-key.pem=$("$MKCERT_BINARY" -CAROOT)/rootCA-key.pem \ + --from-file=rootCA.pem=$("$MKCERT_BINARY" -CAROOT)/rootCA.pem \ + -n default +} + +function createSecretWithTLS { + local secret_name="$K8S_LOCAL_TLS_SECRET" + local ssl_key_path="$SSL_KEY_PATH" + local ssl_cert_path="$SSL_CERT_PATH" + if "$KUBECTL_BINARY" get secret $secret_name -n default &>/dev/null; then + "$KUBECTL_BINARY" delete secret $secret_name -n default + fi + "$KUBECTL_BINARY" create secret tls $secret_name --cert="$ssl_cert_path" --key="$ssl_key_path" -n default +} +function createInfraAndInstallPassboltChart { + if ! "$KUBECTL_BINARY" config view -o jsonpath='{.contexts[*].name}' | grep -q "$KIND_CLUSTER_NAME"; then + createKindCluster + createAndInstallSSLCertificates + createSecretWithTLS + installNginxIngress + installPassboltChart + else + echo "Cluster $KIND_CLUSTER_NAME already exists" + fi +} + +createInfraAndInstallPassboltChart diff --git a/tests/integration/fixtures/gpg.sh b/tests/integration/fixtures/gpg.sh new file mode 100644 index 0000000..7eb80cc --- /dev/null +++ b/tests/integration/fixtures/gpg.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +function createGPGKey { + keysize=3072 + email="$1" + _log Creating user gpg key... + gpg --homedir ${TMPGNUPGHOME} --batch --no-tty --gen-key 2>/dev/null <secret-"$email".asc + gpg --homedir ${TMPGNUPGHOME} --armor --export ${email} >public-"$email".asc + _log Gpg key created and exported +} diff --git a/tests/integration/fixtures/install_dependencies.sh b/tests/integration/fixtures/install_dependencies.sh new file mode 100644 index 0000000..a43727f --- /dev/null +++ b/tests/integration/fixtures/install_dependencies.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +HELM_VERSION="v3.14.4" +HELM_BINARY="helm" +KIND_VERSION="v0.19.0" # 0.19 because the new ones fail on .gitlab-ci +KIND_BINARY="kind" +KUBECTL_BINARY="kubectl" +MKCERT_BINARY="mkcert" +PASSBOLT_CLI_BINARY="passbolt" +PASSBOLT_CLI_VERSION="0.3.1" +PASSBOLT_FQDN=passbolt.local +SSL_KEY_PATH="/tmp/ssl.key" +SSL_CERT_PATH="/tmp/ssl.crt" + +function getKubectl { + local path="./kubectl" + if ! command -v "$KUBECTL_BINARY" >/dev/null && [ ! -f "$path" ]; then + curl -sLO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + curl -sLO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256" + echo "$(cat kubectl.sha256) kubectl" | sha256sum -c + chmod +x kubectl + KUBECTL_BINARY="./kubectl" + fi +} + +function getKind { + local path="./kind" + if ! command -v "$KIND_BINARY" >/dev/null && [ ! -f "$path" ]; then + curl -sLo ./kind-linux-amd64 "https://kind.sigs.k8s.io/dl/$KIND_VERSION/kind-linux-amd64" + curl -sLo ./kind-sha256sum "https://github.com/kubernetes-sigs/kind/releases/download/$KIND_VERSION/kind-linux-amd64.sha256sum" + sha256sum -c kind-sha256sum + mv kind-linux-amd64 kind && chmod +x kind && rm kind-sha256sum + KIND_BINARY="./kind" + fi +} + +function getHelm { + local path="./helm" + if ! command -v "$HELM_BINARY" >/dev/null && [ ! -f "$path" ]; then + curl -sL "https://get.helm.sh/helm-$HELM_VERSION-linux-amd64.tar.gz" >helm-"$HELM_VERSION"-linux-amd64.tar.gz + curl -sL "https://get.helm.sh/helm-$HELM_VERSION-linux-amd64.tar.gz.sha256sum" >helm.sha256sum + sha256sum -c helm.sha256sum + tar -xvf helm-"$HELM_VERSION"-linux-amd64.tar.gz linux-amd64/helm && mv linux-amd64/helm . && rm -rf linux-amd64 helm-"$HELM_VERSION"-linux-amd64.tar.gz helm.sha256sum + HELM_BINARY="./helm" + fi +} + +function getMkcert { + local path="./mkcert" + if ! command -v "$MKCERT_BINARY" >/dev/null && [ ! -f "$path" ]; then + echo "Installing mkcert..." + curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" + chmod +x mkcert-v*-linux-amd64 + mv mkcert-v*-linux-amd64 mkcert + MKCERT_BINARY="./mkcert" + fi +} + +function getPassboltGoCli { + local path="./passbolt" + if ! command -v "$PASSBOLT_CLI_BINARY" >/dev/null && [ ! -f "$path" ]; then + local version="$PASSBOLT_CLI_VERSION" + curl -sL "https://github.com/passbolt/go-passbolt-cli/releases/download/v${version}/go-passbolt-cli_${version}_linux_amd64.tar.gz" >go-passbolt-cli_"${version}"_linux_amd64.tar.gz + curl -sL "https://github.com/passbolt/go-passbolt-cli/releases/download/v${version}/checksums.txt" | grep "${version}_linux_amd64.tar.gz" >cli.sha256sum + sha256sum -c cli.sha256sum + tar -xvf go-passbolt-cli_"${version}"_linux_amd64.tar.gz passbolt >/dev/null && rm cli.sha256sum go-passbolt-cli_"${version}"_linux_amd64.tar.gz + PASSBOLT_CLI_BINARY="./passbolt" + fi +} + +function addHostsEntry { + echo "Adding hosts entry to ingress cluster ip..." + echo "$("$KUBECTL_BINARY" get service/ingress-nginx-controller -o jsonpath='{.spec.clusterIP}' -n ingress-nginx) $PASSBOLT_FQDN" >>/etc/hosts +} + +function installDependencies { + getKind + getKubectl + getHelm + getMkcert + getPassboltGoCli + export KUBECTL_BINARY="$KUBECTL_BINARY" + export HELM_BINARY="$HELM_BINARY" + export MKCERT_BINARY="$MKCERT_BINARY" + export PASSBOLT_CLI_BINARY="$PASSBOLT_CLI_BINARY" + export KIND_BINARY="$KIND_BINARY" +} diff --git a/tests/integration/fixtures/kind-config.yaml b/tests/integration/fixtures/kind-config.yaml new file mode 100644 index 0000000..d4c7007 --- /dev/null +++ b/tests/integration/fixtures/kind-config.yaml @@ -0,0 +1,17 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP diff --git a/tests/integration/fixtures/log.sh b/tests/integration/fixtures/log.sh new file mode 100644 index 0000000..cfec37c --- /dev/null +++ b/tests/integration/fixtures/log.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Prints debug logs if TESTS_DEBUG is true +function _echo { + if [ "$TESTS_DEBUG" == true ]; then + printf '[DEBUG]: %s\n' "${DEBUG_MESSAGES[@]}" + fi + DEBUG_MESSAGES=() +} + +# Appends debug logs to a variable +function _log { + local message="$@" + DEBUG_MESSAGES+=("${message[*]}") +} diff --git a/tests/integration/fixtures/passbolt.sh b/tests/integration/fixtures/passbolt.sh new file mode 100644 index 0000000..b8aeed3 --- /dev/null +++ b/tests/integration/fixtures/passbolt.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +function registerPassboltUser { + local firstname=$1 + local lastname=$2 + local email=$3 + registration=$("$KUBECTL_BINARY" exec -it deployment/passbolt-depl-srv -n default -- su -c "bin/cake passbolt register_user -u $email -f $firstname -l $lastname -r admin" -s /bin/bash www-data 2>/dev/null) + _log "$registration" + user_uuid=$(echo "${registration}" | grep -Eo "(http|https)://[a-zA-Z0-9./?=_%:-]*" | cut -d/ -f6) + user_token=$(echo "${registration}" | grep -Eo "(http|https)://[a-zA-Z0-9./?=_%:-]*" | cut -d/ -f7) + + createGPGKey "$email" + + _log Registering user on passbolt api... + curl -s "https://${PASSBOLT_FQDN}/setup/complete/${user_uuid}" \ + -H "authority: ${PASSBOLT_FQDN}" \ + -H "accept: application/json" \ + -H "content-type: application/json" \ + --data-raw "{\"authenticationtoken\":{\"token\":\"${user_token}\"},\"gpgkey\":{\"armored_key\":\"$(awk '{printf "%s\\n", $0}' public-${email}.asc)\"}}" \ + --compressed >/dev/null + _log User "$email" succesfully registered +} + +function configurePassbolt { + local id=$1 + _log Configuring passbolt cli... + _log $PASSBOLT_CLI_BINARY configure --serverAddress "https://${PASSBOLT_FQDN}" --userPassword "$PASSPHRASE" --userPrivateKeyFile "secret-${id}.asc" + $PASSBOLT_CLI_BINARY configure --serverAddress "https://${PASSBOLT_FQDN}" --userPassword "$PASSPHRASE" --userPrivateKeyFile "secret-${id}.asc" + _log passbolt cli configured +} + +function createPassword { + local name="$1" + local secret="$2" + _log $PASSBOLT_CLI_BINARY create resource --name "${name}" --password "$secret" -j + $PASSBOLT_CLI_BINARY create resource --name "${name}" --password "$secret" -j +} + +function createPasswordInFolder { + local name="$1" + local secret="$2" + local folder="$3" + _log $PASSBOLT_CLI_BINARY create resource --name "${name}" --password "$secret" -f "$folder" -j + $PASSBOLT_CLI_BINARY create resource --name "${name}" --password "$secret" -f "$folder" -j +} + +function createFolder { + local name="$1" + _log $PASSBOLT_CLI_BINARY create folder --name "${name}" -j + $PASSBOLT_CLI_BINARY create folder --name "${name}" -j +} + +function sharePassword { + local id=$1 + local user_id=$2 + local type="$3" + _log $PASSBOLT_CLI_BINARY share resource --id "$id" --user "$user_id" --type "$type" + $PASSBOLT_CLI_BINARY share resource --id "$id" --user "$user_id" --type "$type" +} + +function getUserIdByUsername { + local username="$1" + _log $PASSBOLT_CLI_BINARY list user --filter "Username == \"$username\"" -j | jq -r .[0].id + $PASSBOLT_CLI_BINARY list user --filter "Username == \"$username\"" -j | jq -r .[0].id +} + +function getPasswordSecretById { + local id="$1" + _log "$PASSBOLT_CLI_BINARY" get resource --id "$id" -j | jq -r .password + "$PASSBOLT_CLI_BINARY" get resource --id "$id" -j | jq -r .password +} diff --git a/tests/integration/fixtures/testing.yaml b/tests/integration/fixtures/testing.yaml new file mode 100644 index 0000000..a23c53f --- /dev/null +++ b/tests/integration/fixtures/testing.yaml @@ -0,0 +1,21 @@ +# -- Enable integration tests +integrationTests: + enabled: true + certificatesSecret: mkcert-ca + debug: false +tls: + autogenerate: false + existingSecret: local-tls-secret +ingress: + # -- Enable passbolt ingress + enabled: true + # -- Configure passbolt ingress annotations + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + # -- Configure passbolt ingress hosts + hosts: + # @ignored + - host: "passbolt.local" + paths: + - path: / + pathType: ImplementationSpecific diff --git a/tests/integration/run_integration_tests.sh b/tests/integration/run_integration_tests.sh new file mode 100644 index 0000000..0076e32 --- /dev/null +++ b/tests/integration/run_integration_tests.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -eo pipefail + +SPECS_DIR=$(dirname "$0") + +source "$SPECS_DIR"/fixtures/gpg.sh +source "$SPECS_DIR"/fixtures/passbolt.sh +source "$SPECS_DIR"/fixtures/log.sh +source "$SPECS_DIR"/fixtures/install_dependencies.sh +source <(cat "$SPECS_DIR"/tests/*_test.sh) + +TMPGNUPGHOME=$(mktemp -d) +PASSPHRASE="strong-passphrase" +PASSBOLT_FQDN=passbolt.local +#EMAIL="email$(date +'%s')@domain.tld" +FIRSTNAME="John" +LASTNAME="Doe" +declare -a DEBUG_MESSAGES + +function testRunner { + name="$(echo $* | cut -d : -f 1)" + description="$(echo $* | cut -d : -f 2)" + green_text="\033[0;32m" + red_text="\033[0;31m" + reset="\033[0m" + log_file="/tmp/$name-integration-tests.log" + if $name &>${log_file}; then + _echo + echo -e "${green_text}[PASS] $description${reset}" + else + _echo + echo -e "${red_text}[FAIL] $description${reset}" + cat "$log_file" + return 1 + fi +} + +installDependencies +# install CA from secret values +CAROOT=/mkcert "$MKCERT_BINARY" -install +addHostsEntry + +list=( + "testCreateAndDecryptPassword:It_should_create_and_decrypt_a_password" + "testCreateAndRemovePassword:It_should_create_and_remove_a_password" + "testCreateShareAndDecryptPassword:It_should_create_share_and_decrypt_a_password" + "testCreateAndFillFolder:It_should_create_and_fill_a_folder_with_passwords" +) +failed=false +for name in "${list[@]}"; do + if ! testRunner "$name"; then + failed=true + fi +done + +if [ ${failed} == true ]; then + exit 1 +fi diff --git a/tests/integration/tests/create_and_decrypt_test.sh b/tests/integration/tests/create_and_decrypt_test.sh new file mode 100644 index 0000000..3ae7f45 --- /dev/null +++ b/tests/integration/tests/create_and_decrypt_test.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +function testCreateAndDecryptPassword { + local value="password-example" + local test_id="$(date +'%s')" + local username="email${test_id}@domain.tld" + _log Running "$test_id" test + registerPassboltUser $FIRSTNAME $LASTNAME "${username}" "$test_id" + configurePassbolt "${username}" + password=$(createPassword "${test_id}" "${value}" "$test_id") + result=$("$PASSBOLT_CLI_BINARY" get resource --id $(echo $password | jq -r .id) -j | jq -r .password) + if [[ "$value" != "$result" ]]; then + >&2 echo "Expected \"$value\", got \"$result\"" + return 1 + fi + _log Test "$test_id" ran succesfully +} diff --git a/tests/integration/tests/create_and_fill_folder_test.sh b/tests/integration/tests/create_and_fill_folder_test.sh new file mode 100644 index 0000000..c8e8418 --- /dev/null +++ b/tests/integration/tests/create_and_fill_folder_test.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +function createAndFillFolder { + local name="$1" + local test_id="$2" + local passwords_count="$3" + + _log Creating "$name" folder... + folder="$(createFolder "${test_id}")" + _log "$name" folder created + folder_id="$(echo ${folder} | jq -r .id)" + for index in $(seq 1 $passwords_count); do + createPasswordInFolder "password$index" "secret$index" "${folder_id}" + done +} + +function testCreateAndFillFolder { + local name="test-folder" + local test_id="$(date +'%s')" + local username="email${test_id}@domain.tld" + local passwords_count="3" + _log Running "$test_id" test + registerPassboltUser $FIRSTNAME $LASTNAME "${username}" "$test_id" + configurePassbolt "${username}" + createAndFillFolder "${test_id}" "${test_id}" "${passwords_count}" + _log "$PASSBOLT_CLI_BINARY" list resource --filter "FolderParentID == \"${folder_id}\"" -j + resources=$("$PASSBOLT_CLI_BINARY" list resource --filter "FolderParentID == \"${folder_id}\"" -j) + _log "Resources in ${folder_id} folder: \n$resources" + resources_count="$(echo ${resources} | jq -r 'length')" + if [ "$resources_count" != 3 ]; then + >&2 echo "Expected 3 resources in ${test_id} folder, got $resources_count" + return 1 + fi +} diff --git a/tests/integration/tests/create_and_remove_password_test.sh b/tests/integration/tests/create_and_remove_password_test.sh new file mode 100644 index 0000000..3718365 --- /dev/null +++ b/tests/integration/tests/create_and_remove_password_test.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +function testCreateAndRemovePassword { + local value="to-be-removed" + local description="It should create and remove a password" + local test_id="$(date +'%s')" + local username="email${test_id}@domain.tld" + _log Running "$test_id" test + registerPassboltUser $FIRSTNAME $LASTNAME "${username}" "$test_id" + configurePassbolt "${username}" + id=$(createPassword "$test_id" "${value}" "$test_id") + "$PASSBOLT_CLI_BINARY" delete resource --id $(echo $id | jq -r .id) + if [[ $? -ne 0 ]]; then + >&2 echo "Failed to delete the password!" + return 1 + fi + echo "$description" + _log Test "$test_id" ran succesfully +} diff --git a/tests/integration/tests/create_share_and_decrypt_password_test.sh b/tests/integration/tests/create_share_and_decrypt_password_test.sh new file mode 100644 index 0000000..67869ef --- /dev/null +++ b/tests/integration/tests/create_share_and_decrypt_password_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +function testCreateShareAndDecryptPassword { + local value="password-example" + local test_id="$(date +'%s')" + local source_username="source-${test_id}@domain.tld" + local destination_username="destination-${test_id}@domain.tld" + local logs + _log Running "$test_id" test + registerPassboltUser $FIRSTNAME $LASTNAME "${source_username}" + registerPassboltUser $FIRSTNAME $LASTNAME "${destination_username}" + local destination_user_id=$(getUserIdByUsername "${destination_username}") + configurePassbolt "${source_username}" + local id=$(createPassword "${test_id}" "${value}" "$test_id") + sharePassword "$(echo $id | jq -r .id)" "$destination_user_id" "15" + configurePassbolt "${destination_username}" + local result=$(getPasswordSecretById $(echo $id | jq -r .id)) + if [[ "$value" != "$result" ]]; then + >&2 echo "Expected \"$value\", got \"$result\"" + return 1 + fi + _log Test "$test_id" ran succesfully + +} From f08ceaf20146bd83c7cb6e5623a8c33125a8d276 Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Date: Thu, 25 Apr 2024 10:26:24 +0000 Subject: [PATCH 08/11] Add support for internal and ingress certificates. Fixes #69 --- templates/_helpers.tpl | 39 +++++++++++---- templates/deployment.yaml | 2 +- templates/ingress.yaml | 11 ++--- templates/secret-tls-ingress.yaml | 21 +++++++++ ...cret-tls.yaml => secret-tls-internal.yaml} | 6 +-- tests/ingress_container_tls_test.yaml | 13 +++-- tests/ingress_service_port_test.yaml | 25 ++++++++-- tests/ingress_tls_test.yaml | 47 ++++++++++++++----- .../fixtures/create-cluster-with-passbolt.sh | 28 ++++++++++- tests/integration/fixtures/testing.yaml | 12 +++-- values.yaml | 20 ++++---- 11 files changed, 170 insertions(+), 54 deletions(-) create mode 100644 templates/secret-tls-ingress.yaml rename templates/{secret-tls.yaml => secret-tls-internal.yaml} (66%) diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 6acf025..80d336f 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -135,21 +135,19 @@ Show error message if the user didn't set the needed values during upgrade {{- end }} {{- define "passbolt.tls.secretName" -}} -{{- if .globalTLS.existingSecret -}} - {{- printf "%s" .globalTLS.existingSecret -}} +{{- if .tls.autogenerate -}} + {{- printf "%s-sec-tls-ingress-%d" .name .index -}} {{- else }} - {{- printf "%s-sec-%s" .name .tls.secretName -}} + {{- printf "%s" .tls.existingSecret -}} {{- end }} {{- end }} {{- define "passbolt.container.tls.secretName" -}} {{- $name := .name }} -{{- if .globalTLS.existingSecret -}} - {{- printf "%s" .globalTLS.existingSecret -}} +{{- if .tls.autogenerate -}} + {{- printf "%s-sec-tls-internal" $name -}} {{- else }} - {{- with (index .ingressTLS 0 ) -}} - {{- printf "%s-sec-%s" $name .secretName -}} - {{- end }} + {{- printf "%s" .tls.existingSecret -}} {{- end }} {{- end }} @@ -235,7 +233,7 @@ imagePullSecrets: {{- end -}} {{- define "passbolt.gpg.secretName" -}} -{{- if .Values.gpgExistingSecret -}} +{{- if $.Values.gpgExistingSecret -}} {{- printf "%s" .Values.gpgExistingSecret -}} {{- else }} {{- printf "%s-sec-gpg" .name -}} @@ -249,3 +247,26 @@ imagePullSecrets: {{- printf "%s-sec-jwt" .name -}} {{- end }} {{- end }} + +{{- define "passbolt.gen-ingress-certs" -}} +{{- $commonName := .commonName }} +{{- $altNames := .altNames }} +{{- $ca := genCA "vault-ca" 365 -}} +{{- $cert := genSignedCert $commonName nil $altNames 365 $ca -}} +tls.crt: {{ $cert.Cert | b64enc }} +tls.key: {{ $cert.Key | b64enc }} +ca.crt: {{ $ca.Cert | b64enc }} +ca.key: {{ $ca.Key | b64enc }} +{{- end -}} + +{{- define "passbolt.gen-internal-certs" -}} +{{- $commonName := .commonName }} +{{- $altNames := .altNames }} +{{- $ca := genCA "vault-ca" 365 -}} +{{- $cert := genSignedCert $commonName nil $altNames 365 $ca -}} +server.crt: {{ $cert.Cert | b64enc }} +server-key.pem: {{ $cert.Key | b64enc }} +ca.crt: {{ $ca.Cert | b64enc }} +ca.key: {{ $ca.Key | b64enc }} +{{- end -}} + diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 97556e6..581c7cf 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -189,7 +189,7 @@ spec: volumes: - name: {{ $fullName }}-sec-tls secret: - secretName: {{ include "passbolt.container.tls.secretName" (dict "name" $Name "ingressTLS" .Values.ingress.tls "globalTLS" $.Values.tls ) }} + secretName: {{ include "passbolt.container.tls.secretName" (dict "name" $Name "tls" .Values.app.tls ) }} - name: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} secret: secretName: {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} diff --git a/templates/ingress.yaml b/templates/ingress.yaml index fa9be02..8ecb036 100644 --- a/templates/ingress.yaml +++ b/templates/ingress.yaml @@ -3,7 +3,6 @@ {{- $action := "common" -}} {{- $Name := include "passbolt-library.fullname" . -}} {{- $fullName := printf "%s-%s-%s" $Name $type $action -}} -{{- $svcPort := .Values.service.ports.http.port -}} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} @@ -28,12 +27,12 @@ spec: {{- end }} {{- if .Values.ingress.tls }} tls: - {{- range .Values.ingress.tls }} + {{- range $idx, $tls := .Values.ingress.tls }} - hosts: - {{- range .hosts }} + {{- range $tls.hosts }} - {{ . | quote }} {{- end }} - secretName: {{ include "passbolt.tls.secretName" (dict "name" $Name "tls" . "globalTLS" $.Values.tls ) }} + secretName: {{ include "passbolt.tls.secretName" (dict "name" $Name "tls" . "index" $idx ) }} {{- end }} {{- end }} rules: @@ -51,10 +50,10 @@ spec: service: name: {{ $Name }} port: - number: {{ $svcPort }} + name: {{ .port }} {{- else }} serviceName: {{ $Name }} - servicePort: {{ $svcPort }} + servicePort: {{ .port }} {{- end }} {{- end }} {{- end }} diff --git a/templates/secret-tls-ingress.yaml b/templates/secret-tls-ingress.yaml new file mode 100644 index 0000000..16c1774 --- /dev/null +++ b/templates/secret-tls-ingress.yaml @@ -0,0 +1,21 @@ +{{- $type := "sec" -}} +{{- $action := "tls-ingress" -}} +{{- $Name := include "passbolt-library.fullname" . -}} + +{{- range $idx, $tls := .Values.ingress.tls }} +{{- if $tls.autogenerate }} +{{- $fullName := printf "%s-%s-%s-%d" $Name $type $action $idx -}} +{{- $commonName := index $tls.hosts 0 -}} +{{- $altNames := $tls.hosts -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }} + labels: + {{- include "passbolt-library.typelabels" (dict "action" $action "type" $type) | nindent 4 }} +type: Opaque +data: +{{ ( include "passbolt.gen-ingress-certs" (dict "commonName" $commonName "altNames" $altNames ) ) | indent 2 }} +--- +{{ end }} +{{- end }} diff --git a/templates/secret-tls.yaml b/templates/secret-tls-internal.yaml similarity index 66% rename from templates/secret-tls.yaml rename to templates/secret-tls-internal.yaml index 061627b..6a66bd6 100644 --- a/templates/secret-tls.yaml +++ b/templates/secret-tls-internal.yaml @@ -1,6 +1,6 @@ -{{- if .Values.tls.autogenerate -}} +{{- if .Values.app.tls.autogenerate -}} {{- $type := "sec" -}} -{{- $action := "tls" -}} +{{- $action := "tls-internal" -}} {{- $Name := include "passbolt-library.fullname" . -}} {{- $fullName := printf "%s-%s-%s" $Name $type $action -}} @@ -14,5 +14,5 @@ metadata: {{- include "passbolt-library.typelabels" (dict "action" $action "type" $type) | nindent 4 }} type: Opaque data: -{{ ( include "passbolt-library.gen-certs" . ) | indent 2 }} +{{ ( include "passbolt.gen-internal-certs" (dict "commonName" ( printf "%s-%s-svc.cluster.local" $Name .Release.Namespace ) "altNames" nil ) ) | indent 2 }} {{- end }} diff --git a/tests/ingress_container_tls_test.yaml b/tests/ingress_container_tls_test.yaml index f43fcc2..ae0f8d9 100644 --- a/tests/ingress_container_tls_test.yaml +++ b/tests/ingress_container_tls_test.yaml @@ -5,25 +5,24 @@ release: values: - values-test.yaml tests: - - it: should set tls secretName as the given value + - it: should set container tls secretName as default value templates: - deployment.yaml set: - ingress.enabled: true - ingress.tls[0].secretName: supersecretname + app.tls.autogenerate: true asserts: - contains: path: spec.template.spec.volumes content: secret: - secretName: test-passbolt-sec-supersecretname + secretName: test-passbolt-sec-tls-internal any: true - - it: should set tls secretName as the given value + - it: should set container tls secretName as given value templates: - deployment.yaml set: - ingress.enabled: true - tls.existingSecret: supersecretname + app.tls.autogenerate: false + app.tls.existingSecret: supersecretname asserts: - contains: path: spec.template.spec.volumes diff --git a/tests/ingress_service_port_test.yaml b/tests/ingress_service_port_test.yaml index e490e1b..b0a6b28 100644 --- a/tests/ingress_service_port_test.yaml +++ b/tests/ingress_service_port_test.yaml @@ -2,20 +2,37 @@ suite: ingress service port release: name: test -values: - - values-test.yaml tests: + - it: should set the port of the backend to the configured HTTPS port + templates: + - ingress.yaml + set: + ingress.enabled: true + asserts: + - isSubset: + path: spec.rules[0].http.paths[0].backend.service + content: + name: test-passbolt + port: + name: https + any: true - it: should set the port of the backend to the configured HTTP port templates: - ingress.yaml set: - service.ports.http.port: 5080 ingress.enabled: true + ingress.hosts: + - host: passbolt.local + paths: + - path: / + port: http + pathType: ImplementationSpecific + asserts: - isSubset: path: spec.rules[0].http.paths[0].backend.service content: name: test-passbolt port: - number: 5080 + name: http any: true diff --git a/tests/ingress_tls_test.yaml b/tests/ingress_tls_test.yaml index 9b25f00..339a5bb 100644 --- a/tests/ingress_tls_test.yaml +++ b/tests/ingress_tls_test.yaml @@ -2,43 +2,68 @@ suite: ingress tls secretName release: name: test -values: - - values-test.yaml tests: - it: should set tls secretName as the given value templates: - ingress.yaml set: ingress.enabled: true - ingress.tls[0].secretName: supersecretname + ingress.tls[0]: + existingSecret: supersecretname + hosts: + - passbolt.local asserts: - contains: path: spec.tls content: - secretName: test-passbolt-sec-supersecretname + secretName: supersecretname any: true - - it: should set a default tls secretName + - it: should set a default tls secretName templates: - ingress.yaml set: ingress.enabled: true - ingress.tls[0].secretName: tls + ingress.tls[0]: + autogenerate: true + hosts: + - passbolt.local + asserts: - contains: path: spec.tls content: - secretName: test-passbolt-sec-tls + secretName: test-passbolt-sec-tls-ingress-0 any: true - - it: should set override secretName with a given name + + - it: should set a default tls secretName with correct index templates: - ingress.yaml set: ingress.enabled: true - ingress.tls[0].secretName: tls - tls.existingSecret: supersecret + ingress.tls: + - autogenerate: true + hosts: + - passbolt.local + - autogenerate: true + hosts: + - passbolt.local + - autogenerate: true + hosts: + - passbolt.local + asserts: - contains: path: spec.tls content: - secretName: supersecret + secretName: test-passbolt-sec-tls-ingress-0 + any: true + - contains: + path: spec.tls + content: + secretName: test-passbolt-sec-tls-ingress-1 + any: true + - contains: + path: spec.tls + content: + secretName: test-passbolt-sec-tls-ingress-2 any: true diff --git a/tests/integration/fixtures/create-cluster-with-passbolt.sh b/tests/integration/fixtures/create-cluster-with-passbolt.sh index 70e6e86..d27686b 100644 --- a/tests/integration/fixtures/create-cluster-with-passbolt.sh +++ b/tests/integration/fixtures/create-cluster-with-passbolt.sh @@ -20,13 +20,39 @@ function installNginxIngress { "$KUBECTL_BINARY" rollout status deployment ingress-nginx-controller --timeout=120s -n ingress-nginx } +function upgradePassboltChart { + local private_key="" + local public_key="" + local fingerprint="" + local jwt_private_key="" + local jwt_public_key="" + private_key=$(kubectl get secret passbolt-sec-gpg --namespace default -o jsonpath="{.data.serverkey_private\.asc}")  ✔ │ 56m 0s  + public_key=$(kubectl get secret passbolt-sec-gpg --namespace default -o jsonpath="{.data.serverkey\.asc}") + fingerprint=$(kubectl exec deploy/passbolt-depl-srv -c passbolt-depl-srv -- grep PASSBOLT_GPG_SERVER_KEY_FINGERPRINT /etc/environment | awk -F= '{gsub(/"/, ""); print $2}') + jwt_private_key=$(kubectl get secret passbolt-sec-jwt --namespace default -o jsonpath="{.data.jwt\.key}") + jwt_public_key=$(kubectl get secret passbolt-sec-jwt --namespace default -o jsonpath="{.data.jwt\.pem}") + "$HELM_BINARY" upgrade -i passbolt . \ + -f $HELM_TESTING_VALUES \ + -n default \ + --set integrationTests.debug="$DEBUG" \ + --set gpgServerKeyPrivate="$private_key" \ + --set gpgServerKeyPublic="$public_key" \ + --set passboltEnv.secret.PASSBOLT_GPG_SERVER_KEY_FINGERPRINT="$fingerprint" \ + --set jwtServerPrivate="$jwt_private_key" \ + --set jwtServerPublic="$jwt_public_key" +} + function installPassboltChart { if [[ ! -z "$GITLAB_CI" || ! -z "$GITHUB_WORKFLOW" ]]; then "$HELM_BINARY" repo add bitnami https://charts.bitnami.com/bitnami "$HELM_BINARY" repo add passbolt-library https://download.passbolt.com/charts/passbolt-library "$HELM_BINARY" dependency build fi - "$HELM_BINARY" install passbolt . -f $HELM_TESTING_VALUES -n default --set integrationTests.debug="$DEBUG" + if "$HELM_BINARY" status passbolt; then + upgradePassboltChart + else + "$HELM_BINARY" install passbolt . -f $HELM_TESTING_VALUES -n default --set integrationTests.debug="$DEBUG" + fi "$KUBECTL_BINARY" rollout status deployment passbolt-depl-srv --timeout=120s -n default } diff --git a/tests/integration/fixtures/testing.yaml b/tests/integration/fixtures/testing.yaml index a23c53f..c66d47b 100644 --- a/tests/integration/fixtures/testing.yaml +++ b/tests/integration/fixtures/testing.yaml @@ -3,9 +3,6 @@ integrationTests: enabled: true certificatesSecret: mkcert-ca debug: false -tls: - autogenerate: false - existingSecret: local-tls-secret ingress: # -- Enable passbolt ingress enabled: true @@ -18,4 +15,13 @@ ingress: - host: "passbolt.local" paths: - path: / + port: https pathType: ImplementationSpecific + tls: + - existingSecret: "local-tls-secret" + hosts: + - passbolt.local +app: + tls: + autogenerate: false + existingSecret: "local-tls-secret" diff --git a/values.yaml b/values.yaml index 353fe9e..abd547b 100644 --- a/values.yaml +++ b/values.yaml @@ -151,6 +151,12 @@ app: # -- Configure the passbolt deployment resources extraPodLabels: {} resources: {} + tls: + # -- If autogenerate is true, the chart will generate a secret with a certificate for APP_FULL_BASE_URL hostname + # -- if autogenerate is false, existingSecret should be filled with an existing tls kind secret name + # @ignored + autogenerate: true + #existingSecret: "" # -- Enable email cron cronJobEmail: @@ -356,12 +362,6 @@ service: # -- Configure passbolt HTTP service port name name: http -tls: - # -- Generates a secret with a self-signed cerfificate that is injected on ingress and passbolt container - autogenerate: true - # -- Name of an existing kubernetes secret that contains a SSL certificate to inject on ingress and passbolt container - #existingSecret: "" - ingress: # -- Enable passbolt ingress enabled: false @@ -373,13 +373,15 @@ ingress: - host: passbolt.local paths: - path: / + port: https pathType: ImplementationSpecific # -- Configure passbolt ingress tls tls: - # If secretname is not empty, the tls entry will use it, otherwise will - # have a default name based on the release + # If autogenerate is true, the chart will generate a secret for the given hosts + # if autogenerate is false, existingSecret should be filled with an existing tls kind secret name # @ignored - - secretName: "tls" + - autogenerate: true + # existingSecret: "" hosts: - passbolt.local # -- Configure passbolt deployment nodeSelector From d4cc6392727702cb266fe63c86ae065bc3e3f7dc Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Figueira Date: Thu, 25 Apr 2024 13:40:35 +0200 Subject: [PATCH 09/11] Fixed jwt volumes unit tests --- tests/deployment_jwt_secret_test.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/deployment_jwt_secret_test.yaml b/tests/deployment_jwt_secret_test.yaml index 46413e6..6e689a8 100644 --- a/tests/deployment_jwt_secret_test.yaml +++ b/tests/deployment_jwt_secret_test.yaml @@ -12,13 +12,13 @@ tests: - contains: path: spec.template.spec.containers[0].volumeMounts content: - name: test-passbolt-sec-jwt + name: sec-jwt count: 1 any: true - contains: path: spec.template.spec.volumes content: - name: test-passbolt-sec-jwt + name: sec-jwt secret: secretName: test-passbolt-sec-jwt count: 1 @@ -33,13 +33,13 @@ tests: - contains: path: spec.template.spec.containers[0].volumeMounts content: - name: my-jwt-secret + name: sec-jwt count: 1 any: true - contains: path: spec.template.spec.volumes content: - name: my-jwt-secret + name: sec-jwt secret: secretName: my-jwt-secret count: 1 From be5e4adb8ddd12bd3783c7ac971062a04e8dde83 Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Figueira Date: Thu, 25 Apr 2024 15:53:44 +0200 Subject: [PATCH 10/11] Bump passbolt image tag --- values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values.yaml b/values.yaml index abd547b..9de65f4 100644 --- a/values.yaml +++ b/values.yaml @@ -124,7 +124,7 @@ app: # -- Configure pasbolt deployment image pullPolicy pullPolicy: IfNotPresent # -- Overrides the image tag whose default is the chart appVersion. - tag: 4.4.2-1-ce + tag: 4.6.2-1-ce # Allowed options: mariadb, mysql or postgresql database: kind: mariadb From 7439c53c60428fca614ef7557450471347fac8b1 Mon Sep 17 00:00:00 2001 From: Daniel Del Rio Figueira Date: Thu, 25 Apr 2024 15:55:45 +0200 Subject: [PATCH 11/11] Updated README.md RELEASE_NOTES.md Chart.yaml and CHANGELOG.md for 1.0.0 --- CHANGELOG.md | 16 +++++++++- Chart.yaml | 4 +-- README.md | 10 +++---- RELEASE_NOTES.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 899f13f..e2bf597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,21 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased](https://github.com/passbolt/charts-passbolt/compare/0.7.2...HEAD) +## [Unreleased](https://github.com/passbolt/charts-passbolt/compare/1.0.0...HEAD) + +## [1.0.0] - 2024-04-25 + +### Fixed + +- [#76](https://github.com/passbolt/charts-passbolt/pull/76) Allow use of alternate postgresql port. + +### Added + +- Integration tests were added. +- [#69](https://github.com/passbolt/charts-passbolt/issues/69) Introduce the ability to use different tls certificates on ingress and api. +- [#68](https://github.com/passbolt/charts-passbolt/pull/68) Use static names for pod internal references (container and volumes) +- [#61](https://github.com/passbolt/charts-passbolt/pull/61) feat: use list instead of string for extraVolumes and extraVolumeMounts values. +- [#62](https://github.com/passbolt/charts-passbolt/pull/62) expose the HTTP port in the service. ## [0.7.2] - 2024-01-23 diff --git a/Chart.yaml b/Chart.yaml index a57e96c..4779275 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -15,12 +15,12 @@ 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.7.2 +version: 1.0.0 # 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. -appVersion: 4.4.2-1-ce +appVersion: 4.6.2-1-ce dependencies: - name: passbolt-library version: 0.2.7 diff --git a/README.md b/README.md index b5fa928..fb26b8d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ passbolt sails kubernetes -![Version: 0.7.2](https://img.shields.io/badge/Version-0.7.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.4.2-1-ce](https://img.shields.io/badge/AppVersion-4.4.2--1--ce-informational?style=flat-square) +![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.6.2-1-ce](https://img.shields.io/badge/AppVersion-4.6.2--1--ce-informational?style=flat-square) Passbolt is an open source, security first password manager with strong focus on collaboration. @@ -119,8 +119,9 @@ chart and deletes the release. | app.image.pullPolicy | string | `"IfNotPresent"` | Configure pasbolt deployment image pullPolicy | | app.image.registry | string | `""` | Configure pasbolt deployment image repsitory | | app.image.repository | string | `"passbolt/passbolt"` | | -| app.image.tag | string | `"4.4.2-1-ce"` | Overrides the image tag whose default is the chart appVersion. | +| app.image.tag | string | `"4.6.2-1-ce"` | Overrides the image tag whose default is the chart appVersion. | | app.resources | object | `{}` | | +| app.tls | object | `{}` | | | autoscaling.enabled | bool | `false` | Enable autoscaling on passbolt deployment | | autoscaling.maxReplicas | int | `100` | Configure autoscaling maximum replicas | | autoscaling.minReplicas | int | `1` | Configure autoscaling minimum replicas | @@ -231,7 +232,6 @@ chart and deletes the release. | service.type | string | `"ClusterIP"` | Configure passbolt service type | | serviceAccount.annotations | object | `{}` | Annotations to add to the service account | | serviceAccount.create | bool | `true` | Specifies whether a service account should be created | -| tls.autogenerate | bool | `true` | Generates a secret with a self-signed cerfificate that is injected on ingress and passbolt container | | tolerations | list | `[]` | Configure passbolt deployment tolerations | ## Running tests @@ -260,8 +260,8 @@ We rely on [helm unitttest](https://github.com/helm-unittest/helm-unittest) fram ### Integration tests -The integration tests code is under the `spec`. There are a list of tools that are required locally to run the integration tests ([kind](https://github.com/kubernetes-sigs/kind), [helm](https://github.com/helm/helm), [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl), [mkcert](https://github.com/FiloSottile/mkcert) and [passbolt go cli](https://github.com/passbolt/go-passbolt-cli)) -and they will be downloaded during the tests execution if they are not installed in the system. +The integration tests code is under the `tests/integration`. There are a list of tools that are required locally to run the integration tests ([kind](https://github.com/kubernetes-sigs/kind), [helm](https://github.com/helm/helm), [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl), [mkcert](https://github.com/FiloSottile/mkcert) and [passbolt go cli](https://github.com/passbolt/go-passbolt-cli)) +and they will be downloaded during the tests execution if they are not installed in the system. Even though, there is a cleaning step that runs at the end of the execution to clean the directory. ## Updating README.md diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 489dd62..fa90b6e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,76 @@ -Announcing the immediate availability of passbolt's official helm chart 0.7.2. +Announcing the immediate availability of passbolt's helm chart 1.0.0. +This is a major release that introduces some breaking changes contributed +by the community. -This is a minor change release that fixes a bug when generating the postgresql -credentials secret. +Thanks to all the community members that helped us to improve this chart +and reach version 1.0.0!! :tada: + +@chris968 +@jouve +@Kuruyia + +Following there is a list of breaking changes and possible migration paths +from previous chart versions. Please keep in mind that we can't cover all +possible scenarios. + +If you are having issues upgrading from older chart versions please let us +known by opening an issue in Github + +# TL;DR + +List of breaking changes: + +- Global `tls` value has been removed in favour of `ingress.tls` and `app.tls` +- `ingress.tls[].secretName` has been removed in favour of `ingress.tls[].existingSecret` +- `extraVolumes` and `extraVolumeMounts` values are now a list instead of a string. +- Expose the HTTP port in the service. `service.port`, `service.name` and + `service.targetPort` have been removed in favour of `service.ports` + in order to expose configurable http and https ports. + +# Ingress and TLS related changes + +Global `tls` value has been removed to allow users to have different TLS +certificates injected on ingress objects and passbolt containers. +Ingress TLS is now managed with `ingress.tls` value, while passbolt TLS +is managed with `app.tls` field in the values file. + +## Migrate from old TLS configuration + +`ingress.tls[].secretName` has been removed in favour of +`ingress.tls[].existingSecret` for clarity. + +## Inject same SSL certificate on ingress and service + +Users that were injecting the same secret on Ingress objects and passbolt +container will have to migrate to a configuration similar to: + +```yaml +ingress.tls: + - autogenerate: false + existingSecret: mySSLSecret + hosts: [yourhost.com] +``` + +```yaml +app.tls: + - autogenerate: false + existingSecret: mySSLSecret +``` + +## Inject separate certificates on ingress and service + +Users who want to inject different SSL certificates on ingress objects and passbolt +containers now they have a way to do it by setting: + +```yaml +ingress.tls: + - autogenerate: false + existingSecret: myIngressSSLSecret + hosts: [yourhost.com] +``` + +```yaml +app.tls: + - autogenerate: false + existingSecret: mypassboltSSLSecret +```