diff --git a/charts/trino/templates/NOTES.txt b/charts/trino/templates/NOTES.txt index 90930a1d..d211d7af 100644 --- a/charts/trino/templates/NOTES.txt +++ b/charts/trino/templates/NOTES.txt @@ -8,3 +8,5 @@ Get the application URL by running these commands: echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:8080 {{- end }} + +{{- include "trino.validateValues" . }} diff --git a/charts/trino/templates/_helpers.tpl b/charts/trino/templates/_helpers.tpl index e6023abd..5177bacd 100644 --- a/charts/trino/templates/_helpers.tpl +++ b/charts/trino/templates/_helpers.tpl @@ -24,6 +24,19 @@ If release name contains chart name it will be used as a full name. {{- end }} {{- end }} +{{- define "trino.fullnameEnv" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" | upper | replace "-" "_" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if hasPrefix .Release.Name $name }} +{{- $name | trunc 63 | trimSuffix "-" | upper | replace "-" "_" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" | upper | replace "-" "_" }} +{{- end }} +{{- end }} +{{- end }} + {{/* Create chart name and version as used by the chart label. */}} @@ -155,3 +168,59 @@ Create the secret name for the group-provider file {{- end }} {{- end }} {{- end }} + +{{/* Compile all validation warnings into a single message and call fail. */}} +{{- define "trino.validateValues" -}} +{{- $messages := list -}} +{{- $messages = append $messages (include "trino.validateValues.ingresstlsservice.enabled" .) -}} +{{- $messages = append $messages (include "trino.validateValues.internal.enabled" .) -}} +{{- $messages = append $messages (include "trino.validateValues.httpsonly.enabled" .) -}} +{{- $messages = append $messages (include "trino.validateValues.httpsonly.internal" .) -}} +{{- $messages = append $messages (include "trino.validateValues.httpsonly.ingresstlsservice" .) -}} +{{- $messages = without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate value of .Values.server.config.https.enabled for .Values.ingress.tlsService */}} +{{- define "trino.validateValues.ingresstlsservice.enabled" -}} +{{- if and .Values.ingress.tlsService (not .Values.server.config.https.enabled) -}} +trino: .Values.ingress.tlsService + `.Values.ingress.tlsService` requires `.Values.server.config.https.enabled` +{{- end -}} +{{- end -}} + +{{/* Validate value of .Values.server.config.https.enabled for .Values.server.config.https.internal */}} +{{- define "trino.validateValues.internal.enabled" -}} +{{- if and .Values.server.config.https.internal (not .Values.server.config.https.enabled) -}} +trino: .Values.server.config.https.internal + `.Values.server.config.https.internal` requires `.Values.server.config.https.enabled` +{{- end -}} +{{- end -}} + +{{/* Validate value of .Values.server.config.https.enabled for .Values.server.config.https.only */}} +{{- define "trino.validateValues.httpsonly.enabled" -}} +{{- if and .Values.server.config.https.only (not .Values.server.config.https.enabled) -}} +trino: .Values.server.config.https.only + `.Values.server.config.https.only` requires `.Values.server.config.https.enabled` +{{- end -}} +{{- end -}} + +{{/* Validate value of .Values.server.config.https.internal for .Values.server.config.https.only */}} +{{- define "trino.validateValues.httpsonly.internal" -}} +{{- if and .Values.server.config.https.only (not .Values.server.config.https.internal) -}} +trino: .Values.server.config.https.only + `.Values.server.config.https.only` requires `.Values.server.config.https.internal` +{{- end -}} +{{- end -}} + +{{/* Validate value of .Values.ingress.tlsService for .Values.server.config.https.only */}} +{{- define "trino.validateValues.httpsonly.ingresstlsservice" -}} +{{- if and .Values.server.config.https.only (not .Values.ingress.tlsService) -}} +trino: .Values.server.config.https.only + `.Values.server.config.https.only` requires `.Values.ingress.tlsService` +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/trino/templates/configmap-coordinator.yaml b/charts/trino/templates/configmap-coordinator.yaml index 5c4f7500..7d94a276 100644 --- a/charts/trino/templates/configmap-coordinator.yaml +++ b/charts/trino/templates/configmap-coordinator.yaml @@ -51,24 +51,67 @@ data: config.properties: | coordinator=true node-scheduler.include-coordinator={{ .Values.coordinator.config.nodeScheduler.includeCoordinator }} + {{- if .Values.server.config.https.only }} + http-server.http.enabled=false + {{- else }} http-server.http.port={{ .Values.service.port }} + {{- end }} + {{- if .Values.server.config.https.internal }} + discovery.uri=https://localhost:{{ .Values.service.tlsPort }} + internal-communication.https.required=true + # Taken from https://github.com/trinodb/trino/issues/5230#issuecomment-2062013346 + # Not checking the hostnames may seems like an issue but tls works and is already an additional layer + # of security compared to the shared secret + discovery.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + dynamic.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + exchange.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + failure-detector.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + memoryManager.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + node-manager.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + scheduler.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + workerInfo.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + discovery.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + dynamic.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + exchange.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + failure-detector.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + memoryManager.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + node-manager.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + scheduler.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + workerInfo.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + discovery.http-client.https.hostname-verification=false + dynamic.http-client.https.hostname-verification=false + exchange.http-client.https.hostname-verification=false + failure-detector.http-client.https.hostname-verification=false + memoryManager.http-client.https.hostname-verification=false + node-manager.http-client.https.hostname-verification=false + scheduler.http-client.https.hostname-verification=false + workerInfo.http-client.https.hostname-verification=false + {{- else }} + discovery.uri=http://localhost:{{ .Values.service.port }} + {{- end }} + {{- if .Values.server.config.https.enabled }} + http-server.https.enabled=true + http-server.https.port={{ .Values.service.tlsPort }} + http-server.https.keystore.path={{ .Values.server.config.https.keystore.path }} + http-server.https.keystore.key=${ENV:TRINO_HTTPS_KEYSTORE_SECRET} + http-server.https.keymanager.password=${ENV:TRINO_HTTPS_KEYMANAGER_SECRET} + http-server.https.truststore.path={{ .Values.server.config.https.truststore.path }} + http-server.https.truststore.key=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + {{- end }} + {{- if .Values.ingress.enabled }} + http-server.process-forwarded=true + {{- end }} query.max-memory={{ .Values.server.config.query.maxMemory }} query.max-memory-per-node={{ .Values.coordinator.config.query.maxMemoryPerNode }} {{- if .Values.coordinator.config.memory.heapHeadroomPerNode }} memory.heap-headroom-per-node={{ .Values.coordinator.config.memory.heapHeadroomPerNode }} {{- end }} - discovery.uri=http://localhost:{{ .Values.service.port }} {{- if .Values.server.config.authenticationType }} http-server.authentication.type={{ .Values.server.config.authenticationType }} {{- end }} {{- range $configValue := .Values.additionalConfigProperties }} {{ $configValue }} {{- end }} - {{- if .Values.server.config.https.enabled }} - http-server.https.enabled=true - http-server.https.port={{ .Values.server.config.https.port }} - http-server.https.keystore.path={{ .Values.server.config.https.keystore.path }} - {{- end }} {{- if $coordinatorJmx.enabled }} jmx.rmiregistry.port={{- $coordinatorJmx.registryPort }} jmx.rmiserver.port={{- $coordinatorJmx.serverPort }} diff --git a/charts/trino/templates/configmap-worker.yaml b/charts/trino/templates/configmap-worker.yaml index d78cdee2..4ab62ea6 100644 --- a/charts/trino/templates/configmap-worker.yaml +++ b/charts/trino/templates/configmap-worker.yaml @@ -51,13 +51,41 @@ data: config.properties: | coordinator=false + {{- if .Values.server.config.https.only }} + http-server.http.enabled=false + {{- else }} http-server.http.port={{ .Values.service.port }} + {{- end }} + {{- if .Values.server.config.https.internal }} + internal-communication.https.required=true + discovery.uri=https://{{ template "trino.fullname" . }}:{{ .Values.service.tlsPort }} + http-server.https.enabled=true + http-server.https.port={{ .Values.service.tlsPort }} + http-server.https.keystore.path={{ .Values.server.config.https.workers.keystore.path }} + http-server.https.keystore.key=${ENV:TRINO_HTTPS_KEYSTORE_SECRET} + http-server.https.keymanager.password=${ENV:TRINO_HTTPS_KEYMANAGER_SECRET} + http-server.https.truststore.path={{ .Values.server.config.https.truststore.path }} + http-server.https.truststore.key=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + # Taken from https://github.com/trinodb/trino/issues/5230#issuecomment-2062013346 + # Not checking the hostnames may seems like an issue but tls works and is already an additional layer + # of security compared to the shared secret + discovery.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + exchange.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + node-manager.http-client.trust-store-path={{ .Values.server.config.https.truststore.path }} + discovery.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + exchange.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + node-manager.http-client.trust-store-password=${ENV:TRINO_HTTPS_TRUSTSTORE_SECRET} + discovery.http-client.https.hostname-verification=false + exchange.http-client.https.hostname-verification=false + node-manager.http-client.https.hostname-verification=false + {{- else }} + discovery.uri=http://{{ template "trino.fullname" . }}:{{ .Values.service.port }} + {{- end }} query.max-memory={{ .Values.server.config.query.maxMemory }} query.max-memory-per-node={{ .Values.worker.config.query.maxMemoryPerNode }} {{- if .Values.worker.config.memory.heapHeadroomPerNode }} memory.heap-headroom-per-node={{ .Values.worker.config.memory.heapHeadroomPerNode }} {{- end }} - discovery.uri=http://{{ template "trino.fullname" . }}:{{ .Values.service.port }} {{- range $configValue := .Values.additionalConfigProperties }} {{ $configValue }} {{- end }} diff --git a/charts/trino/templates/deployment-coordinator.yaml b/charts/trino/templates/deployment-coordinator.yaml index 54319456..b8abe09e 100644 --- a/charts/trino/templates/deployment-coordinator.yaml +++ b/charts/trino/templates/deployment-coordinator.yaml @@ -1,4 +1,7 @@ {{- $coordinatorJmx := merge .Values.jmx.coordinator (omit .Values.jmx "coordinator" "worker") -}} +{{- $truststorePasswordSecretRef := .Values.server.config.https.truststore.passwordSecretRef.name -}} +{{- $keystorePasswordSecretRef := .Values.server.config.https.keystore.passwordSecretRef.name -}} +{{- $keymanagerPasswordSecretRef := .Values.server.config.https.keymanager.passwordSecretRef.name -}} apiVersion: apps/v1 kind: Deployment metadata: @@ -134,7 +137,26 @@ spec: securityContext: {{- toYaml .Values.containerSecurityContext | nindent 12 }} env: + {{- if .Values.env }} {{- toYaml .Values.env | nindent 12 }} + {{- end }} + {{- if .Values.server.config.https.enabled }} + - name: TRINO_HTTPS_TRUSTSTORE_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $truststorePasswordSecretRef . }} + key: {{ .Values.server.config.https.truststore.passwordSecretRef.key }} + - name: TRINO_HTTPS_KEYSTORE_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $keystorePasswordSecretRef . }} + key: {{ .Values.server.config.https.keystore.passwordSecretRef.key }} + - name: TRINO_HTTPS_KEYMANAGER_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $keymanagerPasswordSecretRef . }} + key: {{ .Values.server.config.https.keymanager.passwordSecretRef.key }} + {{- end }} envFrom: {{- tpl (toYaml .Values.envFrom) . | nindent 12 }} volumeMounts: @@ -194,9 +216,16 @@ spec: {{- . | toYaml | nindent 12 }} {{- end }} ports: + {{- if not .Values.server.config.https.only }} - name: http containerPort: {{ .Values.service.port }} protocol: TCP + {{- end }} + {{- if .Values.server.config.https.enabled }} + - name: https + containerPort: {{ .Values.service.tlsPort }} + protocol: TCP + {{- end }} {{- if $coordinatorJmx.enabled }} - name: jmx-registry containerPort: {{ $coordinatorJmx.registryPort }} @@ -213,7 +242,13 @@ spec: livenessProbe: httpGet: path: /v1/info + {{- if .Values.server.config.https.only }} + port: https + scheme: HTTPS + {{- else }} port: http + scheme: HTTP + {{- end }} initialDelaySeconds: {{ .Values.coordinator.livenessProbe.initialDelaySeconds | default 30 }} periodSeconds: {{ .Values.coordinator.livenessProbe.periodSeconds | default 10 }} timeoutSeconds: {{ .Values.coordinator.livenessProbe.timeoutSeconds | default 5 }} diff --git a/charts/trino/templates/deployment-worker.yaml b/charts/trino/templates/deployment-worker.yaml index 7a69e8ae..aa572d95 100644 --- a/charts/trino/templates/deployment-worker.yaml +++ b/charts/trino/templates/deployment-worker.yaml @@ -1,4 +1,7 @@ {{- $workerJmx := merge .Values.jmx.worker (omit .Values.jmx "coordinator" "worker") -}} +{{- $truststorePasswordSecretRef := .Values.server.config.https.truststore.passwordSecretRef.name -}} +{{- $keystorePasswordSecretRef := .Values.server.config.https.workers.keystore.passwordSecretRef.name -}} +{{- $keymanagerPasswordSecretRef := .Values.server.config.https.workers.keymanager.passwordSecretRef.name -}} {{- if or .Values.server.keda.enabled (gt (int .Values.server.workers) 0) }} apiVersion: apps/v1 kind: Deployment @@ -120,7 +123,26 @@ spec: securityContext: {{- toYaml .Values.containerSecurityContext | nindent 12 }} env: + {{- if .Values.env }} {{- toYaml .Values.env | nindent 12 }} + {{- end }} + {{- if .Values.server.config.https.internal }} + - name: TRINO_HTTPS_TRUSTSTORE_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $truststorePasswordSecretRef . }} + key: {{ .Values.server.config.https.truststore.passwordSecretRef.key }} + - name: TRINO_HTTPS_KEYSTORE_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $keystorePasswordSecretRef . }} + key: {{ .Values.server.config.https.workers.keystore.passwordSecretRef.key }} + - name: TRINO_HTTPS_KEYMANAGER_SECRET + valueFrom: + secretKeyRef: + name: {{ tpl $keymanagerPasswordSecretRef . }} + key: {{ .Values.server.config.https.workers.keymanager.passwordSecretRef.key }} + {{- end }} envFrom: {{- tpl (toYaml .Values.envFrom) . | nindent 12 }} volumeMounts: @@ -168,9 +190,16 @@ spec: {{- . | toYaml | nindent 12 }} {{- end }} ports: + {{- if not .Values.server.config.https.only }} - name: http containerPort: {{ .Values.service.port }} protocol: TCP + {{- end }} + {{- if .Values.server.config.https.enabled }} + - name: https + containerPort: {{ .Values.service.tlsPort }} + protocol: TCP + {{- end }} {{- if $workerJmx.enabled }} - name: jmx-registry containerPort: {{ $workerJmx.registryPort }} @@ -187,7 +216,13 @@ spec: livenessProbe: httpGet: path: /v1/info + {{- if .Values.server.config.https.only }} + port: https + scheme: HTTPS + {{- else }} port: http + scheme: HTTP + {{- end }} initialDelaySeconds: {{ .Values.worker.livenessProbe.initialDelaySeconds | default 30 }} periodSeconds: {{ .Values.worker.livenessProbe.periodSeconds | default 10 }} timeoutSeconds: {{ .Values.worker.livenessProbe.timeoutSeconds | default 5 }} @@ -218,7 +253,11 @@ spec: -d '"SHUTTING_DOWN"' -H 'Content-type: application/json' -H 'X-Trino-User: admin' + {{- if .Values.server.config.https.only }} + https://localhost:{{- .Values.service.tlsPort -}}/v1/info/state + {{- else }} http://localhost:{{- .Values.service.port -}}/v1/info/state + {{- end }} {{- end }} resources: {{- toYaml .Values.worker.resources | nindent 12 }} diff --git a/charts/trino/templates/ingress.yaml b/charts/trino/templates/ingress.yaml index 1da324c3..0be63306 100644 --- a/charts/trino/templates/ingress.yaml +++ b/charts/trino/templates/ingress.yaml @@ -32,7 +32,11 @@ spec: service: name: {{ include "trino.fullname" $ }} port: + {{- if $.Values.ingress.tlsService }} + number: {{ $.Values.service.tlsPort }} + {{- else }} number: {{ $.Values.service.port }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/trino/templates/service-coordinator.yaml b/charts/trino/templates/service-coordinator.yaml index b028047a..de8b3e12 100644 --- a/charts/trino/templates/service-coordinator.yaml +++ b/charts/trino/templates/service-coordinator.yaml @@ -12,6 +12,7 @@ metadata: spec: type: {{ .Values.service.type }} ports: + {{- if not .Values.server.config.https.only }} - port: {{ .Values.service.port }} targetPort: http protocol: TCP @@ -19,6 +20,13 @@ spec: {{- if .Values.service.nodePort }} nodePort: {{ .Values.service.nodePort }} {{- end }} + {{- end }} + {{- if .Values.server.config.https.enabled }} + - port: {{ .Values.service.tlsPort }} + targetPort: https + protocol: TCP + name: https + {{- end }} {{- if $coordinatorJmx.exporter.enabled }} - port: {{ $coordinatorJmx.exporter.port }} targetPort: jmx-exporter diff --git a/charts/trino/templates/service-worker.yaml b/charts/trino/templates/service-worker.yaml index 97fec58c..e8b339cc 100644 --- a/charts/trino/templates/service-worker.yaml +++ b/charts/trino/templates/service-worker.yaml @@ -12,10 +12,18 @@ metadata: spec: clusterIP: None ports: + {{- if not .Values.server.config.https.only }} - port: {{ .Values.service.port }} targetPort: http protocol: TCP name: http + {{- end }} + {{- if .Values.server.config.https.internal }} + - port: {{ .Values.service.tlsPort }} + targetPort: https + protocol: TCP + name: https + {{- end }} {{- if $workerJmx.exporter.enabled }} - port: {{$workerJmx.exporter.port }} targetPort: jmx-exporter diff --git a/charts/trino/values.yaml b/charts/trino/values.yaml index 645fe587..3020c015 100644 --- a/charts/trino/values.yaml +++ b/charts/trino/values.yaml @@ -49,10 +49,40 @@ server: config: path: /etc/trino https: + # -- Enable https support enabled: false - port: 8443 + # -- Enable communications between coordinator and workers through https. It depends on https being enabled. + # Be aware that when enabled, truststore infos must also be valid for workers + # TLS certificates must also have serverAuth and clientAuth usages + internal: false + # -- Disable http server completely. It requires https.internal and ingress.tlsService (if Ingress is configured) + only: false keystore: path: "" + passwordSecretRef: + name: "" + key: "" + keymanager: + passwordSecretRef: + name: "" + key: "" + # -- Specific workers TLS settings when communications between coordinator and workers go through https. + # Notice that truststore infos are the same as the coordinator + workers: + keystore: + path: "" + passwordSecretRef: + name: "" + key: "" + keymanager: + passwordSecretRef: + name: "" + key: "" + truststore: + path: "" + passwordSecretRef: + name: "" + key: "" # -- Trino supports multiple [authentication # types](https://trino.io/docs/current/security/authentication-types.html): # PASSWORD, CERTIFICATE, OAUTH2, JWT, KERBEROS. @@ -489,6 +519,7 @@ service: annotations: {} type: ClusterIP port: 8080 + tlsPort: 8443 # service.nodePort -- The port the service listens on the host, for the `NodePort` type. If not set, Kubernetes will # [allocate a port # automatically](https://kubernetes.io/docs/concepts/services-networking/service/#nodeport-custom-port). @@ -1063,6 +1094,12 @@ ingress: enabled: false className: "" annotations: {} + # -- Use the TLS service backend instead of the plaintext one -- + # Depending on Openshift or Kubernetes peculiarities you may have to annotate your ingress + # with fields like: + # * route.openshift.io/destination-ca-certificate-secret + # * route.openshift.io/termination + tlsService: false hosts: [] # ingress.hosts -- [Ingress # rules](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules).