diff --git a/charts/rstudio-workbench/Chart.yaml b/charts/rstudio-workbench/Chart.yaml index 46d386ef..b3740f13 100644 --- a/charts/rstudio-workbench/Chart.yaml +++ b/charts/rstudio-workbench/Chart.yaml @@ -1,6 +1,6 @@ name: rstudio-workbench description: Official Helm chart for Posit Workbench -version: 0.8.7 +version: 1.0.0 apiVersion: v2 appVersion: 2024.09.1 icon: https://rstudio.com/wp-content/uploads/2018/10/RStudio-Logo-Flat.png diff --git a/charts/rstudio-workbench/README.md b/charts/rstudio-workbench/README.md index f79e701d..4df72cf9 100644 --- a/charts/rstudio-workbench/README.md +++ b/charts/rstudio-workbench/README.md @@ -14,7 +14,6 @@ To ensure a stable production deployment: * "Pin" the version of the Helm chart that you are using. You can do this using the: * `helm dependency` command *and* the associated "Chart.lock" files *or* * the `--version` flag. - ::: {.callout-important} This protects you from breaking changes. ::: @@ -452,6 +451,8 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | affinity | object | `{}` | A map used verbatim as the pod's "affinity" definition | | args | list | `[]` | args is the pod container's run arguments. | | command | list | `[]` | command is the pod container's run command. By default, it uses the container's default. However, the chart expects a container using `supervisord` for startup | +| config.database.conf.value | string | 0644 | Database connection config | +| config.database.conf.existingSecret | string | `""` | Secret for database connection config | | config.defaultMode.jobJsonOverrides | int | 0644 | default mode for jobJsonOverrides config | | config.defaultMode.pam | int | 0644 | default mode for pam scripts | | config.defaultMode.prestart | int | 0755 | default mode for prestart config | @@ -475,7 +476,8 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | diagnostics | object | `{"directory":"/var/log/rstudio","enabled":false}` | Settings for enabling server diagnostics | | extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) | | fullnameOverride | string | `""` | the full name of the release (can be overridden) | -| global.secureCookieKey | string | `""` | | +| global.secureCookieKey.value | string | `""` | | +| global.secureCookieKey.existingSecret | string | `""` | Secret containing secureCookieKey | | homeStorage.accessModes | list | `["ReadWriteMany"]` | accessModes defined for the storage PVC (represented as YAML) | | homeStorage.create | bool | `false` | whether to create the persistentVolumeClaim for homeStorage | | homeStorage.mount | bool | `false` | Whether the persistentVolumeClaim should be mounted (even if not created) | @@ -507,7 +509,8 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | launcher.templateValues | object | `{"job":{"annotations":{},"labels":{},"ttlSecondsAfterFinished":null},"pod":{"affinity":{},"annotations":{},"command":[],"containerSecurityContext":{},"defaultSecurityContext":{},"env":[],"extraContainers":[],"imagePullPolicy":"","imagePullSecrets":[],"initContainers":[],"labels":{},"nodeSelector":{},"securityContext":{},"serviceAccountName":"","tolerations":[],"volumeMounts":[],"volumes":[]},"service":{"annotations":{},"labels":{},"type":"ClusterIP"}}` | values that are passed along to the launcher job rendering process as a data object (in JSON). These values are then used within session templates. | | launcher.templateValues.pod.command | list | `[]` | command for all pods. This is really not something we should expose and will be removed once we have a better option | | launcher.useTemplates | bool | `false` | whether to render and use templates in the job launching process | -| launcherPem | string | `""` | An inline launcher.pem key. If not provided, one will be auto-generated. See README for more details. | +| launcherPem.value | string | `""` | An inline launcher.pem key. If not provided, one will be auto-generated. See README for more details. | +| launcherPem.existingSecret | string | `""` | Existing Secret for launcherPem | | launcherPub | bool | `false` | An inline launcher.pub key to pair with launcher.pem. If `false` (the default), we will try to generate a `launcher.pub` from the provided `launcher.pem` | | license.file | object | `{"contents":false,"mountPath":"/etc/rstudio-licensing","mountSubPath":false,"secret":false,"secretKey":"license.lic"}` | the file section is used for licensing with a license file | | license.file.contents | bool | `false` | contents is an in-line license file | @@ -552,7 +555,8 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | revisionHistoryLimit | int | `10` | The revisionHistoryLimit to use for the pod deployment. Do not set to 0 | | sealedSecret.annotations | object | `{}` | annotations for SealedSecret resources | | sealedSecret.enabled | bool | `false` | use SealedSecret instead of Secret to deploy secrets | -| secureCookieKey | string | `""` | | +| secureCookieKey.value | string | `""` | | +| secureCookieKey.existingSecret | string | `""` | Secret containing secureCookieKey | | securityContext | object | `{}` | | | service.annotations | object | `{}` | Annotations for the service, for example to specify [an internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer) | | service.clusterIP | string | `""` | The cluster-internal IP to use with `service.type` ClusterIP | @@ -587,7 +591,8 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | topologySpreadConstraints | list | `[]` | An array used verbatim as the pod's "topologySpreadConstraints" definition | | userCreate | bool | `false` | userCreate determines whether a user should be created at startup (if true) | | userName | string | `"rstudio"` | userName determines the username of the created user | -| userPassword | string | `"rstudio"` | userPassword determines the password of the created user | +| userPassword.value | string | `"rstudio"` | userPassword determines the password of the created user | +| userPassword.existingSecret | string | `""` | Existing Secret for userPassword | | userUid | string | `"10000"` | userUid determines the UID of the created user | | versionOverride | string | `""` | A Workbench version to override the "tag" for the RStudio Workbench image and the session images. Necessary until https://github.com/helm/helm/issues/8194 | | xdgConfigDirs | string | `"/mnt/dynamic:/mnt/session-configmap:/mnt/secret-configmap:/mnt/configmap:/mnt/load-balancer/"` | The XDG config dirs (directories where configuration will be read from). Do not change without good reason. | diff --git a/charts/rstudio-workbench/templates/NOTES.txt b/charts/rstudio-workbench/templates/NOTES.txt index 0cf600e8..204db5fe 100644 --- a/charts/rstudio-workbench/templates/NOTES.txt +++ b/charts/rstudio-workbench/templates/NOTES.txt @@ -1,20 +1,20 @@ {{ include "rstudio-workbench.fullname" . }} successfully deployed to namespace {{ $.Release.Namespace }} -{{- if eq .Values.launcherPem "" }} +{{- if eq .Values.launcherPem.value "" }} NOTE: Using auto-generated value for "launcher.pem" - - We recommend making this value persistent by setting `.Values.launcherPem` + - We recommend making this value persistent by setting `.Values.launcherPem.value` or `.Values.launcherPem.existingSecret` - If the value changes, sessions started before the change will not be accessible - You can get the current value with: ``` kubectl -n {{ $.Release.Namespace }} get secret {{ include "rstudio-workbench.fullname" . }}-secret --template='{{print "{{" }}index .data "launcher.pem" | base64decode {{print "}}" }}' ``` {{- end }} -{{- if eq (default .Values.secureCookieKey .Values.global.secureCookieKey) "" }} +{{- if eq (default .Values.secureCookieKey.value .Values.global.secureCookieKey.value) "" }} NOTE: Using an auto-generated value for "secure-cookie-key" - - We recommend making this value persistent by setting `.Values.global.secureCookieKey` + - We recommend making this value persistent by setting `.Values.global.secureCookieKey.value` - If the value changes, authenticated sessions will be invalidated (all users will be logged out) and some old sessions will not be accessible - You can get the current value with: ``` diff --git a/charts/rstudio-workbench/templates/_helpers.tpl b/charts/rstudio-workbench/templates/_helpers.tpl index 29f9ffdd..bf967bd6 100644 --- a/charts/rstudio-workbench/templates/_helpers.tpl +++ b/charts/rstudio-workbench/templates/_helpers.tpl @@ -62,8 +62,17 @@ containers: value: "{{ .Values.userName }}" - name: RSW_TESTUSER_UID value: "{{ .Values.userUid }}" + {{- if .Values.userPassword.existingSecret }} - name: RSW_TESTUSER_PASSWD - value: "{{ .Values.userPassword }}" + valueFrom: + secretKeyRef: + key: password + name: {{ .Values.userPassword.existingSecret }} + {{- end }} + {{- if .Values.userPassword.value }} + - name: RSW_TESTUSER_PASSWD + value: {{ .Values.userPassword.value }} + {{- end }} {{- else }} - name: RSW_TESTUSER value: "" @@ -122,8 +131,25 @@ containers: - name: rstudio-session-secret mountPath: {{ .Values.session.defaultSecretMountPath }} {{- end }} + {{- if or (not .Values.launcherPem.existingSecret) (not .Values.secureCookieKey.existingSecret) }} - name: rstudio-secret mountPath: "/mnt/secret-configmap/rstudio/" + {{- end }} + {{- if .Values.launcherPem.existingSecret }} + - name: launcher-pem-secret + mountPath: "/mnt/secret-configmap/rstudio/launcher.pem" + subPath: "launcher.pem" + {{- end }} + {{- if .Values.secureCookieKey.existingSecret }} + - name: secure-cookie-key-secret + mountPath: "/mnt/secret-configmap/rstudio/secure-cookie-key" + subPath: "secure-cookie-key" + {{- end }} + {{- if .Values.config.database.conf.existingSecret }} + - name: database-conf-secret + mountPath: "/mnt/secret-configmap/rstudio/database.conf" + subPath: "database.conf" + {{- end }} {{- if .Values.config.userProvisioning }} - name: rstudio-user mountPath: "/etc/sssd/conf.d/" @@ -303,10 +329,30 @@ volumes: name: {{ include "rstudio-workbench.fullname" . }}-pam defaultMode: {{ .Values.config.defaultMode.pam }} {{- end }} +{{- if or (not .Values.launcherPem.existingSecret) (not .Values.secureCookieKey.existingSecret) (not .Values.config.database.conf.existingSecret) }} - name: rstudio-secret secret: secretName: {{ include "rstudio-workbench.fullname" . }}-secret defaultMode: {{ .Values.config.defaultMode.secret }} +{{- end }} +{{- if .Values.launcherPem.existingSecret }} +- name: launcher-pem-secret + secret: + secretName: {{ .Values.launcherPem.existingSecret }} + defaultMode: {{ .Values.config.defaultMode.secret }} +{{- end }} +{{- if .Values.secureCookieKey.existingSecret }} +- name: secure-cookie-key-secret + secret: + secretName: {{ .Values.secureCookieKey.existingSecret }} + defaultMode: {{ .Values.config.defaultMode.secret }} +{{- end }} +{{- if .Values.config.database.conf.existingSecret }} +- name: database-conf-secret + secret: + secretName: {{ .Values.config.database.conf.existingSecret }} + defaultMode: {{ .Values.config.defaultMode.secret }} +{{- end }} {{- if .Values.config.userProvisioning }} - name: rstudio-user secret: @@ -440,8 +486,8 @@ app.kubernetes.io/instance: {{ .Release.Name }} - if it is, we warn and leave it alone */}} {{- define "rstudio-workbench.launcherPem" -}} -{{- $pemVar := $.Values.launcherPem -}} -{{- if eq ($.Values.launcherPem) ("") -}} +{{- $pemVar := $.Values.launcherPem.value -}} +{{- if and (eq $.Values.launcherPem.value "") (eq $.Values.launcherPem.existingSecret "") -}} {{- $secretName := print (include "rstudio-workbench.fullname" .) "-secret" }} {{- $currentSecret := lookup "v1" "Secret" $.Release.Namespace $secretName }} {{- if and $currentSecret (not .Values.dangerRegenerateAutomatedValues) }} @@ -462,7 +508,7 @@ app.kubernetes.io/instance: {{ .Release.Name }} - if it is, we warn and leave it alone */}} {{- define "rstudio-workbench.secureCookieKey" -}} -{{- $cookieVar := default .Values.secureCookieKey .Values.global.secureCookieKey -}} +{{- $cookieVar := default .Values.secureCookieKey.value .Values.global.secureCookieKey.value -}} {{- if eq ($cookieVar) ("") -}} {{- $secretName := print (include "rstudio-workbench.fullname" .) "-secret" }} {{- $currentSecret := lookup "v1" "Secret" $.Release.Namespace $secretName }} diff --git a/charts/rstudio-workbench/templates/configmap-secret.yaml b/charts/rstudio-workbench/templates/configmap-secret.yaml index b15919a1..2a907ebe 100644 --- a/charts/rstudio-workbench/templates/configmap-secret.yaml +++ b/charts/rstudio-workbench/templates/configmap-secret.yaml @@ -11,11 +11,21 @@ spec: encryptedData: {{- include "rstudio-library.config.ini" .Values.config.secret | nindent 4 }} {{- /* do not auto-generate value as the secret will not be encrypted */}} + {{- if .Values.launcherPem.existingSecret }} + launcher.pem: | + {{- $launcherPemSecret := (lookup "v1" "Secret" $.Release.Namespace .Values.launcherPem.existingSecret) }} + {{- if $launcherPemSecret }} + {{- $launcherPem := index $launcherPemSecret.data "private_key" | b64dec }} + {{- $launcherPem | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.launcherPem.value }} launcher.pem: | {{- .Values.launcherPem | nindent 6 }} + {{- end }} {{- /* do not auto-generate value as the secret will not be encrypted */}} secure-cookie-key: | - {{- default .Values.secureCookieKey .Values.global.secureCookieKey | nindent 6 }} + {{- default .Values.secureCookieKey.value .Values.global.secureCookieKey.value | nindent 6 }} template: data: {{- if .Values.launcherPub }} diff --git a/charts/rstudio-workbench/values.yaml b/charts/rstudio-workbench/values.yaml index 5c098577..56c22d9e 100644 --- a/charts/rstudio-workbench/values.yaml +++ b/charts/rstudio-workbench/values.yaml @@ -273,7 +273,10 @@ userName: "rstudio" # -- userUid determines the UID of the created user userUid: "10000" # -- userPassword determines the password of the created user -userPassword: "rstudio" +userPassword: + value: "rstudio" + # key 'password' + existingSecret: "" # -- The XDG config dirs (directories where configuration will be read from). Do not change without good reason. xdgConfigDirs: "/mnt/dynamic:/mnt/session-configmap:/mnt/secret-configmap:/mnt/configmap:/mnt/load-balancer/" @@ -376,16 +379,25 @@ extraObjects: [] jobJsonOverridesFiles: {} # -- An inline launcher.pem key. If not provided, one will be auto-generated. See README for more details. -launcherPem: "" +launcherPem: + value: "" + # key 'launcher.pem' + existingSecret: "" # -- An inline launcher.pub key to pair with launcher.pem. If `false` (the default), we will try to generate a `launcher.pub` from the provided `launcher.pem` launcherPub: false -secureCookieKey: "" +secureCookieKey: + value: "" + # key 'secure-cookie-key' + existingSecret: "" dangerRegenerateAutomatedValues: false global: - secureCookieKey: "" + secureCookieKey: + value: "" + # key 'secure-cookie-key' + existingSecret: "" config: defaultMode: @@ -417,6 +429,12 @@ config: # @default -- 0644 pam: 0644 + database: + conf: + value: "" + # key 'database.conf' + existingSecret: "" + # -- a map of session-scoped config files. Mounted to `/mnt/session-configmap/rstudio/` on both server and session, by default. session: repos.conf: