diff --git a/charts/everest/README.md b/charts/everest/README.md index 5af373fd..d5fcd57b 100644 --- a/charts/everest/README.md +++ b/charts/everest/README.md @@ -189,8 +189,27 @@ The following table shows the configurable parameters of the Percona Everest cha | server.resources | object | `{"limits":{"cpu":"200m","memory":"500Mi"},"requests":{"cpu":"100m","memory":"20Mi"}}` | Resources to allocate for the server container. | | server.service | object | `{"name":"everest","port":8080,"type":"ClusterIP"}` | Service configuration for the server. | | server.service.name | string | `"everest"` | Name of the service for everest | -| server.service.port | int | `8080` | Port to expose on the service. | +| server.service.port | int | `8080` | Port to expose on the service. If `tls.enabled=true`, then the service is exposed on port 443. | | server.service.type | string | `"ClusterIP"` | Type of service to create. | +| server.tls.certificate.additionalHosts | list | `[]` | Certificate Subject Alternate Names (SANs) | +| server.tls.certificate.create | bool | `false` | Create a Certificate resource (requires cert-manager to be installed) If set, creates a Certificate resource instead of a Secret. The Certificate uses the Secret name provided by `tls.secret.name` The Everest server pod will come up only after cert-manager has reconciled the Certificate resource. | +| server.tls.certificate.domain | string | `""` | Certificate primary domain (commonName) | +| server.tls.certificate.duration | string | | The requested 'duration' (i.e. lifetime) of the certificate. # Ref: https://cert-manager.io/docs/usage/certificate/#renewal | +| server.tls.certificate.issuer.group | string | `""` | Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io` | +| server.tls.certificate.issuer.kind | string | `""` | Certificate issuer kind. Either `Issuer` or `ClusterIssuer` | +| server.tls.certificate.issuer.name | string | `""` | Certificate issuer name. Eg. `letsencrypt` | +| server.tls.certificate.privateKey.algorithm | string | `"RSA"` | Algorithm used to generate certificate private key. One of: `RSA`, `Ed25519` or `ECDSA` | +| server.tls.certificate.privateKey.encoding | string | `"PKCS1"` | The private key cryptography standards (PKCS) encoding for private key. Either: `PCKS1` or `PKCS8` | +| server.tls.certificate.privateKey.rotationPolicy | string | `"Never"` | Rotation policy of private key when certificate is re-issued. Either: `Never` or `Always` | +| server.tls.certificate.privateKey.size | int | `2048` | Key bit size of the private key. If algorithm is set to `Ed25519`, size is ignored. | +| server.tls.certificate.renewBefore | string | | How long before the expiry a certificate should be renewed. # Ref: https://cert-manager.io/docs/usage/certificate/#renewal | +| server.tls.certificate.secretTemplate | object | `{"annotations":{},"labels":{}}` | Template for the Secret created by the Certificate resource. | +| server.tls.certificate.secretTemplate.annotations | object | `{}` | Annotations to add to the Secret created by the Certificate resource. | +| server.tls.certificate.secretTemplate.labels | object | `{}` | Labels to add to the Secret created by the Certificate resource. | +| server.tls.certificate.usages | list | `[]` | Usages for the certificate ## Ref: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.KeyUsage | +| server.tls.enabled | bool | `false` | If set, enables TLS for the Everest server. Setting tls.enabled=true creates a Secret containing the TLS certificates. Along with certificate.create, it creates a Certificate resource instead. | +| server.tls.secret.certs | object | `{"tls.crt":"","tls.key":""}` | Use the specified tls.crt and tls.key in the Secret. If unspecified, the server creates a self-signed certificate (not recommended for production). | +| server.tls.secret.name | string | `"everest-server-tls"` | Name of the Secret containing the TLS certificates. This Secret is created if tls.enabled=true and certificate.create=false. | | telemetry | bool | `true` | If set, enabled sending telemetry information. | | upgrade.preflightChecks | bool | `true` | If set, run preliminary checks before upgrading. It is strongly recommended to enable this setting. | | versionMetadataURL | string | `"https://check.percona.com"` | URL of the Version Metadata Service. | diff --git a/charts/everest/templates/_helpers.tpl b/charts/everest/templates/_helpers.tpl index 8192f81e..f4958d60 100644 --- a/charts/everest/templates/_helpers.tpl +++ b/charts/everest/templates/_helpers.tpl @@ -112,6 +112,18 @@ altNames: - localhost {{- end }} -{{- define "everest.versionMetadataURL" -}} +{{- define "everest.versionMetadataURL" }} {{- trimSuffix "/" (default "https://check.percona.com" .Values.versionMetadataURL) -}} {{- end }} + +{{- define "everest.tlsCerts" -}} +{{- $svcName := printf "everest" }} +{{- $svcNameWithNS := ( printf "%s.%s" $svcName (include "everest.namespace" .) ) }} +{{- $fullName := ( printf "%s.svc" $svcNameWithNS ) }} +{{- $altNames := list $svcName $svcNameWithNS $fullName }} +{{- $ca := genCA $svcName 3650 }} +{{- $cert := genSignedCert $fullName nil $altNames 3650 $ca }} +{{- $tlsCerts := .Values.server.tls.secret.certs }} +tls.key: {{ index $tlsCerts "tls.key" | default $cert.Key | b64enc }} +tls.crt: {{ index $tlsCerts "tls.crt" | default $cert.Cert | b64enc }} +{{- end }} diff --git a/charts/everest/templates/everest-server/accounts.secret.yaml b/charts/everest/templates/everest-server/accounts.secret.yaml index e408a4d1..37d72871 100644 --- a/charts/everest/templates/everest-server/accounts.secret.yaml +++ b/charts/everest/templates/everest-server/accounts.secret.yaml @@ -11,7 +11,7 @@ metadata: insecure-password/admin: "true" {{- else }} {{- range $key, $value := $secret.metadata.annotations }} - {{ $key }}: "{{ $value }}" + {{ $key }}: {{ $value | quote }} {{- end }} {{- end }} helm.sh/resource-policy: keep diff --git a/charts/everest/templates/everest-server/certificate.yaml b/charts/everest/templates/everest-server/certificate.yaml new file mode 100644 index 00000000..05495979 --- /dev/null +++ b/charts/everest/templates/everest-server/certificate.yaml @@ -0,0 +1,46 @@ +{{- if (and .Values.server.tls.enabled .Values.server.tls.certificate.create) }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.server.tls.secret.name }} + namespace: {{ include "everest.namespace" . }} +spec: + {{- with .Values.server.tls.certificate.secretTemplate }} + secretTemplate: + annotations: + {{- range $key, $value := .annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + labels: + {{- range $key, $value := .labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + secretName: {{ .Values.server.tls.secret.name }} + commonName: {{ .Values.server.tls.certificate.domain }} + dnsNames: + - {{ .Values.server.tls.certificate.domain }} + {{- range .Values.server.tls.certificate.additionalHosts }} + - {{ . | quote }} + {{- end }} + {{- with .Values.server.tls.certificate.duration }} + duration: {{ . | quote }} + {{- end }} + {{- with .Values.server.tls.certificate.renewBefore }} + renewBefore: {{ . | quote }} + {{- end }} + issuerRef: + {{- with .Values.server.tls.certificate.issuer.group }} + group: {{ . | quote }} + {{- end }} + kind: {{ .Values.server.tls.certificate.issuer.kind | quote }} + name: {{ .Values.server.tls.certificate.issuer.name | quote }} + {{- with .Values.server.tls.certificate.privateKey }} + privateKey: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.server.tls.certificate.usages }} + usages: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/everest/templates/everest-server/deployment.yaml b/charts/everest/templates/everest-server/deployment.yaml index 9632b62b..691ce185 100644 --- a/charts/everest/templates/everest-server/deployment.yaml +++ b/charts/everest/templates/everest-server/deployment.yaml @@ -1,6 +1,11 @@ {{- if (ne (include "everest.namespace" .) "everest-system") }} {{ fail "Namespace cannot be set to anything other than everest-system" }} {{- end }} +{{- $tlsCertsPath := "/etc/tls" }} +{{- $probeScheme := "HTTP" }} +{{- if .Values.server.tls.enabled }} +{{- $probeScheme = "HTTPS" }} +{{- end }} apiVersion: apps/v1 kind: Deployment metadata: @@ -26,27 +31,39 @@ spec: - name: jwt-secret secret: secretName: everest-jwt + {{- if .Values.server.tls.enabled }} + - name: tls-certs + secret: + secretName: {{ .Values.server.tls.secret.name }} + {{- end }} containers: - name: everest image: {{ .Values.server.image }}:{{ .Chart.Version }} ports: - - containerPort: 8080 + - containerPort: {{ .Values.server.service.port }} readinessProbe: httpGet: path: /healthz - port: 8080 + port: {{ .Values.server.service.port }} + scheme: {{ $probeScheme }} initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /healthz - port: 8080 + port: {{ .Values.server.service.port }} + scheme: {{ $probeScheme }} initialDelaySeconds: 300 periodSeconds: 15 resources: {{ toYaml .Values.server.resources | nindent 12 }} volumeMounts: - name: jwt-secret mountPath: /etc/jwt + {{- if .Values.server.tls.enabled }} + - name: tls-certs + mountPath: {{ $tlsCertsPath }} + readOnly: true + {{- end }} env: {{- if hasKey .Values.server "apiRequestsRateLimit" }} - name: API_REQUESTS_RATE_LIMIT @@ -54,6 +71,12 @@ spec: {{- end }} - name: VERSION_SERVICE_URL value: {{ (include "everest.versionMetadataURL" .) }} + - name: PORT + value: {{ .Values.server.service.port | quote }} + {{- if .Values.server.tls.enabled }} + - name: TLS_CERTS_PATH + value: {{ $tlsCertsPath | quote }} + {{- end }} {{- if .Values.server.env }} {{- toYaml .Values.server.env | nindent 8 }} {{- end }} diff --git a/charts/everest/templates/everest-server/service.yaml b/charts/everest/templates/everest-server/service.yaml index da00721b..dcbc9f3a 100644 --- a/charts/everest/templates/everest-server/service.yaml +++ b/charts/everest/templates/everest-server/service.yaml @@ -13,5 +13,11 @@ spec: type: {{ .Values.server.service.type }} ports: - protocol: TCP + {{- if .Values.server.tls.enabled }} + name: https + port: 443 + {{- else }} + name: http port: {{ .Values.server.service.port }} - targetPort: 8080 + {{- end }} + targetPort: {{ .Values.server.service.port }} diff --git a/charts/everest/templates/everest-server/tls.secret.yaml b/charts/everest/templates/everest-server/tls.secret.yaml new file mode 100644 index 00000000..e2355599 --- /dev/null +++ b/charts/everest/templates/everest-server/tls.secret.yaml @@ -0,0 +1,11 @@ +{{- if (and .Release.IsInstall .Values.server.tls.enabled (not .Values.server.tls.certificate.create) ) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.server.tls.secret.name }} + namespace: {{ include "everest.namespace" . }} + annotations: + helm.sh/resource-policy: keep +data: + {{- include "everest.tlsCerts" . | trim | nindent 2 }} +{{- end }} diff --git a/charts/everest/values.yaml b/charts/everest/values.yaml index c480e633..0572fabd 100644 --- a/charts/everest/values.yaml +++ b/charts/everest/values.yaml @@ -24,6 +24,7 @@ server: # -- Type of service to create. type: ClusterIP # -- Port to expose on the service. + # If `tls.enabled=true`, then the service is exposed on port 443. port: 8080 # -- Key for signing JWT tokens. This needs to be an RSA private key. # This is created during installation only. @@ -55,6 +56,71 @@ server: # If unset, a random password is generated. # It is strongly recommended to reset the admin password after installation. initialAdminPassword: "" + + # TLS settings for the Everest server. + tls: + # -- If set, enables TLS for the Everest server. + # Setting tls.enabled=true creates a Secret containing the TLS certificates. + # Along with certificate.create, it creates a Certificate resource instead. + enabled: false + + secret: + # -- Name of the Secret containing the TLS certificates. + # This Secret is created if tls.enabled=true and certificate.create=false. + name: everest-server-tls + # -- Use the specified tls.crt and tls.key in the Secret. + # If unspecified, the server creates a self-signed certificate (not recommended for production). + certs: + tls.key: "" + tls.crt: "" + + certificate: + # -- Create a Certificate resource (requires cert-manager to be installed) + # If set, creates a Certificate resource instead of a Secret. + # The Certificate uses the Secret name provided by `tls.secret.name` + # The Everest server pod will come up only after cert-manager has reconciled the Certificate resource. + create: false + # -- Certificate primary domain (commonName) + domain: "" + # -- Certificate Subject Alternate Names (SANs) + additionalHosts: [] + # -- The requested 'duration' (i.e. lifetime) of the certificate. + # @default -- `""` (defaults to 2160h = 90d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + duration: "" + # -- How long before the expiry a certificate should be renewed. + # @default -- `""` (defaults to 360h = 15d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + renewBefore: "" + # Certificate issuer + ## Ref: https://cert-manager.io/docs/concepts/issuer + issuer: + # -- Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io` + group: "" + # -- Certificate issuer kind. Either `Issuer` or `ClusterIssuer` + kind: "" + # -- Certificate issuer name. Eg. `letsencrypt` + name: "" + # Private key of the certificate + privateKey: + # -- Rotation policy of private key when certificate is re-issued. Either: `Never` or `Always` + rotationPolicy: Never + # -- The private key cryptography standards (PKCS) encoding for private key. Either: `PCKS1` or `PKCS8` + encoding: PKCS1 + # -- Algorithm used to generate certificate private key. One of: `RSA`, `Ed25519` or `ECDSA` + algorithm: RSA + # -- Key bit size of the private key. If algorithm is set to `Ed25519`, size is ignored. + size: 2048 + # -- Usages for the certificate + ### Ref: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.KeyUsage + usages: [] + # -- Template for the Secret created by the Certificate resource. + secretTemplate: + # -- Annotations to add to the Secret created by the Certificate resource. + annotations: {} + # -- Labels to add to the Secret created by the Certificate resource. + labels: {} + # -- Additional environment variables to pass to the server deployment. env: [] # - name: key1