From 5ef5aaa0d822c5b8ce47d1698a0ea874d69c5b09 Mon Sep 17 00:00:00 2001 From: SmokyZone Date: Fri, 18 Sep 2026 20:20:20 +0200 Subject: [PATCH] Terminate TLS on OpenBao with a cert-manager self-signed certificate Adds a ClusterIssuer (selfSigned) + Certificate, mounts the resulting secret into the OpenBao pod, and switches the listener config from tls_disable=1 to a TLS-enabled listener. UI/API is now served over https://:30200 instead of plain HTTP. Also updates ClusterSecretStore/bootstrap Job to use https + trust the self-signed cert via caProvider/BAO_SKIP_VERIFY. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 21 ++++++++++++++++ templates/bootstrap-job.yaml | 6 ++++- templates/clustersecretstore.yaml | 9 ++++++- templates/tls.yaml | 35 ++++++++++++++++++++++++++ values.yaml | 41 ++++++++++++++++++++++++++++++- 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 templates/tls.yaml diff --git a/README.md b/README.md index 99bedf1..b9b08dd 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,37 @@ via Vault's Kubernetes auth method. This chart wraps the official [`openbao-helm`](https://github.com/openbao/openbao-helm) chart as a dependency and adds: +- A self-signed TLS certificate (via cert-manager) that OpenBao terminates + itself, so both the UI and API are served over HTTPS - A `ClusterSecretStore` (ESO CRD) pointing at the OpenBao service - A one-time bootstrap `Job` (disabled by default) that enables the Kubernetes auth method, a read-only policy, and a role bound to ESO's ServiceAccount +## TLS + +OpenBao terminates HTTPS itself using a certificate issued by a dedicated +`ClusterIssuer/openbao-selfsigned` (cert-manager, `selfSigned` type - no +external CA involved). The UI/API is reachable at +`https://:30200` (NodePort, same pattern as ArgoCD). + +Because the certificate is self-signed, browsers will show a trust warning +- this is expected. `ExternalSecret`/`ClusterSecretStore` traffic from ESO +trusts it automatically via `caProvider` (pointing at the same +`openbao-tls` Secret cert-manager creates), so no manual CA import is +needed for that path. + +If you add/replace a node, or want a different reachable hostname, add it to +`tls.ipAddresses` / `tls.dnsNames` in `values.yaml` and cert-manager will +reissue the certificate automatically. + ## Prerequisites - ESO must already be installed in the cluster (deployed separately via the `apps-in-apps` repo) with a ServiceAccount named `eso.serviceAccountName` (default: `external-secrets`) in `eso.namespace` (default: `external-secrets`). +- cert-manager must already be installed (used for the self-signed TLS cert, + see below). ## Deployment & manual init/unseal diff --git a/templates/bootstrap-job.yaml b/templates/bootstrap-job.yaml index 887edc0..597a725 100644 --- a/templates/bootstrap-job.yaml +++ b/templates/bootstrap-job.yaml @@ -29,7 +29,11 @@ spec: image: {{ .Values.bootstrap.image }} env: - name: BAO_ADDR - value: "http://{{ include "openbao-gitops.openbaoFullname" . }}:8200" + value: "{{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://{{ include "openbao-gitops.openbaoFullname" . }}:8200" + {{- if .Values.tls.enabled }} + - name: BAO_SKIP_VERIFY + value: "true" + {{- end }} - name: BAO_TOKEN valueFrom: secretKeyRef: diff --git a/templates/clustersecretstore.yaml b/templates/clustersecretstore.yaml index 46d685d..5ba6bfd 100644 --- a/templates/clustersecretstore.yaml +++ b/templates/clustersecretstore.yaml @@ -8,9 +8,16 @@ metadata: spec: provider: vault: - server: "http://{{ include "openbao-gitops.openbaoFullname" . }}.{{ .Release.Namespace }}.svc:8200" + server: "{{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://{{ include "openbao-gitops.openbaoFullname" . }}.{{ .Release.Namespace }}.svc:8200" path: {{ .Values.eso.kvMountPath }} version: v2 + {{- if .Values.tls.enabled }} + caProvider: + type: Secret + name: {{ .Values.tls.secretName }} + namespace: {{ .Release.Namespace }} + key: tls.crt + {{- end }} auth: kubernetes: mountPath: kubernetes diff --git a/templates/tls.yaml b/templates/tls.yaml new file mode 100644 index 0000000..e3a8029 --- /dev/null +++ b/templates/tls.yaml @@ -0,0 +1,35 @@ +{{- if .Values.tls.enabled }} +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: openbao-selfsigned +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.tls.secretName }} + namespace: {{ .Release.Namespace }} +spec: + secretName: {{ .Values.tls.secretName }} + duration: {{ .Values.tls.duration }} + renewBefore: {{ .Values.tls.renewBefore }} + issuerRef: + name: openbao-selfsigned + kind: ClusterIssuer + dnsNames: + - {{ include "openbao-gitops.openbaoFullname" . }} + - {{ include "openbao-gitops.openbaoFullname" . }}.{{ .Release.Namespace }} + - {{ include "openbao-gitops.openbaoFullname" . }}.{{ .Release.Namespace }}.svc + - {{ include "openbao-gitops.openbaoFullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + - localhost + {{- range .Values.tls.dnsNames }} + - {{ . }} + {{- end }} + ipAddresses: + - "127.0.0.1" + {{- range .Values.tls.ipAddresses }} + - {{ . | quote }} + {{- end }} +{{- end }} diff --git a/values.yaml b/values.yaml index ea4cb95..f94e0ba 100644 --- a/values.yaml +++ b/values.yaml @@ -10,6 +10,24 @@ openbao: # Standalone mode: single replica, file storage backend, PVC-backed. standalone: enabled: true + # TLS terminated directly by OpenBao itself, using the cert-manager + # issued self-signed certificate mounted below (see templates/tls.yaml + # and the `tls:` section further down). "-tls-skip-verify" is already + # baked into the chart's readiness/liveness probes, so this doesn't + # need any extra values there. + config: | + ui = true + + listener "tcp" { + tls_disable = 0 + address = "[::]:8200" + cluster_address = "[::]:8201" + tls_cert_file = "/openbao/userconfig/openbao-tls/tls.crt" + tls_key_file = "/openbao/userconfig/openbao-tls/tls.key" + } + storage "file" { + path = "/openbao/data" + } dataStorage: enabled: true @@ -24,6 +42,12 @@ openbao: authDelegator: enabled: true + # Mounts the cert-manager issued TLS secret at + # /openbao/userconfig/openbao-tls/{tls.crt,tls.key,ca.crt}. + extraVolumes: + - type: secret + name: openbao-tls + resources: requests: cpu: 250m @@ -35,7 +59,7 @@ openbao: ui: enabled: true # NodePort, same pattern as ArgoCD (30080/30443) and Gitea (30300): - # reachable at http://:30200 without needing an Ingress. + # reachable at https://:30200 without needing an Ingress. serviceType: NodePort serviceNodePort: 30200 @@ -43,6 +67,21 @@ openbao: # Sidecar-injector webhook is not needed for ESO integration. enabled: false +# --- TLS (self-signed via cert-manager) ------------------------------------- + +tls: + enabled: true + secretName: openbao-tls + # cert-manager Certificate validity/renewal. + duration: 2160h # 90d + renewBefore: 360h # 15d + # Extra SANs beyond the in-cluster service names (which are always + # included). Add your node IP(s)/hostname(s) here so browsers hitting the + # NodePort get a matching cert. + ipAddresses: + - 192.168.2.218 + dnsNames: [] + # --- ESO <-> OpenBao binding ------------------------------------------------- eso: