diff --git a/charts/everest/README.md b/charts/everest/README.md index 71089282..f54b01be 100644 --- a/charts/everest/README.md +++ b/charts/everest/README.md @@ -165,10 +165,28 @@ The following table shows the configurable parameters of the Percona Everest cha | server.initialAdminPassword | string | `""` | The initial password configured for the admin user. If unset, a random password is generated. It is strongly recommended to reset the admin password after installation. | | server.jwtKey | string | `""` | Key for signing JWT tokens. This needs to be an RSA private key. This is created during installation only. To update the key after installation, you need to manually update the `everest-jwt` Secret or use everestctl. | | server.oidc | object | `{}` | OIDC configuration for Everest. These settings are applied during installation only. To change the settings after installation, you need to manually update the `everest-settings` ConfigMap. | +| server.port | int | `8080` | Port on which the Everest server listens. | | server.rbac | object | `{"enabled":false,"policy":"g, admin, role:admin\n"}` | Settings for RBAC. These settings are applied during installation only. To change the settings after installation, you need to manually update the `everest-rbac` ConfigMap. | | server.rbac.enabled | bool | `false` | If set, enables RBAC for Everest. | | server.rbac.policy | string | `"g, admin, role:admin\n"` | RBAC policy configuration. Ignored if `rbac.enabled` is false. | | server.resources | object | `{"limits":{"cpu":"200m","memory":"500Mi"},"requests":{"cpu":"100m","memory":"20Mi"}}` | Resources to allocate for the server container. | +| 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.secretTemplateAnnotations | object | `{}` | Annotations that allow the certificate to be composed from data residing in existing Kubernetes Resources | +| 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..5e098425 --- /dev/null +++ b/charts/everest/templates/everest-server/certificate.yaml @@ -0,0 +1,42 @@ +{{- 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.secretTemplateAnnotations }} + secretTemplate: + annotations: + {{- range $key, $value := . }} + {{ $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 7692e706..273d9634 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.port }} readinessProbe: httpGet: path: /healthz - port: 8080 + port: {{ .Values.server.port }} + scheme: {{ $probeScheme }} initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /healthz - port: 8080 + port: {{ .Values.server.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,3 +71,9 @@ spec: {{- end }} - name: VERSION_SERVICE_URL value: {{ (include "everest.versionMetadataURL" .) }} + - name: PORT + value: {{ .Values.server.port | quote }} + {{- if .Values.server.tls.enabled }} + - name: TLS_CERTS_PATH + value: {{ $tlsCertsPath | quote }} + {{- end }} diff --git a/charts/everest/templates/everest-server/service.yaml b/charts/everest/templates/everest-server/service.yaml index 051dacd7..e784d9b4 100644 --- a/charts/everest/templates/everest-server/service.yaml +++ b/charts/everest/templates/everest-server/service.yaml @@ -12,5 +12,12 @@ spec: app.kubernetes.io/component: everest-server type: ClusterIP ports: - - protocol: TCP - port: 8080 + - protocol: TCP + {{- if .Values.server.tls.enabled }} + name: https + port: 443 + {{- else }} + port: {{ .Values.server.port }} + name: http + {{- end }} + targetPort: {{ .Values.server.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 fcf90a68..80a72d4e 100644 --- a/charts/everest/values.yaml +++ b/charts/everest/values.yaml @@ -42,6 +42,69 @@ server: # If unset, a random password is generated. # It is strongly recommended to reset the admin password after installation. initialAdminPassword: "" + # -- Port on which the Everest server listens. + port: 8080 + + # 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: [] + # -- Annotations that allow the certificate to be composed from data residing in existing Kubernetes Resources + secretTemplateAnnotations: {} + operator: # -- Image to use for the Everest operator container. image: perconalab/everest-operator