From 48fa1ee8127fc605e03c635f62c76ae57ac22061 Mon Sep 17 00:00:00 2001 From: David Blane Date: Sat, 5 Mar 2022 16:29:52 +0000 Subject: [PATCH 01/14] Integration for using vault injector via annotations --- charts/node/Chart.yaml | 2 +- charts/node/README.md | 16 +++++++-- charts/node/templates/statefulset.yaml | 48 +++++++++++++++++++++++++- charts/node/values.yaml | 16 +++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/charts/node/Chart.yaml b/charts/node/Chart.yaml index 4992f925..53c8bf5a 100644 --- a/charts/node/Chart.yaml +++ b/charts/node/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: node description: A Helm chart to deploy Substrate/Polkadot nodes type: application -version: 1.1.1 +version: 1.3.0 appVersion: "0.0.1" diff --git a/charts/node/README.md b/charts/node/README.md index fc316ca1..7e1eec01 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -22,6 +22,14 @@ helm install kusama-node parity/node --set node.chainDataSnapshotUrl=https://ksm ``` ⚠️ For some chains where the local directory name is different from the chain ID, `node.chainPath` needs to be set to a custom value. +### Vault prerequisities + +- Vault agent injector [installed](https://www.vaultproject.io/docs/platform/k8s/injector/installation) on the cluster +- Kubernetes [auth enabled](https://learn.hashicorp.com/tutorials/vault/kubernetes-sidecar#configure-kubernetes-authentication) in your vault instance +- Secrets for either the keys or the nodeKey created in your vault using kv-2 +- A policy for each of your secrets configured in your vault +- an authentication role crated in your vault instance (should match the serviceAccount name for this chart) with policies for accessing your keys attached + ## Parameters ### Common parameters @@ -35,7 +43,7 @@ helm install kusama-node parity/node --set node.chainDataSnapshotUrl=https://ksm | `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | | `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | | `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | -| `storaceClass` | The storage class to use for volumes | `default` | +| `storageClass` | The storage class to use for volumes | `default` | ### Node parameters @@ -44,9 +52,11 @@ helm install kusama-node parity/node --set node.chainDataSnapshotUrl=https://ksm | `node.chain` | Network to connect the node to (ie `--chain`) | `polkadot` | | `node.command` | Command to be invoked to launch the node binary | `polkadot` | | `node.flags` | Node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` (both set with `node.chain`) | `--prometheus-external --rpc-external --ws-external --rpc-cors all` | -| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }) | `{}` | +| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }), supercedes `node.vault.keys` | `{}` | +| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{ name, vaultPath, typeTarget, schemeTarget, seedTarget}) | `{}` | +| `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, keyTarget}) | `{}` | | `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | -| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key) | `nil` | +| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | | `node.enableStartupProbe` | If true, enable the startup probe check | `true` | | `node.enableReadinessProbe` | If true, enable the readiness probe check | `true` | | `node.dataVolumeSize` | The size of the chain data PersistentVolume | `100Gi` | diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 23fe7f51..a176d607 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -17,10 +17,31 @@ spec: serviceName: {{ $fullname }} template: metadata: - {{- with .Values.podAnnotations }} + {{- if or .Values.podAnnotations .Values.node.vault.keys .Values.node.vault.nodeKey }} annotations: + {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} + {{- range $keys := .Values.node.vault.keys }} + vault.hashicorp.com/agent-inject-secret-{{ .name }}: {{ .vaultPath | squote }} + vault.hashicorp.com/agent-inject-template-{{ .name }}: | + {{`{{ with secret "`}}{{ .vaultPath }}{{`" }}{{- range $k, $v := .Data.data }} + {{ $k }}: {{ $v }} + {{- end }}{{ end }}`}} + {{- end }} + {{- if or .Values.node.vault.keys .Values.node.vault.nodeKey }} + {{- if .Values.node.vault.nodeKey }} + vault.hashicorp.com/agent-inject-secret-{{ .Values.node.vault.nodeKey.name }}: {{ .Values.node.vault.nodeKey.vaultPath | squote }} + vault.hashicorp.com/agent-inject-template-{{ .Values.node.vault.nodeKey.name }}: | + {{`{{ with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }}{{- range $k, $v := .Data.data }} + {{ $k }}: {{ $v }} + {{- end }}{{ end }}`}} + {{- end }} + vault.hashicorp.com/agent-inject: 'true' + vault.hashicorp.com/agent-init-first: 'true' + vault.hashicorp.com/role: {{ include "node.serviceAccountName" . | squote }} + {{- end }} + {{- end }} labels: {{- include "node.labels" . | nindent 8 }} spec: @@ -212,6 +233,29 @@ spec: - mountPath: /var/run/secrets/{{ .type }} name: {{ .type }} {{- end }} + {{ else if .Values.node.vault.keys }} + - name: inject-vault-keys + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + command: [ "/bin/sh" ] + args: + - -c + - | + {{- range $keys := .Values.node.vault.keys }} + cat /vault/secrets/{{ .name }} + {{ $.Values.node.command }} key insert --base-path /data \ + --chain ${CHAIN} \ + --key-type $(awk '/{{ .typeTarget }}/ {print $2}' /vault/secrets/{{ .name }}) \ + --scheme $(awk '/{{ .schemeTarget }}/ {print $2}' /vault/secrets/{{ .name }}) \ + --suri "$(awk '/{{ .seedTarget }}/ { $1=""; print}' /vault/secrets/{{ .name }} | cut -c 2-)" \ + && echo "Inserted key {{ .name }} into Keystore" \ + || echo "Failed to insert key {{ .name}} into Keystore." + {{- end }} + env: + - name: CHAIN + value: {{ .Values.node.chain }} + volumeMounts: + - mountPath: /data + name: chain-data {{- end }} {{- if .Values.node.perNodeServices.createP2pNodePortService }} - name: retrieve-node-port @@ -284,6 +328,8 @@ spec: --node-key-file /data/node-key \ {{- else if .Values.node.customNodeKey }} --node-key $(cat /tmp/custom-node-key) \ + {{- else if .Values.node.vault.nodeKey }} + --node-key $(awk '/{{ .Values.node.vault.nodeKey.keyTarget }}/ {print $2}' /vault/secrets/{{ .Values.node.vault.nodeKey.name }}) \ {{- end }} {{- if .Values.node.tracing.enabled }} --jaeger-agent=127.0.0.1:{{ .Values.jaegerAgent.ports.compactPort }} \ diff --git a/charts/node/values.yaml b/charts/node/values.yaml index 01fe2633..e86abb42 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -96,6 +96,22 @@ node: # - type: "babe" # scheme: "sr25519" # seed: "//Alice//babe" + vault: + keys: {} + # - name: grankey + # vaultPath: secret/grankey + # typeTarget: type + # schemeTarget: scheme + # seedTarget: seed + # - name: babekey + # vaultPath: secrets/babeKey + # typeTarget: type + # schemeTarget: scheme + # seedTarget: seed + nodeKey: {} + # name: nodekey + # vaultPath: secret/nodekey + # keyTarget: key persistGeneratedNodeKey: false #customNodeKey: "" resources: {} From 97f6a1ab99f4a23728bf6f851b28c8be339d28ce Mon Sep 17 00:00:00 2001 From: David Blane Date: Sat, 5 Mar 2022 16:37:48 +0000 Subject: [PATCH 02/14] Remove debugging step --- charts/node/templates/statefulset.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 035af51b..74e4d23d 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -241,7 +241,6 @@ spec: - -c - | {{- range $keys := .Values.node.vault.keys }} - cat /vault/secrets/{{ .name }} {{ $.Values.node.command }} key insert --base-path /data \ --chain ${CHAIN} \ --key-type $(awk '/{{ .typeTarget }}/ {print $2}' /vault/secrets/{{ .name }}) \ From 474407c1e13a61b6ab0bc83cdd8f8e78ede7f660 Mon Sep 17 00:00:00 2001 From: David Blane Date: Sat, 5 Mar 2022 16:45:05 +0000 Subject: [PATCH 03/14] Readme improvement --- charts/node/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/node/README.md b/charts/node/README.md index c97ff408..c0d003e2 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -22,8 +22,8 @@ helm install kusama-node parity/node --set node.chainDataSnapshotUrl=https://ksm ``` ⚠️ For some chains where the local directory name is different from the chain ID, `node.chainPath` needs to be set to a custom value. -### Vault prerequisities - +### Optional Vault Integration +To integrate this chart with vault: - Vault agent injector [installed](https://www.vaultproject.io/docs/platform/k8s/injector/installation) on the cluster - Kubernetes [auth enabled](https://learn.hashicorp.com/tutorials/vault/kubernetes-sidecar#configure-kubernetes-authentication) in your vault instance - Secrets for either the keys or the nodeKey created in your vault using kv-2 From 29fb31df0cde0c3e2631f7049a26839ee0e9eae9 Mon Sep 17 00:00:00 2001 From: Anthony Lazam Date: Mon, 7 Mar 2022 17:51:11 +0800 Subject: [PATCH 04/14] Include extra labels for service monitor --- charts/node/templates/serviceMonitor.yaml | 7 ++++--- charts/node/values.yaml | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/charts/node/templates/serviceMonitor.yaml b/charts/node/templates/serviceMonitor.yaml index 3265d743..3cfebdf9 100644 --- a/charts/node/templates/serviceMonitor.yaml +++ b/charts/node/templates/serviceMonitor.yaml @@ -28,7 +28,8 @@ spec: namespaceSelector: matchNames: - {{ $.Release.Namespace }} + {{- with $.Values.node.serviceMonitor.targetLabels }} targetLabels: - - chain - - instance -{{- end }} + {{ toYaml .| nindent 4 }} + {{- end}} +{{- end }} \ No newline at end of file diff --git a/charts/node/values.yaml b/charts/node/values.yaml index ffd107ae..2fbbf872 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -118,8 +118,11 @@ node: serviceMonitor: enabled: false #namespace: monitoring - #interval: 10s - # scrapeTimeout: 10s + interval: 1m + scrapeTimeout: 30s + targetLabels: + - chain + - instance perNodeServices: createClusterIPService: true createP2pNodePortService: false From 64a6e171af736db25fef9318e12927906cff7b41 Mon Sep 17 00:00:00 2001 From: Anthony Lazam Date: Mon, 7 Mar 2022 20:51:46 +0800 Subject: [PATCH 05/14] Replaced instance by node --- charts/node/values.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/node/values.yaml b/charts/node/values.yaml index 2fbbf872..787da6d7 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -122,7 +122,7 @@ node: scrapeTimeout: 30s targetLabels: - chain - - instance + - node perNodeServices: createClusterIPService: true createP2pNodePortService: false @@ -180,4 +180,4 @@ affinity: {} storageClass: "default" -extraContainers: [] \ No newline at end of file +extraContainers: [] From a8c1050f26004abc3a8dd63f6886a7f063c746c3 Mon Sep 17 00:00:00 2001 From: Anthony Lazam Date: Tue, 8 Mar 2022 11:25:53 +0800 Subject: [PATCH 06/14] Added honorlabels in servicemonitor --- charts/node/README.md | 1 + charts/node/templates/serviceMonitor.yaml | 1 + charts/node/values.yaml | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/node/README.md b/charts/node/README.md index c0d003e2..0514d832 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -83,6 +83,7 @@ To integrate this chart with vault: | `node.serviceMonitor.namespace` | Prometheus namespace | `nil` | | `node.serviceMonitor.internal` | Prometheus scrape interval | `nil` | | `node.serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `nil` | +| `node.serviceMonitor.targetLabels` | transfers labels on the Kubernetes Pod onto service monitor | `[nodes]` | | `node.tracing.enabled` | If true, creates a jaeger agent sidecar | `false` | | `node.subtrateApiSiecar.enabled` | If true, creates a substrate api sidecar | `false` | | `node.perNodeServices.createClusterIPService` | If true creates a clusterIP API service | `true` | diff --git a/charts/node/templates/serviceMonitor.yaml b/charts/node/templates/serviceMonitor.yaml index 3cfebdf9..309a4788 100644 --- a/charts/node/templates/serviceMonitor.yaml +++ b/charts/node/templates/serviceMonitor.yaml @@ -24,6 +24,7 @@ spec: {{- end }} {{- if $.Values.node.serviceMonitor.scrapeTimeout }} scrapeTimeout: {{ $.Values.node.serviceMonitor.scrapeTimeout }} + honorLabels: true {{- end }} namespaceSelector: matchNames: diff --git a/charts/node/values.yaml b/charts/node/values.yaml index 787da6d7..d17a1c41 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -121,7 +121,6 @@ node: interval: 1m scrapeTimeout: 30s targetLabels: - - chain - node perNodeServices: createClusterIPService: true From 1a81911c734e5c42a0c2d23ac43770f128ef4235 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 17:24:29 +0100 Subject: [PATCH 07/14] add additional vault config values to make it compatible with gcp service account auth --- charts/node/README.md | 97 ++++++++++++++------------ charts/node/templates/statefulset.yaml | 15 +++- charts/node/values.yaml | 5 ++ 3 files changed, 70 insertions(+), 47 deletions(-) diff --git a/charts/node/README.md b/charts/node/README.md index 0514d832..ef3becb6 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -47,51 +47,56 @@ To integrate this chart with vault: ### Node parameters -| Parameter | Description | Default | -|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| -| `node.chain` | Network to connect the node to (ie `--chain`) | `polkadot` | -| `node.command` | Command to be invoked to launch the node binary | `polkadot` | -| `node.flags` | Node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` (both set with `node.chain`) | `--prometheus-external --rpc-external --ws-external --rpc-cors all` | -| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }), supercedes `node.vault.keys` | `{}` | -| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{ name, vaultPath, typeTarget, schemeTarget, seedTarget}) | `{}` | -| `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, keyTarget}) | `{}` | -| `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | -| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | -| `node.enableStartupProbe` | If true, enable the startup probe check | `true` | -| `node.enableReadinessProbe` | If true, enable the readiness probe check | `true` | -| `node.dataVolumeSize` | The size of the chain data PersistentVolume | `100Gi` | -| `node.replica` | Number of replica in the node StatefulSet | `1` | -| `node.role` | Set the role of the node: `full`, `authority`/`validator`, `collator` or `light` | `full` | -| `node.chainDataSnapshotUrl` | Download and load chain data from a snapshot archive http URL | `` | -| `node.chainDataSnapshotFormat` | The snapshot archive format (`tar` or `7z`) | `tar` | -| `node.chainDataGcsBucketUrl` | Sync chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `` | -| `node.chainPath` | Path at which the chain database files are located (`/data/chains/${CHAIN_PATH}`) | `nil` (if undefined, fallbacks to the value in `node.chain`) | -| `node.chainDataKubernetesVolumeSnapshot` | Initialize the chain data volume from a Kubernetes VolumeSnapshot | `` | -| `node.customChainspecUrl` | Download and use a custom chainspec file from a URL | `nil` | -| `node.collator.isParachain` | If true, configure the node as a parachain (set the relay-chain flags after `--`) | `nil` | -| `node.collator.relayChainCustomChainspecUrl` | Download and use a custom relay-chain chainspec file from a URL | `nil` | -| `node.collator.relayChainDataSnapshotUrl` | Download and load relay-chain data from a snapshot archive http URL | `nil` | -| `node.collator.relayChainDataSnapshotFormat` | The relay-chain snapshot archive format (`tar` or `7z`) | `nil` | -| `node.collator.relayChainPath` | Path at which the chain database files are located (`/data/polkadot/chains/${RELAY_CHAIN_PATH}`) | `nil` | -| `node.collator.relayChainDataKubernetesVolumeSnapshot` | Initialize the relay-chain data volume from a Kubernetes VolumeSnapshot | `nil` | -| `node.collator.relayChainDataGcsBucketUrl` | Sync relay-chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `nil` | -| `node.collator.relayChainFlags` | Relay-chain node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` | `nil` | -| `node.resources.limits` | The resources limits (cpu/memory) for nodes | `{}` | -| `node.podManagementPolicy` | The pod management policy to apply to the StatefulSet, set it to `Parallel` to launch or terminate all Pods in parallel, and not to wait for pods to become Running and Ready or completely terminated prior to launching or terminating another pod | `{}` | -| `node.resources.requests` | The resources requests (cpu/memory) for nodes | `{}` | -| `node.serviceMonitor.enabled` | If true, creates a Prometheus Operator ServiceMonitor | `false` | -| `node.serviceMonitor.namespace` | Prometheus namespace | `nil` | -| `node.serviceMonitor.internal` | Prometheus scrape interval | `nil` | -| `node.serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `nil` | -| `node.serviceMonitor.targetLabels` | transfers labels on the Kubernetes Pod onto service monitor | `[nodes]` | -| `node.tracing.enabled` | If true, creates a jaeger agent sidecar | `false` | -| `node.subtrateApiSiecar.enabled` | If true, creates a substrate api sidecar | `false` | -| `node.perNodeServices.createClusterIPService` | If true creates a clusterIP API service | `true` | -| `node.perNodeServices.createP2pNodePortService` | If true creates a p2p NodePort service, if `node.collator.isParachain` also true, creates a NodePort p2p service for the parachain | `false` | -| `node.perNodeServices.relayServiceAnnotations` | Annotations to be inserted into the relay chain service | `{}` | -| `node.perNodeServices.paraServiceAnnotations` | Annotations to be inserted into the para chain service | `{}` | -| `node.perNodeServices.setPublicAddressToExternalIp.enabled` | If true sets the `--public-addr` flag to be the NodePort p2p services external address | `false` | -| `node.perNodeServices.setPublicAddressToExternalIP.ipRetrievalServiceUrl` | The external service to return the NodePort IP | `https://ifconfig.io` | +| Parameter | Description | Default | +|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `node.chain` | Network to connect the node to (ie `--chain`) | `polkadot` | +| `node.command` | Command to be invoked to launch the node binary | `polkadot` | +| `node.flags` | Node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` (both set with `node.chain`) | `--prometheus-external --rpc-external --ws-external --rpc-cors all` | +| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }), supercedes `node.vault.keys` | `{}` | +| `node.vault.authPath` | Set the vault-agent authentication path (defaults to `auth/kubernetes`) | `nil` | +| `node.vault.authRole` | Set the vault role to be used by the vault-agent (defaults to the service account name) | `nil` | +| `node.vault.authType` | Set the vault-agent authentication type (defaults to `kubernetes` when not set) | `nil` | +| `node.vault.authConfigType` | Set the vault-agent authentication additional `type` parameter | `nil` | +| `node.vault.authConfigServiceAccount` | Set the vault-agent authentication additional `service-account` parameter | `nil` | +| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{ name, vaultPath, typeTarget, schemeTarget, seedTarget}) | `{}` | +| `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, keyTarget}) | `{}` | +| `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | +| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | +| `node.enableStartupProbe` | If true, enable the startup probe check | `true` | +| `node.enableReadinessProbe` | If true, enable the readiness probe check | `true` | +| `node.dataVolumeSize` | The size of the chain data PersistentVolume | `100Gi` | +| `node.replica` | Number of replica in the node StatefulSet | `1` | +| `node.role` | Set the role of the node: `full`, `authority`/`validator`, `collator` or `light` | `full` | +| `node.chainDataSnapshotUrl` | Download and load chain data from a snapshot archive http URL | `` | +| `node.chainDataSnapshotFormat` | The snapshot archive format (`tar` or `7z`) | `tar` | +| `node.chainDataGcsBucketUrl` | Sync chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `` | +| `node.chainPath` | Path at which the chain database files are located (`/data/chains/${CHAIN_PATH}`) | `nil` (if undefined, fallbacks to the value in `node.chain`) | +| `node.chainDataKubernetesVolumeSnapshot` | Initialize the chain data volume from a Kubernetes VolumeSnapshot | `` | +| `node.customChainspecUrl` | Download and use a custom chainspec file from a URL | `nil` | +| `node.collator.isParachain` | If true, configure the node as a parachain (set the relay-chain flags after `--`) | `nil` | +| `node.collator.relayChainCustomChainspecUrl` | Download and use a custom relay-chain chainspec file from a URL | `nil` | +| `node.collator.relayChainDataSnapshotUrl` | Download and load relay-chain data from a snapshot archive http URL | `nil` | +| `node.collator.relayChainDataSnapshotFormat` | The relay-chain snapshot archive format (`tar` or `7z`) | `nil` | +| `node.collator.relayChainPath` | Path at which the chain database files are located (`/data/polkadot/chains/${RELAY_CHAIN_PATH}`) | `nil` | +| `node.collator.relayChainDataKubernetesVolumeSnapshot` | Initialize the relay-chain data volume from a Kubernetes VolumeSnapshot | `nil` | +| `node.collator.relayChainDataGcsBucketUrl` | Sync relay-chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `nil` | +| `node.collator.relayChainFlags` | Relay-chain node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` | `nil` | +| `node.resources.limits` | The resources limits (cpu/memory) for nodes | `{}` | +| `node.podManagementPolicy` | The pod management policy to apply to the StatefulSet, set it to `Parallel` to launch or terminate all Pods in parallel, and not to wait for pods to become Running and Ready or completely terminated prior to launching or terminating another pod | `{}` | +| `node.resources.requests` | The resources requests (cpu/memory) for nodes | `{}` | +| `node.serviceMonitor.enabled` | If true, creates a Prometheus Operator ServiceMonitor | `false` | +| `node.serviceMonitor.namespace` | Prometheus namespace | `nil` | +| `node.serviceMonitor.internal` | Prometheus scrape interval | `nil` | +| `node.serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `nil` | +| `node.serviceMonitor.targetLabels` | transfers labels on the Kubernetes Pod onto service monitor | `[nodes]` | +| `node.tracing.enabled` | If true, creates a jaeger agent sidecar | `false` | +| `node.subtrateApiSiecar.enabled` | If true, creates a substrate api sidecar | `false` | +| `node.perNodeServices.createClusterIPService` | If true creates a clusterIP API service | `true` | +| `node.perNodeServices.createP2pNodePortService` | If true creates a p2p NodePort service, if `node.collator.isParachain` also true, creates a NodePort p2p service for the parachain | `false` | +| `node.perNodeServices.relayServiceAnnotations` | Annotations to be inserted into the relay chain service | `{}` | +| `node.perNodeServices.paraServiceAnnotations` | Annotations to be inserted into the para chain service | `{}` | +| `node.perNodeServices.setPublicAddressToExternalIp.enabled` | If true sets the `--public-addr` flag to be the NodePort p2p services external address | `false` | +| `node.perNodeServices.setPublicAddressToExternalIP.ipRetrievalServiceUrl` | The external service to return the NodePort IP | `https://ifconfig.io` | ### Other parameters @@ -117,4 +122,4 @@ To integrate this chart with vault: | `jaegerAgent.ports.samplingPort` | Port for HTTP sampling strategies | `5778` | | `jaegerAgent.collector.url` | The URL which jaeger agent sends data | `nil` | | `jaegerAgent.collector.port ` | The port which jaeger agent sends data | `14250` | -| `extraContainers ` | Sidecar containers to add to the node | `[]` | \ No newline at end of file +| `extraContainers ` | Sidecar containers to add to the node | `[]` | diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 74e4d23d..32f3f1da 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -39,7 +39,20 @@ spec: {{- end }} vault.hashicorp.com/agent-inject: 'true' vault.hashicorp.com/agent-init-first: 'true' - vault.hashicorp.com/role: {{ include "node.serviceAccountName" . | squote }} + vault.hashicorp.com/agent-pre-populate-only: 'true' + vault.hashicorp.com/role: {{ .Values.node.vault.authRole | default (include "node.serviceAccountName" .) | squote }} + {{- end }} + {{- if .Values.node.vault.authType }} + vault.hashicorp.com/auth-type: {{ .Values.node.vault.authType | squote }} + {{- end }} + {{- if .Values.node.vault.authPath }} + vault.hashicorp.com/auth-path: {{ .Values.node.vault.authPath | squote }} + {{- end }} + {{- if .Values.node.vault.authConfigType }} + vault.hashicorp.com/auth-config-type: {{ .Values.node.vault.authConfigType | squote }} + {{- end }} + {{- if .Values.node.vault.authConfigServiceAccount }} + vault.hashicorp.com/auth-config-service-account: {{ .Values.node.vault.authConfigServiceAccount | squote }} {{- end }} {{- end }} labels: diff --git a/charts/node/values.yaml b/charts/node/values.yaml index d17a1c41..3e7d8978 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -97,6 +97,11 @@ node: # scheme: "sr25519" # seed: "//Alice//babe" vault: + #authPath: "" + #authRole: "" + #authType: "" + #authConfigType: "" + #authConfigServiceAccount: "" keys: {} # - name: grankey # vaultPath: secret/grankey From e848cd5db6028c18344be4f37475eefb95ec9f5d Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 18:18:02 +0100 Subject: [PATCH 08/14] inject nodekey secret from vault into a file which is then passed to the node-key flag --- charts/node/templates/statefulset.yaml | 8 ++++---- charts/node/values.yaml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 32f3f1da..0e67d1fa 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -33,9 +33,9 @@ spec: {{- if .Values.node.vault.nodeKey }} vault.hashicorp.com/agent-inject-secret-{{ .Values.node.vault.nodeKey.name }}: {{ .Values.node.vault.nodeKey.vaultPath | squote }} vault.hashicorp.com/agent-inject-template-{{ .Values.node.vault.nodeKey.name }}: | - {{`{{ with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }}{{- range $k, $v := .Data.data }} - {{ $k }}: {{ $v }} - {{- end }}{{ end }}`}} + {{`{{- with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }} + {{ index .Data.data.`}}{{ .Values.node.vault.nodeKey.keyTarget }}{{` }} + {{- end }}`}} {{- end }} vault.hashicorp.com/agent-inject: 'true' vault.hashicorp.com/agent-init-first: 'true' @@ -341,7 +341,7 @@ spec: {{- else if .Values.node.customNodeKey }} --node-key $(cat /tmp/custom-node-key) \ {{- else if .Values.node.vault.nodeKey }} - --node-key $(awk '/{{ .Values.node.vault.nodeKey.keyTarget }}/ {print $2}' /vault/secrets/{{ .Values.node.vault.nodeKey.name }}) \ + --node-key $(cat /vault/secrets/{{ .Values.node.vault.nodeKey.name }}) \ {{- end }} {{- if .Values.node.tracing.enabled }} --jaeger-agent=127.0.0.1:{{ .Values.jaegerAgent.ports.compactPort }} \ diff --git a/charts/node/values.yaml b/charts/node/values.yaml index 3e7d8978..13ac5b5f 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -116,6 +116,7 @@ node: nodeKey: {} # name: nodekey # vaultPath: secret/nodekey + # remark: keyTarget cannot contain dashes ('-'), only alphanumeric characters due to a limitation in the go templating # keyTarget: key persistGeneratedNodeKey: false #customNodeKey: "" From a44c80c2979c8a6c94a00143b457eab217773591 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 18:40:57 +0100 Subject: [PATCH 09/14] inject seed keys secret from vault into files on init replacing awk queries to extract it from YAML files --- charts/node/README.md | 98 +++++++++++++------------- charts/node/templates/statefulset.yaml | 18 ++--- charts/node/values.yaml | 16 ++--- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/charts/node/README.md b/charts/node/README.md index ef3becb6..d731a14e 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -47,56 +47,56 @@ To integrate this chart with vault: ### Node parameters -| Parameter | Description | Default | -|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| -| `node.chain` | Network to connect the node to (ie `--chain`) | `polkadot` | -| `node.command` | Command to be invoked to launch the node binary | `polkadot` | -| `node.flags` | Node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` (both set with `node.chain`) | `--prometheus-external --rpc-external --ws-external --rpc-cors all` | -| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }), supercedes `node.vault.keys` | `{}` | -| `node.vault.authPath` | Set the vault-agent authentication path (defaults to `auth/kubernetes`) | `nil` | -| `node.vault.authRole` | Set the vault role to be used by the vault-agent (defaults to the service account name) | `nil` | -| `node.vault.authType` | Set the vault-agent authentication type (defaults to `kubernetes` when not set) | `nil` | -| `node.vault.authConfigType` | Set the vault-agent authentication additional `type` parameter | `nil` | -| `node.vault.authConfigServiceAccount` | Set the vault-agent authentication additional `service-account` parameter | `nil` | -| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{ name, vaultPath, typeTarget, schemeTarget, seedTarget}) | `{}` | -| `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, keyTarget}) | `{}` | -| `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | -| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | -| `node.enableStartupProbe` | If true, enable the startup probe check | `true` | -| `node.enableReadinessProbe` | If true, enable the readiness probe check | `true` | -| `node.dataVolumeSize` | The size of the chain data PersistentVolume | `100Gi` | -| `node.replica` | Number of replica in the node StatefulSet | `1` | -| `node.role` | Set the role of the node: `full`, `authority`/`validator`, `collator` or `light` | `full` | -| `node.chainDataSnapshotUrl` | Download and load chain data from a snapshot archive http URL | `` | -| `node.chainDataSnapshotFormat` | The snapshot archive format (`tar` or `7z`) | `tar` | -| `node.chainDataGcsBucketUrl` | Sync chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `` | -| `node.chainPath` | Path at which the chain database files are located (`/data/chains/${CHAIN_PATH}`) | `nil` (if undefined, fallbacks to the value in `node.chain`) | -| `node.chainDataKubernetesVolumeSnapshot` | Initialize the chain data volume from a Kubernetes VolumeSnapshot | `` | -| `node.customChainspecUrl` | Download and use a custom chainspec file from a URL | `nil` | -| `node.collator.isParachain` | If true, configure the node as a parachain (set the relay-chain flags after `--`) | `nil` | -| `node.collator.relayChainCustomChainspecUrl` | Download and use a custom relay-chain chainspec file from a URL | `nil` | -| `node.collator.relayChainDataSnapshotUrl` | Download and load relay-chain data from a snapshot archive http URL | `nil` | -| `node.collator.relayChainDataSnapshotFormat` | The relay-chain snapshot archive format (`tar` or `7z`) | `nil` | -| `node.collator.relayChainPath` | Path at which the chain database files are located (`/data/polkadot/chains/${RELAY_CHAIN_PATH}`) | `nil` | -| `node.collator.relayChainDataKubernetesVolumeSnapshot` | Initialize the relay-chain data volume from a Kubernetes VolumeSnapshot | `nil` | -| `node.collator.relayChainDataGcsBucketUrl` | Sync relay-chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `nil` | -| `node.collator.relayChainFlags` | Relay-chain node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` | `nil` | -| `node.resources.limits` | The resources limits (cpu/memory) for nodes | `{}` | +| Parameter | Description | Default | +|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `node.chain` | Network to connect the node to (ie `--chain`) | `polkadot` | +| `node.command` | Command to be invoked to launch the node binary | `polkadot` | +| `node.flags` | Node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` (both set with `node.chain`) | `--prometheus-external --rpc-external --ws-external --rpc-cors all` | +| `node.keys` | The list of keys to inject on the node before startup (object{ type, scheme, seed }), supercedes `node.vault.keys` | `{}` | +| `node.vault.authPath` | Set the vault-agent authentication path (defaults to `auth/kubernetes`) | `nil` | +| `node.vault.authRole` | Set the vault role to be used by the vault-agent (defaults to the service account name) | `nil` | +| `node.vault.authType` | Set the vault-agent authentication type (defaults to `kubernetes` when not set) | `nil` | +| `node.vault.authConfigType` | Set the vault-agent authentication additional `type` parameter | `nil` | +| `node.vault.authConfigServiceAccount` | Set the vault-agent authentication additional `service-account` parameter | `nil` | +| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{name, vaultPath, vaultKey, scheme, type}) | `{}` | +| `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, vaultKey}) | `{}` | +| `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | +| `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | +| `node.enableStartupProbe` | If true, enable the startup probe check | `true` | +| `node.enableReadinessProbe` | If true, enable the readiness probe check | `true` | +| `node.dataVolumeSize` | The size of the chain data PersistentVolume | `100Gi` | +| `node.replica` | Number of replica in the node StatefulSet | `1` | +| `node.role` | Set the role of the node: `full`, `authority`/`validator`, `collator` or `light` | `full` | +| `node.chainDataSnapshotUrl` | Download and load chain data from a snapshot archive http URL | `` | +| `node.chainDataSnapshotFormat` | The snapshot archive format (`tar` or `7z`) | `tar` | +| `node.chainDataGcsBucketUrl` | Sync chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `` | +| `node.chainPath` | Path at which the chain database files are located (`/data/chains/${CHAIN_PATH}`) | `nil` (if undefined, fallbacks to the value in `node.chain`) | +| `node.chainDataKubernetesVolumeSnapshot` | Initialize the chain data volume from a Kubernetes VolumeSnapshot | `` | +| `node.customChainspecUrl` | Download and use a custom chainspec file from a URL | `nil` | +| `node.collator.isParachain` | If true, configure the node as a parachain (set the relay-chain flags after `--`) | `nil` | +| `node.collator.relayChainCustomChainspecUrl` | Download and use a custom relay-chain chainspec file from a URL | `nil` | +| `node.collator.relayChainDataSnapshotUrl` | Download and load relay-chain data from a snapshot archive http URL | `nil` | +| `node.collator.relayChainDataSnapshotFormat` | The relay-chain snapshot archive format (`tar` or `7z`) | `nil` | +| `node.collator.relayChainPath` | Path at which the chain database files are located (`/data/polkadot/chains/${RELAY_CHAIN_PATH}`) | `nil` | +| `node.collator.relayChainDataKubernetesVolumeSnapshot` | Initialize the relay-chain data volume from a Kubernetes VolumeSnapshot | `nil` | +| `node.collator.relayChainDataGcsBucketUrl` | Sync relay-chain data files from a GCS bucket (eg. `gs://bucket-name/folder-name`) | `nil` | +| `node.collator.relayChainFlags` | Relay-chain node flags other than `--name` (set from the helm release name), `--base-path` and `--chain` | `nil` | +| `node.resources.limits` | The resources limits (cpu/memory) for nodes | `{}` | | `node.podManagementPolicy` | The pod management policy to apply to the StatefulSet, set it to `Parallel` to launch or terminate all Pods in parallel, and not to wait for pods to become Running and Ready or completely terminated prior to launching or terminating another pod | `{}` | -| `node.resources.requests` | The resources requests (cpu/memory) for nodes | `{}` | -| `node.serviceMonitor.enabled` | If true, creates a Prometheus Operator ServiceMonitor | `false` | -| `node.serviceMonitor.namespace` | Prometheus namespace | `nil` | -| `node.serviceMonitor.internal` | Prometheus scrape interval | `nil` | -| `node.serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `nil` | -| `node.serviceMonitor.targetLabels` | transfers labels on the Kubernetes Pod onto service monitor | `[nodes]` | -| `node.tracing.enabled` | If true, creates a jaeger agent sidecar | `false` | -| `node.subtrateApiSiecar.enabled` | If true, creates a substrate api sidecar | `false` | -| `node.perNodeServices.createClusterIPService` | If true creates a clusterIP API service | `true` | -| `node.perNodeServices.createP2pNodePortService` | If true creates a p2p NodePort service, if `node.collator.isParachain` also true, creates a NodePort p2p service for the parachain | `false` | -| `node.perNodeServices.relayServiceAnnotations` | Annotations to be inserted into the relay chain service | `{}` | -| `node.perNodeServices.paraServiceAnnotations` | Annotations to be inserted into the para chain service | `{}` | -| `node.perNodeServices.setPublicAddressToExternalIp.enabled` | If true sets the `--public-addr` flag to be the NodePort p2p services external address | `false` | -| `node.perNodeServices.setPublicAddressToExternalIP.ipRetrievalServiceUrl` | The external service to return the NodePort IP | `https://ifconfig.io` | +| `node.resources.requests` | The resources requests (cpu/memory) for nodes | `{}` | +| `node.serviceMonitor.enabled` | If true, creates a Prometheus Operator ServiceMonitor | `false` | +| `node.serviceMonitor.namespace` | Prometheus namespace | `nil` | +| `node.serviceMonitor.internal` | Prometheus scrape interval | `nil` | +| `node.serviceMonitor.scrapeTimeout` | Prometheus scrape timeout | `nil` | +| `node.serviceMonitor.targetLabels` | transfers labels on the Kubernetes Pod onto service monitor | `[nodes]` | +| `node.tracing.enabled` | If true, creates a jaeger agent sidecar | `false` | +| `node.subtrateApiSiecar.enabled` | If true, creates a substrate api sidecar | `false` | +| `node.perNodeServices.createClusterIPService` | If true creates a clusterIP API service | `true` | +| `node.perNodeServices.createP2pNodePortService` | If true creates a p2p NodePort service, if `node.collator.isParachain` also true, creates a NodePort p2p service for the parachain | `false` | +| `node.perNodeServices.relayServiceAnnotations` | Annotations to be inserted into the relay chain service | `{}` | +| `node.perNodeServices.paraServiceAnnotations` | Annotations to be inserted into the para chain service | `{}` | +| `node.perNodeServices.setPublicAddressToExternalIp.enabled` | If true sets the `--public-addr` flag to be the NodePort p2p services external address | `false` | +| `node.perNodeServices.setPublicAddressToExternalIP.ipRetrievalServiceUrl` | The external service to return the NodePort IP | `https://ifconfig.io` | ### Other parameters diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 0e67d1fa..02abdab2 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -25,16 +25,16 @@ spec: {{- range $keys := .Values.node.vault.keys }} vault.hashicorp.com/agent-inject-secret-{{ .name }}: {{ .vaultPath | squote }} vault.hashicorp.com/agent-inject-template-{{ .name }}: | - {{`{{ with secret "`}}{{ .vaultPath }}{{`" }}{{- range $k, $v := .Data.data }} - {{ $k }}: {{ $v }} - {{- end }}{{ end }}`}} + {{`{{- with secret "`}}{{ .vaultPath }}{{`" }} + {{ .Data.data.`}}{{ .vaultKey }}{{` }} + {{- end }}`}} {{- end }} {{- if or .Values.node.vault.keys .Values.node.vault.nodeKey }} {{- if .Values.node.vault.nodeKey }} vault.hashicorp.com/agent-inject-secret-{{ .Values.node.vault.nodeKey.name }}: {{ .Values.node.vault.nodeKey.vaultPath | squote }} vault.hashicorp.com/agent-inject-template-{{ .Values.node.vault.nodeKey.name }}: | {{`{{- with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }} - {{ index .Data.data.`}}{{ .Values.node.vault.nodeKey.keyTarget }}{{` }} + {{ .Data.data.`}}{{ .Values.node.vault.nodeKey.vaultKey }}{{` }} {{- end }}`}} {{- end }} vault.hashicorp.com/agent-inject: 'true' @@ -256,11 +256,11 @@ spec: {{- range $keys := .Values.node.vault.keys }} {{ $.Values.node.command }} key insert --base-path /data \ --chain ${CHAIN} \ - --key-type $(awk '/{{ .typeTarget }}/ {print $2}' /vault/secrets/{{ .name }}) \ - --scheme $(awk '/{{ .schemeTarget }}/ {print $2}' /vault/secrets/{{ .name }}) \ - --suri "$(awk '/{{ .seedTarget }}/ { $1=""; print}' /vault/secrets/{{ .name }} | cut -c 2-)" \ - && echo "Inserted key {{ .name }} into Keystore" \ - || echo "Failed to insert key {{ .name}} into Keystore." + --key-type {{ .type }} \ + --scheme {{ .scheme }} \ + --suri "/vault/secrets/{{ .name }}" \ + && echo "Inserted key {{ .name }} (type={{ .type }}, scheme={{ .scheme }}) into Keystore" \ + || echo "Failed to insert key {{ .name }} (type={{ .type }}, scheme={{ .scheme }}) into Keystore." {{- end }} env: - name: CHAIN diff --git a/charts/node/values.yaml b/charts/node/values.yaml index 13ac5b5f..fc0ac9ae 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -104,20 +104,20 @@ node: #authConfigServiceAccount: "" keys: {} # - name: grankey + # type: type + # scheme: scheme # vaultPath: secret/grankey - # typeTarget: type - # schemeTarget: scheme - # seedTarget: seed + # vaultKey: gran # - name: babekey + # type: type + # scheme: scheme # vaultPath: secrets/babeKey - # typeTarget: type - # schemeTarget: scheme - # seedTarget: seed + # vaultKey: babe nodeKey: {} # name: nodekey # vaultPath: secret/nodekey - # remark: keyTarget cannot contain dashes ('-'), only alphanumeric characters due to a limitation in the go templating - # keyTarget: key + # remark: vaultKey cannot contain dashes ('-'), only alphanumeric characters due to a limitation in the go templating + # vaultKey: key persistGeneratedNodeKey: false #customNodeKey: "" resources: {} From 555bad0332dbfd915704c39e79799f74ca55dc32 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 18:58:22 +0100 Subject: [PATCH 10/14] fix init container key injection for nodes using a custom chainspec --- charts/node/templates/statefulset.yaml | 4 ++-- charts/node/values.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 02abdab2..e1caee08 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -229,7 +229,7 @@ spec: - | {{- range $keys := .Values.node.keys }} {{ $.Values.node.command }} key insert --base-path /data \ - --chain ${CHAIN} \ + --chain {{ if $.Values.node.customChainspecUrl }}{{ $.Values.node.customChainspecPath }}{{ else }}${CHAIN}{{ end }} \ --key-type $(cat /var/run/secrets/{{ .type }}/type) \ --scheme $(cat /var/run/secrets/{{ .type }}/scheme) \ --suri /var/run/secrets/{{ .type }}/seed \ @@ -255,7 +255,7 @@ spec: - | {{- range $keys := .Values.node.vault.keys }} {{ $.Values.node.command }} key insert --base-path /data \ - --chain ${CHAIN} \ + --chain {{ if $.Values.node.customChainspecUrl }}{{ $.Values.node.customChainspecPath }}{{ else }}${CHAIN}{{ end }} \ --key-type {{ .type }} \ --scheme {{ .scheme }} \ --suri "/vault/secrets/{{ .name }}" \ diff --git a/charts/node/values.yaml b/charts/node/values.yaml index fc0ac9ae..fd6557c0 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -108,6 +108,7 @@ node: # scheme: scheme # vaultPath: secret/grankey # vaultKey: gran + # extraDerivation: // # - name: babekey # type: type # scheme: scheme From eff63ff825ea3685cf50b79b75f2058fd8794bc1 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 19:04:57 +0100 Subject: [PATCH 11/14] fix whitespace issue in vault go templating --- charts/node/templates/statefulset.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index e1caee08..8ff0b027 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -25,17 +25,13 @@ spec: {{- range $keys := .Values.node.vault.keys }} vault.hashicorp.com/agent-inject-secret-{{ .name }}: {{ .vaultPath | squote }} vault.hashicorp.com/agent-inject-template-{{ .name }}: | - {{`{{- with secret "`}}{{ .vaultPath }}{{`" }} - {{ .Data.data.`}}{{ .vaultKey }}{{` }} - {{- end }}`}} + {{`{{ with secret "`}}{{ .vaultPath }}{{`" }}{{ .Data.data.`}}{{ .vaultKey }}{{` }}{{ end }}`}} {{- end }} {{- if or .Values.node.vault.keys .Values.node.vault.nodeKey }} {{- if .Values.node.vault.nodeKey }} vault.hashicorp.com/agent-inject-secret-{{ .Values.node.vault.nodeKey.name }}: {{ .Values.node.vault.nodeKey.vaultPath | squote }} vault.hashicorp.com/agent-inject-template-{{ .Values.node.vault.nodeKey.name }}: | - {{`{{- with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }} - {{ .Data.data.`}}{{ .Values.node.vault.nodeKey.vaultKey }}{{` }} - {{- end }}`}} + {{`{{ with secret "`}}{{ .Values.node.vault.nodeKey.vaultPath }}{{`" }}{{ .Data.data.`}}{{ .Values.node.vault.nodeKey.vaultKey }}{{` }}{{ end }}`}} {{- end }} vault.hashicorp.com/agent-inject: 'true' vault.hashicorp.com/agent-init-first: 'true' @@ -229,7 +225,7 @@ spec: - | {{- range $keys := .Values.node.keys }} {{ $.Values.node.command }} key insert --base-path /data \ - --chain {{ if $.Values.node.customChainspecUrl }}{{ $.Values.node.customChainspecPath }}{{ else }}${CHAIN}{{ end }} \ + --chain {{ if $.Values.node.customChainspecUrl }}{{ $.Values.node.customChainspecPath }}{{ else }}${CHAIN}{{ end }} \ --key-type $(cat /var/run/secrets/{{ .type }}/type) \ --scheme $(cat /var/run/secrets/{{ .type }}/scheme) \ --suri /var/run/secrets/{{ .type }}/seed \ From 1bbea2d21b6928c22e5ced8c37fd3f9ac1359c72 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 19:22:01 +0100 Subject: [PATCH 12/14] add an extra derivation option to vault injected keys --- charts/node/README.md | 15 ++++++++++++++- charts/node/templates/statefulset.yaml | 4 ++++ charts/node/values.yaml | 6 +++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/charts/node/README.md b/charts/node/README.md index d731a14e..6288eab8 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -23,6 +23,7 @@ helm install kusama-node parity/node --set node.chainDataSnapshotUrl=https://ksm ⚠️ For some chains where the local directory name is different from the chain ID, `node.chainPath` needs to be set to a custom value. ### Optional Vault Integration + To integrate this chart with vault: - Vault agent injector [installed](https://www.vaultproject.io/docs/platform/k8s/injector/installation) on the cluster - Kubernetes [auth enabled](https://learn.hashicorp.com/tutorials/vault/kubernetes-sidecar#configure-kubernetes-authentication) in your vault instance @@ -30,6 +31,18 @@ To integrate this chart with vault: - A policy for each of your secrets configured in your vault - an authentication role crated in your vault instance (should match the serviceAccount name for this chart) with policies for accessing your keys attached +``` +node: + vault: + keys: + - name: aura + type: aura + scheme: sr25519 + vaultPath: kv/secret/polkadot-node # path at which the secret is located in Vault + vaultKey: aura # key under which the secret value is stored in Vault + extraDerivation: "//${HOSTNAME}//aura" # allows to have unique derived keys for each pod of the statefulset +``` + ## Parameters ### Common parameters @@ -58,7 +71,7 @@ To integrate this chart with vault: | `node.vault.authType` | Set the vault-agent authentication type (defaults to `kubernetes` when not set) | `nil` | | `node.vault.authConfigType` | Set the vault-agent authentication additional `type` parameter | `nil` | | `node.vault.authConfigServiceAccount` | Set the vault-agent authentication additional `service-account` parameter | `nil` | -| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{name, vaultPath, vaultKey, scheme, type}) | `{}` | +| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{name, vaultPath, vaultKey, scheme, type, extraDerivation}) | `{}` | | `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, vaultKey}) | `{}` | | `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | | `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | diff --git a/charts/node/templates/statefulset.yaml b/charts/node/templates/statefulset.yaml index 8ff0b027..637b589e 100644 --- a/charts/node/templates/statefulset.yaml +++ b/charts/node/templates/statefulset.yaml @@ -254,7 +254,11 @@ spec: --chain {{ if $.Values.node.customChainspecUrl }}{{ $.Values.node.customChainspecPath }}{{ else }}${CHAIN}{{ end }} \ --key-type {{ .type }} \ --scheme {{ .scheme }} \ + {{- if .extraDerivation }} + --suri "$(cat /vault/secrets/{{ .name }}){{ .extraDerivation }}" \ + {{ else }} --suri "/vault/secrets/{{ .name }}" \ + {{- end }} && echo "Inserted key {{ .name }} (type={{ .type }}, scheme={{ .scheme }}) into Keystore" \ || echo "Failed to insert key {{ .name }} (type={{ .type }}, scheme={{ .scheme }}) into Keystore." {{- end }} diff --git a/charts/node/values.yaml b/charts/node/values.yaml index fd6557c0..75f0898e 100644 --- a/charts/node/values.yaml +++ b/charts/node/values.yaml @@ -106,17 +106,17 @@ node: # - name: grankey # type: type # scheme: scheme - # vaultPath: secret/grankey + # vaultPath: kv/secret/grankey # vaultKey: gran # extraDerivation: // # - name: babekey # type: type # scheme: scheme - # vaultPath: secrets/babeKey + # vaultPath: kv/secrets/babeKey # vaultKey: babe nodeKey: {} # name: nodekey - # vaultPath: secret/nodekey + # vaultPath: kv/secret/nodekey # remark: vaultKey cannot contain dashes ('-'), only alphanumeric characters due to a limitation in the go templating # vaultKey: key persistGeneratedNodeKey: false From d4261d4bbdbd091f5ca84798e06f562bb384ef14 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 9 Mar 2022 19:34:36 +0100 Subject: [PATCH 13/14] add readme section on how to set node key from Vault --- charts/node/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/charts/node/README.md b/charts/node/README.md index 6288eab8..787a2ece 100644 --- a/charts/node/README.md +++ b/charts/node/README.md @@ -41,6 +41,10 @@ node: vaultPath: kv/secret/polkadot-node # path at which the secret is located in Vault vaultKey: aura # key under which the secret value is stored in Vault extraDerivation: "//${HOSTNAME}//aura" # allows to have unique derived keys for each pod of the statefulset + nodeKey: + name: nodekey + vaultPath: kv/secret/polkadot-node + vaultKey: nodekey ``` ## Parameters @@ -71,7 +75,7 @@ node: | `node.vault.authType` | Set the vault-agent authentication type (defaults to `kubernetes` when not set) | `nil` | | `node.vault.authConfigType` | Set the vault-agent authentication additional `type` parameter | `nil` | | `node.vault.authConfigServiceAccount` | Set the vault-agent authentication additional `service-account` parameter | `nil` | -| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{name, vaultPath, vaultKey, scheme, type, extraDerivation}) | `{}` | +| `node.vault.keys` | The list of vault secrets to inject on the node before startup (object{name, vaultPath, vaultKey, scheme, type, extraDerivation}). Note that the vaultKey must be alphanumeric. | `{}` | | `node.vault.nodeKey` | The vault secret to inject as a custom nodeKey (the secrets value must be 64 byte hex) (object {name, vaultPath, vaultKey}) | `{}` | | `node.persistGeneratedNodeKey` | Persist the auto-generated node key inside the data volume (at /data/node-key) | `false` | | `node.customNodeKey` | Use a custom node-key, if `node.persistGeneratedNodeKey` is true then this will not be used. (Must be 64 byte hex key), supercedes `node.vault.nodeKey` | `nil` | From 4d262d0e27411d1ac6e97368b82d8b7626e7d642 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Thu, 10 Mar 2022 16:17:29 +0100 Subject: [PATCH 14/14] tag node chart version 1.4.0 --- charts/node/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/node/Chart.yaml b/charts/node/Chart.yaml index 53c8bf5a..e95d0e60 100644 --- a/charts/node/Chart.yaml +++ b/charts/node/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: node description: A Helm chart to deploy Substrate/Polkadot nodes type: application -version: 1.3.0 +version: 1.4.0 appVersion: "0.0.1"