diff --git a/CHANGELOG.md b/CHANGELOG.md index a322672..b23a0c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased](https://github.com/passbolt/charts-passbolt/compare/0.7.0...HEAD) +## [0.7.1] - 2024-01-09 + +### Added + +- [#67](https://github.com/passbolt/charts-passbolt/pull/67) feat: add value for supplying an existing secret containing the JWT server keypair +- [#74](https://github.com/passbolt/charts-passbolt/pull/74) Per architecture kubectl download + +### Fixed + +- [#71](https://github.com/passbolt/charts-passbolt/pull/71) fix: set JWT private key in the secret + ## [0.7.0] - 2023-11-23 ### Added diff --git a/Chart.yaml b/Chart.yaml index cc16c5e..f788134 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.0 +version: 0.7.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 4.4.0-1-ce +appVersion: 4.4.2-1-ce dependencies: - name: passbolt-library version: 0.2.7 diff --git a/README.md b/README.md index 722531e..80db743 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ passbolt sails kubernetes -![Version: 0.7.0](https://img.shields.io/badge/Version-0.7.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.4.0-1-ce](https://img.shields.io/badge/AppVersion-4.4.0--1--ce-informational?style=flat-square) +![Version: 0.7.1](https://img.shields.io/badge/Version-0.7.1-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) Passbolt is an open source, security first password manager with strong focus on collaboration. @@ -119,7 +119,7 @@ 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.0-1-ce"` | Overrides the image tag whose default is the chart appVersion. | +| app.image.tag | string | `"4.4.2-1-ce"` | Overrides the image tag whose default is the chart appVersion. | | app.resources | object | `{}` | | | autoscaling.enabled | bool | `false` | Enable autoscaling on passbolt deployment | | autoscaling.maxReplicas | int | `100` | Configure autoscaling maximum replicas | @@ -143,6 +143,7 @@ chart and deletes the release. | jobCreateGpgKeys.extraPodLabels | object | `{}` | | | jobCreateJwtKeys.extraPodLabels | object | `{}` | | | jwtCreateKeysForced | bool | `false` | Forces overwrite JWT keys | +| jwtExistingSecret | string | `""` | Name of the existing secret for the JWT server keypair. The secret must contain the `jwt.key` and `jwt.pem` keys. | | jwtPath | string | `"/etc/passbolt/jwt"` | Configure passbolt jwt directory | | jwtServerPrivate | string | `""` | JWT server private key in base64 | | jwtServerPublic | string | `""` | JWT server public key in base64 | diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e25c187..8875d47 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,9 +1,9 @@ -Announcing the immediate availability of passbolt's official helm chart 0.7.0. +Announcing the immediate availability of passbolt's official helm chart 0.7.1. -First of all, thanks to @Kuruyia for the contributions made to this new release. -One of them adds the ability to inject the GPG key pair from an existing secret -and another one to add some defaults values on the email configuration. +This release contains support for providing external secrets for JWT keys +as well as automatic support to download kubectl binaries based on host +cpu architecture. -The release also brings a new field to toggle the initContainer that waits for -the database to be ready, so users that use service mesh or they have already a -running database can disable it. +Thanks to all the community members involved in this release! + +@Kuruyia @ook diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index f21f291..cc91c9c 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -97,7 +97,7 @@ Show error message if the user didn't set the needed values during upgrade {{- $message = printf "%s\n%s" $message (printf " export FINGERPRINT=$(kubectl exec deploy/%s -c %s -- grep PASSBOLT_GPG_SERVER_KEY_FINGERPRINT /etc/environment | awk -F= '{gsub(/\"/, \"\"); print $2}')" $dpName $containerName) -}} {{- $arguments = printf "%s %s" $arguments (printf "--set %s=$%s --set %s=$%s --set %s=$%s" "gpgServerKeyPrivate" "PRIVATE_KEY" "gpgServerKeyPublic" "PUBLIC_KEY" "passboltEnv.secret.PASSBOLT_GPG_SERVER_KEY_FINGERPRINT" "FINGERPRINT" ) -}} {{- end }} -{{ if and $.Release.IsUpgrade .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED ( not .Values.jwtCreateKeysForced ) (or ( not $.Values.jwtServerPublic ) ( not $.Values.jwtServerPrivate )) }} +{{ if and $.Release.IsUpgrade .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED ( not .Values.jwtCreateKeysForced ) ( not .Values.jwtExistingSecret ) (or ( not $.Values.jwtServerPublic ) ( not $.Values.jwtServerPrivate )) }} {{- if eq $header "" }} {{- $header = printf "JWT" -}} {{- else }} @@ -222,3 +222,11 @@ imagePullSecrets: {{- printf "%s-sec-gpg" .name -}} {{- end }} {{- end }} + +{{- define "passbolt.jwt.secretName" -}} +{{- if .Values.jwtExistingSecret -}} + {{- printf "%s" .Values.jwtExistingSecret -}} +{{- else }} + {{- printf "%s-sec-jwt" .name -}} +{{- end }} +{{- end }} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 8d74714..7a52c00 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -29,7 +29,7 @@ spec: checksum/sec-gpg: {{ include (print $.Template.BasePath "/secret-gpg.yaml") . | sha256sum }} {{- end }} checksum/cm-env: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }} - {{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} + {{- if and .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED ( not .Values.jwtExistingSecret ) }} checksum/sec-jwt: {{ include (print $.Template.BasePath "/secret-jwt.yaml") . | sha256sum }} {{- end }} {{- if .Values.app.cache.redis.sentinelProxy.enabled }} @@ -151,7 +151,7 @@ spec: readOnly: true {{- end }} {{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} - - name: {{ $fullName }}-sec-jwt + - name: {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} mountPath: {{ quote .Values.jwtPath }} readOnly: true {{- end }} @@ -205,9 +205,9 @@ spec: path: subscription_key.txt {{- end }} {{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} - - name: {{ $fullName }}-sec-jwt + - name: {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} secret: - secretName: {{ $Name }}-sec-jwt + secretName: {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} {{- end }} {{- if .Values.app.cache.redis.sentinelProxy.enabled }} - name: {{ $fullName }}-sec-redis-proxy diff --git a/templates/job-create-gpg.yaml b/templates/job-create-gpg.yaml index 73a86eb..efb2dff 100644 --- a/templates/job-create-gpg.yaml +++ b/templates/job-create-gpg.yaml @@ -67,7 +67,8 @@ spec: PUBLIC_SERVERKEY="$(gpg --homedir $GNUPGHOME --armor --export $key_email | base64 -w0)" cd /tmp - kubectlDownload=${KUBECTL_DOWNLOAD_CMD:-'curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"'} + cpuArch=${CPU_ARCH:-$(eval "case `uname -m` in 'x86_64') echo 'amd64';;'aarch64') echo 'arm64';;esac")} + kubectlDownload=${KUBECTL_DOWNLOAD_CMD:-'curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${cpuArch}/kubectl"'} eval $kubectlDownload chmod +x kubectl ./kubectl patch secret {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} --type='json' -p='[{"op": "replace", "path" : "/data/serverkey_private.asc", "value" : '"${PRIVATE_SERVERKEY}"'}]' diff --git a/templates/job-create-jwt.yaml b/templates/job-create-jwt.yaml index e35b5f7..7948931 100644 --- a/templates/job-create-jwt.yaml +++ b/templates/job-create-jwt.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED (or ( not .Values.jwtServerPrivate ) ( not .Values.jwtServerPublic )) }} +{{- if and .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED ( not .Values.jwtExistingSecret ) (or ( not .Values.jwtServerPrivate ) ( not .Values.jwtServerPublic )) }} {{- $type := "job" -}} {{- $action := "create-jwt-keys" -}} {{- $Name := include "passbolt-library.fullname" . -}} @@ -45,11 +45,12 @@ spec: PUBLIC_JWT_KEY="$(cat {{ .Values.jwtPath }}/jwt.pem | base64 -w0 )" cd /tmp - kubectlDownload=${KUBECTL_DOWNLOAD_CMD:-'curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"'} + cpuArch=${CPU_ARCH:-$(eval "case `uname -m` in 'x86_64') echo 'amd64';;'aarch64') echo 'arm64';;esac")} + kubectlDownload=${KUBECTL_DOWNLOAD_CMD:-'curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${cpuArch}/kubectl"'} eval $kubectlDownload chmod +x kubectl - ./kubectl patch secret {{ $Name }}-sec-jwt --type='json' -p='[{"op": "replace", "path" : "/data/jwt.key", "value" : '"${PUBLIC_JWT_KEY}"'}]' - ./kubectl patch secret {{ $Name }}-sec-jwt --type='json' -p='[{"op": "replace", "path" : "/data/jwt.pem", "value" : '"${PUBLIC_JWT_KEY}"'}]' + ./kubectl patch secret {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} --type='json' -p='[{"op": "replace", "path" : "/data/jwt.key", "value" : '"${PRIVATE_JWT_KEY}"'}]' + ./kubectl patch secret {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} --type='json' -p='[{"op": "replace", "path" : "/data/jwt.pem", "value" : '"${PUBLIC_JWT_KEY}"'}]' touch /tmp/pod/success echo "Success" env: diff --git a/templates/rbac.yaml b/templates/rbac.yaml index 40396a8..60a8056 100644 --- a/templates/rbac.yaml +++ b/templates/rbac.yaml @@ -19,7 +19,7 @@ rules: - {{ $Name }}-cm-env - {{ $Name }}-sec-env - {{ include "passbolt.gpg.secretName" ( dict "name" $Name "Values" $.Values ) }} - - {{ $Name }}-sec-jwt + - {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} - {{ $Name }}-sec-tls - {{ $Name }}-sec-tls-ing - {{ $Name }}-sec-subscription @@ -113,7 +113,7 @@ rules: resources: [ "configmaps", "secrets" ] resourceNames: - {{ $Name }}-cm-env - - {{ $Name }}-sec-jwt + - {{ include "passbolt.jwt.secretName" ( dict "name" $Name "Values" $.Values ) }} - {{ $Name }}-sec-env - {{ $Name }}-sec-redis-proxy verbs: ["get", "patch"] diff --git a/templates/secret-jwt.yaml b/templates/secret-jwt.yaml index 3a26c4f..06845f3 100644 --- a/templates/secret-jwt.yaml +++ b/templates/secret-jwt.yaml @@ -1,4 +1,4 @@ -{{- if .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED }} +{{- if and .Values.passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED ( not .Values.jwtExistingSecret ) }} {{- $type := "sec" -}} {{- $action := "jwt" -}} {{- $Name := include "passbolt-library.fullname" . -}} diff --git a/tests/auto_jwt_keys_creation_install.yaml b/tests/auto_jwt_keys_creation_install_test.yaml similarity index 85% rename from tests/auto_jwt_keys_creation_install.yaml rename to tests/auto_jwt_keys_creation_install_test.yaml index 6aecf18..27fae0b 100644 --- a/tests/auto_jwt_keys_creation_install.yaml +++ b/tests/auto_jwt_keys_creation_install_test.yaml @@ -17,7 +17,7 @@ tests: kind: Job name: test-passbolt-job-create-jwt-keys - - it: should not create a gpg job + - it: should not create a gpg job if key values are supplied templates: - job-create-jwt.yaml set: @@ -38,6 +38,15 @@ tests: - hasDocuments: count: 0 + - it: should not create a gpg job if an existing secret is supplied + templates: + - job-create-jwt.yaml + set: + jwtExistingSecret: "my-jwt-secret" + asserts: + - hasDocuments: + count: 0 + - it: should be executed only on pre-install templates: - job-create-jwt.yaml @@ -60,7 +69,10 @@ tests: asserts: - matchRegex: path: spec.template.spec.containers[0].args[1] - pattern: ./kubectl patch secret test-passbolt-sec-jwt* + pattern: .*./kubectl patch secret test-passbolt-sec-jwt .*PRIVATE_JWT_KEY.* + - matchRegex: + path: spec.template.spec.containers[0].args[1] + pattern: .*./kubectl patch secret test-passbolt-sec-jwt .*PUBLIC_JWT_KEY.* - it: should have a jwt-secret with smaller weight than jwt secret job templates: diff --git a/tests/auto_jwt_keys_creation_upgrade.yaml b/tests/auto_jwt_keys_creation_upgrade_test.yaml similarity index 79% rename from tests/auto_jwt_keys_creation_upgrade.yaml rename to tests/auto_jwt_keys_creation_upgrade_test.yaml index b016366..df21be8 100644 --- a/tests/auto_jwt_keys_creation_upgrade.yaml +++ b/tests/auto_jwt_keys_creation_upgrade_test.yaml @@ -12,6 +12,9 @@ tests: set: jwtServerPublic: "" jwtServerPrivate: "" + jwtCreateKeysForced: true + gpgServerKeyPrivate: "test" + gpgServerKeyPublic: "test" asserts: - equal: path: metadata.annotations["helm.sh/hook"] diff --git a/tests/cronjob_images.yaml b/tests/cronjob_images_test.yaml similarity index 100% rename from tests/cronjob_images.yaml rename to tests/cronjob_images_test.yaml diff --git a/tests/deployment_jwt_secret_test.yaml b/tests/deployment_jwt_secret_test.yaml new file mode 100644 index 0000000..46413e6 --- /dev/null +++ b/tests/deployment_jwt_secret_test.yaml @@ -0,0 +1,46 @@ +--- +suite: deployment jwt secret +release: + name: test +values: + - values-test.yaml +tests: + - it: should contain a volumes and volumeMounts section for jwt secret + templates: + - deployment.yaml + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: test-passbolt-sec-jwt + count: 1 + any: true + - contains: + path: spec.template.spec.volumes + content: + name: test-passbolt-sec-jwt + secret: + secretName: test-passbolt-sec-jwt + count: 1 + any: true + + - it: should use the existing jwt secret if supplied + templates: + - deployment.yaml + set: + jwtExistingSecret: "my-jwt-secret" + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: my-jwt-secret + count: 1 + any: true + - contains: + path: spec.template.spec.volumes + content: + name: my-jwt-secret + secret: + secretName: my-jwt-secret + count: 1 + any: true diff --git a/tests/initContainer_image.yaml b/tests/initContainer_image_test.yaml similarity index 86% rename from tests/initContainer_image.yaml rename to tests/initContainer_image_test.yaml index 0174266..e5b744c 100644 --- a/tests/initContainer_image.yaml +++ b/tests/initContainer_image_test.yaml @@ -9,6 +9,8 @@ tests: set: app.initImage: null # this means emtpy haha app.database.kind: "postgresql" + postgresqlDependencyEnabled: true + mariadbDependencyEnabled: false asserts: - equal: path: spec.template.spec.initContainers[0].image @@ -16,7 +18,7 @@ tests: - matchRegex: path: spec.template.spec.initContainers[0].args[1] pattern: 'client="pg_isready"' - - it: image should be match what is defined on the app.initImage field and the dbclient should match app.initImage.client + - it: image should match what is defined on the app.initImage field and the dbclient should match app.initImage.client templates: - deployment.yaml set: @@ -24,6 +26,8 @@ tests: app.initImage.tag: test app.initImage.client: test app.database.kind: "postgresql" + postgresqlDependencyEnabled: true + mariadbDependencyEnabled: false asserts: - equal: path: spec.template.spec.initContainers[0].image diff --git a/tests/secret_env_postgresql_support.yaml b/tests/secret_env_postgresql_support_test.yaml similarity index 83% rename from tests/secret_env_postgresql_support.yaml rename to tests/secret_env_postgresql_support_test.yaml index 908b08d..0b78059 100644 --- a/tests/secret_env_postgresql_support.yaml +++ b/tests/secret_env_postgresql_support_test.yaml @@ -8,6 +8,8 @@ tests: - secret-env.yaml set: app.database.kind: "postgresql" + mariadbDependencyEnabled: false + postgresqlDependencyEnabled: true passboltEnv.secret.DATASOURCES_DEFAULT_PASSWORD: pass passboltEnv.secret.DATASOURCES_DEFAULT_DATABASE: passboltDatabase passboltEnv.secret.DATASOURCES_DEFAULT_USERNAME: passboltUsername @@ -15,11 +17,13 @@ tests: - equal: path: data.DATASOURCES_DEFAULT_URL value: "cG9zdGdyZXM6Ly9wYXNzYm9sdFVzZXJuYW1lOnBhc3NAdGVzdC1wb3N0Z3Jlc3FsOjU0MzIvcGFzc2JvbHREYXRhYmFzZT9zY2hlbWE9cGFzc2JvbHQ=" - - it: should contain the DATASOURCES_DEFAULT_URL with default given schema + - it: should contain the DATASOURCES_DEFAULT_URL with given schema templates: - secret-env.yaml set: app.database.kind: "postgresql" + mariadbDependencyEnabled: false + postgresqlDependencyEnabled: true passboltEnv.secret.DATASOURCES_DEFAULT_PASSWORD: pass passboltEnv.secret.DATASOURCES_DEFAULT_DATABASE: passboltDatabase passboltEnv.secret.DATASOURCES_DEFAULT_USERNAME: passboltUsername @@ -27,4 +31,4 @@ tests: asserts: - equal: path: data.DATASOURCES_DEFAULT_URL - value: "cG9zdGdyZXM6Ly9wYXNzYm9sdFVzZXJuYW1lOnBhc3NAdGVzdC1wb3N0Z3Jlc3FsOjU0MzIvcGFzc2JvbHREYXRhYmFzZT9zY2hlbWE9cGFzc2JvbHQ=" + value: "cG9zdGdyZXM6Ly9wYXNzYm9sdFVzZXJuYW1lOnBhc3NAdGVzdC1wb3N0Z3Jlc3FsOjU0MzIvcGFzc2JvbHREYXRhYmFzZT9zY2hlbWE9cGFzc2JvbHRTY2hlbWE=" diff --git a/tests/secret_jwt_test.yaml b/tests/secret_jwt_test.yaml new file mode 100644 index 0000000..569a9bd --- /dev/null +++ b/tests/secret_jwt_test.yaml @@ -0,0 +1,35 @@ +--- +suite: secret jwt +release: + name: test +values: + - values-test.yaml +tests: + - it: should create a jwt secret + templates: + - secret-jwt.yaml + set: + jwtExistingSecret: "" + asserts: + - containsDocument: + apiVersion: v1 + kind: Secret + name: test-passbolt-sec-jwt + + - it: should not create a jwt secret when an existing secret is supplied + templates: + - secret-jwt.yaml + set: + jwtExistingSecret: "my-jwt-secret" + asserts: + - hasDocuments: + count: 0 + + - it: should not create a jwt secret when jwt authentication is disabled + templates: + - secret-jwt.yaml + set: + passboltEnv.plain.PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED: false + asserts: + - hasDocuments: + count: 0 diff --git a/tests/values-test.yaml b/tests/values-test.yaml index 0e84f17..40d7ca6 100644 --- a/tests/values-test.yaml +++ b/tests/values-test.yaml @@ -104,6 +104,8 @@ gpgServerKeyPublic: "" # -- Name of the existing secret for the GPG server keypair. The secret must contain the `serverkey.asc` and `serverkey_private.asc` keys. gpgExistingSecret: "" +# -- Name of the existing secret for the JWT server keypair. The secret must contain the `jwt.key` and `jwt.pem` keys. +jwtExistingSecret: "" # -- Configure passbolt jwt directory jwtPath: /etc/passbolt/jwt # -- JWT server private key in base64 diff --git a/values.yaml b/values.yaml index 1eb4410..44a9e46 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.0-1-ce + tag: 4.4.2-1-ce # Allowed options: mariadb, mysql or postgresql database: kind: mariadb @@ -174,6 +174,8 @@ gpgServerKeyPublic: "" # -- Name of the existing secret for the GPG server keypair. The secret must contain the `serverkey.asc` and `serverkey_private.asc` keys. gpgExistingSecret: "" +# -- Name of the existing secret for the JWT server keypair. The secret must contain the `jwt.key` and `jwt.pem` keys. +jwtExistingSecret: "" # -- Configure passbolt jwt directory jwtPath: /etc/passbolt/jwt # -- JWT server private key in base64