From ae8f4ad22b9fdfd1bec52e9f05ff195b38d14e77 Mon Sep 17 00:00:00 2001 From: Alan Bridgeman Date: Fri, 19 Dec 2025 17:11:14 -0600 Subject: [PATCH] Updated chart so that it worked better as a subchart, is more configurable and better documented --- README.md | 40 +++- templates/_helpers.tpl | 16 ++ .../vault-creds-persistant-volume-claim.yaml | 10 +- templates/vault-hashicorp-secret.yaml | 10 +- templates/vault-ingress.yaml | 10 +- templates/vault-keyvault-secret.yaml | 12 +- ...ult-role-vars-persistant-volume-claim.yaml | 10 +- templates/vault-service.yaml | 14 +- .../vault-snapshot-server-configmap.yaml | 6 +- templates/vault-statefulset.yaml | 40 ++-- values.yaml | 199 ++++++++++-------- 11 files changed, 222 insertions(+), 145 deletions(-) create mode 100644 templates/_helpers.tpl diff --git a/README.md b/README.md index 9d71ad6..240d2b3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,41 @@ To use this chart as a dependency: ```yaml dependencies: - name: ba-custom-hashicorp-vault - version: 1.0.0 + version: 1.0.2 repository: "https://helm.bridgemanaccessible.ca/" - condition: vault.enabled -``` \ No newline at end of file + alias: passVault + condition: passVault.enabled +``` + +# Values (`values.yaml`) +The following table summarizes the values that can be specified in the `values.yaml` + +| Value Name | Possible Values | Required | +| ------------------------------------------------------------ | ---------------------------------------------------------------- | -------- | +| `type` | `hashicorp` / `azure` | Yes | +| `vaultName` | string | No | +| `vaultPort` | number (ex. `8200`) | No | +| `clientID` | string | No | +| `clientSecret` | string | No | +| `tenantID` | string | No | +| `create`.`enabled` | `true` / `false` | Yes | +| `create`.`image`.`repository` | string (ex. `/ba-custom-hashicorp-vault`) | Yes* | +| `create`.`image`.`tag` | `latest` | Yes* | +| `create`.`ingress`.`enabled` | `true` / `false` | Yes* | +| `create`.`ingress`.`host` | string (ex. `vault.`) | Yes** | +| `create`.`snapshotServer`.`enabled` | `true` / `false` | Yes* | +| `create`.`snapshotServer`.`externalPort` | number (ex. `81`) | Yes*** | +| `create`.`snapshotServer`.`internalPort` | number (ex. `8300`) | Yes*** | +| `create`.`snapshotServer`.`vaultCredsPVC`.`storageClassName` | string (ex. `vault-role-vars-rook-cephfs`) | Yes*** | +| `create`.`snapshotServer`.`vaultCredsPVC`.`size` | size string (ex. `512Mi`) | Yes*** | +| `create`.`appRole`.`roleIDSecretName` | string (ex. `VAULT_ROLE_ID`) | Yes* | +| `create`.`appRole`.`secretIDSecretName` | string (ex. `VAULT_SECRET_ID`) | Yes* | +| `create`.`roleVarsPVC`.`storageClassName` | string (ex. `vault-role-vars-rook-cephfs`) | Yes* | +| `create`.`roleVarsPVC`.`size` | size string (ex. `512Mi`) | Yes* | +| `create`.`vaultData`.`storageClassName` | string(ex. `rook-ceph-block`) | Yes* | +| `create`.`vaultData`.`accessModes` | array<`ReadWriteOnce`> | Yes* | +| `create`.`vaultData`.`size` | size string (ex. `2Gi`) | Yes* | + +`*` If `create`.`enabled` is `true` +`**` If `create`.`ingress`.`enabled` is `true` +`***` If `creat`.`snapshotServer`.`enabled` is `true` \ No newline at end of file diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl new file mode 100644 index 0000000..c6e6106 --- /dev/null +++ b/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "vault.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/vault-creds-persistant-volume-claim.yaml b/templates/vault-creds-persistant-volume-claim.yaml index a24bc41..65352b3 100644 --- a/templates/vault-creds-persistant-volume-claim.yaml +++ b/templates/vault-creds-persistant-volume-claim.yaml @@ -1,15 +1,15 @@ -{{- if .Values.vault.create.enabled -}} +{{- if .Values.create.enabled -}} apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-vault-creds + name: {{ include "vault.fullname" . }}-creds labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: - storageClassName: vault-role-vars-rook-cephfs + storageClassName: {{ .Values.create.snapshotServer.vaultCredsPVC.storageClassName }} accessModes: - ReadWriteMany resources: requests: - storage: 512Mi + storage: {{ .Values.create.snapshotServer.vaultCredsPVC.size }} {{- end -}} \ No newline at end of file diff --git a/templates/vault-hashicorp-secret.yaml b/templates/vault-hashicorp-secret.yaml index 90b200f..7d6d91d 100644 --- a/templates/vault-hashicorp-secret.yaml +++ b/templates/vault-hashicorp-secret.yaml @@ -1,24 +1,24 @@ -{{- if and (.Values.vault.enabled) (eq .Values.vault.type "hashicorp") -}} +{{- if and (.Values.enabled) (eq .Values.type "hashicorp") -}} apiVersion: v1 kind: Secret metadata: - name: {{ .Release.Name }}-vault-secret + name: {{ include "vault.fullname" . }}-secret type: opaque data: {{- if .Values.vault.create.enabled }} # Because we create the Hashicorp Vault instance as part of the Helm chart, # we can use the name of the created resource (utilizing k8s built-in container connections) # to connect to the Vault instance without having to hard-code the Vault name. - vault-name: {{ printf "%s-vault" .Release.Name | b64enc }} + vault-name: {{ include "vault.fullname" . | b64enc }} # Because we create the Hashicorp Vault instance as part of the Helm chart, # We know the port that the Vault instance is running on. vault-port: {{ printf "%d" 80 | b64enc }} {{- else }} # Because the Vault wasn't created as part of the Helm chart, # we need the deployer to specify the name of the Vault instance to connect to. - vault-name: {{ .Values.vault.vaultName | b64enc }} + vault-name: {{ .Values.vaultName | b64enc }} # Because the Vault wasn't created as part of the Helm chart, # we need the deployer to specify the port that the Vault instance is running on. - vault-port: {{ .Values.vault.vaultPort | b64enc }} + vault-port: {{ .Values.vaultPort | b64enc }} {{- end }} {{- end -}} \ No newline at end of file diff --git a/templates/vault-ingress.yaml b/templates/vault-ingress.yaml index 93496b6..545de72 100644 --- a/templates/vault-ingress.yaml +++ b/templates/vault-ingress.yaml @@ -1,21 +1,21 @@ -{{- if .Values.vault.create.ingress.enabled -}} +{{- if .Values.create.ingress.enabled -}} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ .Release.Name }}-vault-ingress + name: {{ include "vault.fullname" . }}-ingress labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: ingressClassName: nginx rules: - - host: {{ .Values.vault.create.ingress.host }} + - host: {{ .Values.create.ingress.host }} http: paths: - path: / pathType: Prefix backend: service: - name: {{ .Release.Name }}-vault + name: {{ include "vault.fullname" . }} port: number: 80 {{- end -}} \ No newline at end of file diff --git a/templates/vault-keyvault-secret.yaml b/templates/vault-keyvault-secret.yaml index ad1741e..b9ff6d1 100644 --- a/templates/vault-keyvault-secret.yaml +++ b/templates/vault-keyvault-secret.yaml @@ -1,12 +1,12 @@ -{{- if and (.Values.vault.enabled) (eq .Values.vault.type "azure") -}} +{{- if and (.Values.enabled) (eq .Values.vault.type "azure") -}} apiVersion: v1 kind: Secret metadata: - name: {{ .Release.Name }}-vault-secret + name: {{ include "vault.fullname" . }}-secret type: opaque data: - client-id: {{ .Values.vault.clientId | b64enc }} - client-secret: {{ .Values.vault.clientSecret | b64enc}} - name: {{ .Values.vault.vaultName | b64enc }} - tenant-id: {{ .Values.vault.tenantId | b64enc }} + client-id: {{ .Values.clientId | b64enc }} + client-secret: {{ .Values.clientSecret | b64enc}} + name: {{ .Values.vaultName | b64enc }} + tenant-id: {{ .Values.tenantId | b64enc }} {{- end -}} \ No newline at end of file diff --git a/templates/vault-role-vars-persistant-volume-claim.yaml b/templates/vault-role-vars-persistant-volume-claim.yaml index 400afd2..fcf3931 100644 --- a/templates/vault-role-vars-persistant-volume-claim.yaml +++ b/templates/vault-role-vars-persistant-volume-claim.yaml @@ -1,15 +1,15 @@ -{{- if .Values.vault.create.enabled -}} +{{- if .Values.create.enabled -}} apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-vault-role-vars + name: {{ include "vault.fullname" . }}-role-vars labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: - storageClassName: vault-role-vars-rook-cephfs + storageClassName: {{ .Values.create.roleVarsPVC.storageClassName }} accessModes: - ReadWriteMany resources: requests: - storage: 512Mi + storage: {{ .Values.create.roleVarsPVC.size }} {{- end -}} \ No newline at end of file diff --git a/templates/vault-service.yaml b/templates/vault-service.yaml index b515ec7..0da1eb3 100644 --- a/templates/vault-service.yaml +++ b/templates/vault-service.yaml @@ -1,19 +1,19 @@ -{{- if .Values.vault.create.enabled -}} +{{- if .Values.create.enabled -}} apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-vault + name: {{ include "vault.fullname" . }} labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: selector: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} ports: - {{- if .Values.vault.create.snapshotServer.enabled }} + {{- if .Values.create.snapshotServer.enabled }} - name: custom-snapshot-server protocol: TCP - port: {{ .Values.vault.create.snapshotServer.externalPort }} - targetPort: {{ .Values.vault.create.snapshotServer.internalPort }} + port: {{ .Values.create.snapshotServer.externalPort }} + targetPort: {{ .Values.create.snapshotServer.internalPort }} {{- end }} - name: http protocol: TCP diff --git a/templates/vault-snapshot-server-configmap.yaml b/templates/vault-snapshot-server-configmap.yaml index abb27ce..e211b7a 100644 --- a/templates/vault-snapshot-server-configmap.yaml +++ b/templates/vault-snapshot-server-configmap.yaml @@ -1,8 +1,8 @@ -{{- if .Values.vault.create.snapshotServer.enabled -}} +{{- if .Values.create.snapshotServer.enabled -}} apiVersion: v1 kind: ConfigMap metadata: - name: {{ .Release.Name }}-vault-snapshot-config + name: {{ include "vault.fullname" . }}-snapshot-config data: - port: {{ .Values.vault.create.snapshotServer.externalPort | quote }} + port: {{ .Values.create.snapshotServer.externalPort | quote }} {{- end -}} \ No newline at end of file diff --git a/templates/vault-statefulset.yaml b/templates/vault-statefulset.yaml index d5d4b15..b26751a 100644 --- a/templates/vault-statefulset.yaml +++ b/templates/vault-statefulset.yaml @@ -1,44 +1,44 @@ -{{- if and (.Values.vault.create.enabled) (eq .Values.vault.type "hashicorp") -}} +{{- if and (.Values.create.enabled) (eq .Values.type "hashicorp") -}} apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ .Release.Name }}-vault + name: {{ include "vault.fullname" . }} labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: - serviceName: {{ .Release.Name }}-vault + serviceName: {{ include "vault.fullname" . }} replicas: 1 selector: matchLabels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} template: metadata: labels: - app: {{ .Release.Name }}-vault + app: {{ include "vault.fullname" . }} spec: # Because the Vault process runs with a non-root user inside the container, # we need to set the fsGroup to ensure that the mounted volumes have the correct permissions securityContext: fsGroup: 1000 containers: - - name: {{ .Release.Name }}-vault - image: {{ .Values.vault.create.image.repository }}:{{ .Values.vault.create.image.tag }} + - name: {{ include "vault.fullname" . }} + image: {{ .Values.create.image.repository }}:{{ .Values.create.image.tag }} ports: - containerPort: 8200 - containerPort: 8201 - {{- if .Values.vault.create.snapshotServer.enabled }} - - containerPort: {{ .Values.vault.create.snapshotServer.internalPort }} + {{- if .Values.create.snapshotServer.enabled }} + - containerPort: {{ .Values.create.snapshotServer.internalPort }} {{- end }} env: - name: VAULT_ADDR value: http://0.0.0.0:8200 - name: ROLE_ID_SECRET_NAME - value: USER_PASSWORD_DEFAULT_VAULT_ROLE_ID + value: {{ .Values.create.appRole.roleIDSecretName }} - name: SECRET_ID_SECRET_NAME - value: USER_PASSWORD_DEFAULT_VAULT_SECRET_ID - {{- if .Values.vault.create.snapshotServer.enabled }} + value: {{ .Values.create.appRole.secretIDSecretName }} + {{- if .Values.create.snapshotServer.enabled }} - name: SNAPSHOT_SERVER_PORT - value: {{ .Values.vault.create.snapshotServer.internalPort | quote }} + value: {{ .Values.create.snapshotServer.internalPort | quote }} {{- end }} volumeMounts: - name: vault-data @@ -55,24 +55,24 @@ spec: - name: vault-log emptyDir: {} - name: vault-creds - {{- if .Values.vault.create.snapshotServer.enabled }} + {{- if .Values.create.snapshotServer.enabled }} persistentVolumeClaim: - claimName: {{ .Release.Name }}-vault-creds + claimName: {{ include "vault.fullname" . }}-creds {{- else }} emptyDir: {} {{- end }} - name: vault-role-vars persistentVolumeClaim: - claimName: {{ .Release.Name }}-vault-role-vars + claimName: {{ include "vault.fullname" . }}-role-vars # To have data consistency across pod restarts, we use a volume claim template # We do this instead of a static PVC because we require less control and it's easier to manage volumeClaimTemplates: - metadata: name: vault-data spec: - storageClassName: rook-ceph-block - accessModes: [ "ReadWriteOnce" ] + storageClassName: {{ .Values.create.vaultData.storageClassName }} + accessModes: {{ .Values.create.vaultData.accessModes }} resources: requests: - storage: 2Gi + storage: {{ .Values.create.vaultData.size }} {{- end -}} \ No newline at end of file diff --git a/values.yaml b/values.yaml index 93e8a85..935ac0b 100644 --- a/values.yaml +++ b/values.yaml @@ -1,95 +1,122 @@ +# ============================ # Configurations for the vault -vault: - # If a password "vault" should be used - # That is, if a dedicated software for secret management should be used - # This should virtually always be true as it's the most secure option +# ============================ + +# The type of secrets "vault" to use. +# +# Vaults +# ------ +# The following table lists the supported "vault" types: +# +# | Type | Description | Current Status | Required Fields | +# | ----------- | -------------------- | -------------- | --------------------------------------------------- | +# | `hashicorp` | Uses Hashicorp Vault | Implemented | `vaultName` (if `create` not true) | +# | `azure` | Uses Azure Key Vault | Implemented | `vaultName`, `clientId`, `clientSecret`, `tenantId` | +# +type: 'hashicorp' + +# The name of the vault instance to connect to +# +# This is relevant if type is set to `hashicorp` or `azure` +# Note, if `create` is true this is ignored +# +# For `hashicorp`, this is generally the hostname of the Hashicorp Vault instance to connect to +# For `azure`, this is the name of the Azure Key Vault instance to connect to +#vaultName: '' + +# The port of the vault instance to connect to +# +# ONLY RELEVANT iF `type` IS SET TO `hashicorp` AND `create` IS NOT TRUE +#vaultPort: 8200 + +# The client ID of the Azure Key Vault instance +# +# ONLY RELEVANT IF `type` IS SET TO `azure` +#clientID: "" + +# The client secret of the Azure Key Vault instance +# +# ONLY RELEVANT IF `type` IS SET TO `azure` +#clientSecret: "" + +# The tenant ID of the Azure Key Vault instance +# +# ONLY RELEVANT IF `type` IS SET TO `azure` +#tenantID: "" + +# Configurations to create a Hashicorp Vault instance as part of the Helm chart +# +# THIS IS ONLY RELEVANT IF `type` IS SET TO `hashicorp` +create: + # If a Hashicorp Vault instance should be created as part of the Helm chart enabled: true - # The type of password "vault" (or storage if `enabled` is `false`) to use. - # - # Vaults - # ------ - # The following table lists the supported "vault" types: - # - # | Type | Description | Current Status | Required Fields | - # | ----------- | -------------------- | -------------- | --------------------------------------------------- | - # | `hashicorp` | Uses Hashicorp Vault | Implemented | `vaultName` (if `create` not true) | - # | `azure` | Uses Azure Key Vault | Implemented | `vaultName`, `clientId`, `clientSecret`, `tenantId` | - # - # Storage - # ------- - # The following table lists the supported storage types. - # These are methods OUTSIDE of a dedicated "vault" software. - # These are generally **discouraged** as they are less secure. - # - # | Type | Description | Current Status | Required Fields | - # | ----------- | ------------------------------- | -------------- | ---------------- | - # | `file` | Uses a file | To-Do | `path` | - # | `mem` | Uses in-memory (no persistance) | To-Do | N/A | - # - type: 'hashicorp' + # Configurations for the image to use if creating the Hashicorp Vault instance + # as part of the Helm chart + image: + # The repository of the image to use + repository: /ba-custom-hashicorp-vault - # The name of the vault instance to connect to - # - # This is relevant if type is set to `hashicorp` or `azure` - # Note, if `create` is true this is ignored - # - # For `hashicorp`, this is generally the hostname of the Hashicorp Vault instance to connect to - # For `azure`, this is the name of the Azure Key Vault instance to connect to - #vaultName: '' - - # The port of the vault instance to connect to - # - # ONLY RELEVANT iF `type` IS SET TO `hashicorp` AND `create` IS NOT TRUE - #vaultPort: 8200 - - # The client ID of the Azure Key Vault instance - # - # ONLY RELEVANT IF `type` IS SET TO `azure` - #client-id: "" - - # The client secret of the Azure Key Vault instance - # - # ONLY RELEVANT IF `type` IS SET TO `azure` - #client-secret: "" - - # The tenant ID of the Azure Key Vault instance - # - # ONLY RELEVANT IF `type` IS SET TO `azure` - #tenant-id: "" - - # Configurations to create a Hashicorp Vault instance as part of the Helm chart - # - # THIS IS ONLY RELEVANT IF `type` IS SET TO `hashicorp` - create: - # If a Hashicorp Vault instance should be created as part of the Helm chart + # The tag of the image to use + tag: latest + + # Configurations for the ingress of the created Hashicorp Vault instance + ingress: + # If an ingress should be created for the created Hashicorp Vault instance enabled: true - # Configurations for the image to use if creating the Hashicorp Vault instance - # as part of the Helm chart - image: - # The repository of the image to use - repository: /ba-custom-hashicorp-vault - - # The tag of the image to use - tag: latest + # The host of the ingress for the created Hashicorp Vault instance + host: vault. - # Configurations for the ingress of the created Hashicorp Vault instance - ingress: - # If an ingress should be created for the created Hashicorp Vault instance - enabled: true + # As part of the custom Hashicorp Vault image it includes a "snapshot server" + # This allows for the triggering and receiving of manual backups ("snapshots") and restoration via HTTP + snapshotServer: + # If the snapshot server should be enabled/running + enabled: true - # The host of the ingress for the created Hashicorp Vault instance - host: vault. + # The external port that is opened via the service resource + externalPort: 81 + + # The internal port that the snapshot server listens on + internalPort: 8300 + + # Configurations for the `vault-creds` Persistent Volume Claim (PVC). + # The `vault-creds` PVC is used for the credentials used by the snapshot server to authenticate with Vault + vaultCredsPVC: + storageClassName: vault-role-vars-rook-cephfs + size: 512Mi + + # Configurations for the AppRole authentication method for the created Vault instance + appRole: + # The name of the environment variable/secret that contains the Role ID for the app + roleIDSecretName: VAULT_ROLE_ID + + # The name of the environment variable/secret that contains the Secret ID for the app + secretIDSecretName: VAULT_SECRET_ID + + # Configurations for the `role-vars` Persistent Volume Claim (PVC). + # The `role-vars` PVC is used for the app's AppRole auth access variables (role & secret IDs etc...) + roleVarsPVC: + # Because the PVC needs to be a RWX type volume (so that multiple pods can access it) + # Because the app and the vault are separate pods. + # We need to use a storage class that supports RWX (Custom create CephFS backed storage class) + storageClassName: vault-role-vars-rook-cephfs - # As part of the custom Hashicorp Vault image it includes a "snapshot server" - # This allows for the triggering and receiving of manual backups ("snapshots") and restoration via HTTP - snapshotServer: - # If the snapshot server should be enabled/running - enabled: true - - # The external port that is opened via the service resource - externalPort: 81 - - # The internal port that the snapshot server listens on - internalPort: 8300 \ No newline at end of file + # The size of the PVC (note because this is largely just credentials a small size is sufficient) + size: 512Mi + + # Configurations for the `vault-data` Persistent Volume Claim (PVC). + # The `vault-data` PVC is used for the Vault's data storage. + # In particular, a PVC allows data persistence across pod restarts. + vaultData: + # The storage class to use for the PVC + # Note, because there are no special requirements here we can use a standard RWO type volume + # Which means the default storage class (Rook Ceph Block) is sufficient + storageClassName: rook-ceph-block + + # The access modes for the PVC (shouldn't ever really need to be changed) + accessModes: + - ReadWriteOnce + + # The size of the PVC (Note, this should be sized according to expected usage) + size: 2Gi \ No newline at end of file