diff --git a/RUNBOOK.md b/RUNBOOK.md
index acb235f..b057c5f 100644
--- a/RUNBOOK.md
+++ b/RUNBOOK.md
@@ -204,6 +204,34 @@ Both API Keys and Secrets keys are generated by you. `api_key` must be a UUID, `
See [Peer information and credential exchange](#8-peer-information-and-credential-exchange) below for a recommendation
on how to exchange credentials between peers.
+#### Keystore backend
+
+`verifier.secrets.bootstrap` also selects where the verifier's **signing key** lives:
+`keystoreBackend: postgres` (default) or `keystoreBackend: kms`.
+
+**On `externalSecret`, the chart writes the keystore block for you** from `keystoreBackend` and
+`verifier.secrets.bootstrap.kms.*`.
+
+**On `gcpSecretStore`, `awsSecretStore` and `existingSecret` you write `secrets.toml` yourself** and the
+chart only mounts it. `keystoreBackend` and `kms.*` are ignored on those paths. For production, where a
+managed KMS is recommended over a Postgres-held key, the block you need is:
+
+```toml
+[keystore]
+backend = "kms"
+
+[keystore.kms]
+# "aws" or "gcp". Required; there is no default.
+provider = "gcp"
+# AWS: a Key ID or ARN. GCP: a CryptoKeyVersion resource name.
+ecdsa_key_id = "projects/
/locations//keyRings//cryptoKeys//cryptoKeyVersions/1"
+```
+
+Credentials to use KMS come from the cloud's authentication mechanism, see [Service Accounts](#service-accounts) below.
+
+The full reference, including per-cloud IAM guidance, is
+[`secrets.documented.toml`](https://github.com/smartcontractkit/chainlink-ccv/blob/main/docs/config/bootstrap/secrets.documented.toml).
+
### Ingress
You can configure an ingress to the aggregator, which must be exposed to the internet, using one of these three values:
diff --git a/charts/ccv-cell/README.md b/charts/ccv-cell/README.md
index c9e6711..1566b87 100644
--- a/charts/ccv-cell/README.md
+++ b/charts/ccv-cell/README.md
@@ -63,6 +63,9 @@ A CCV Cell also has a few external pre-requisites for a production grade deploym
- A Key Management Service (KMS) solution:
- While the application supports holding the signing key in PostgreSQL, this is not recommended for production.
- Instead, use a managed service for signing.
+ - Configure it with `verifier.secrets.bootstrap.keystoreBackend: kms`, or by writing the `[keystore.kms]`
+ block in `secrets.toml` yourself. See the [runbook](../../RUNBOOK.md#keystore-backend) and
+ [`secrets.documented.toml`](https://github.com/smartcontractkit/chainlink-ccv/blob/main/docs/config/bootstrap/secrets.documented.toml).
- **We strongly recommend that, for production, you configure alerts for unexpected use of this key. Only the ccv-cell
should be accessing this service.**
- A Cloud IAM Service Account:
@@ -355,8 +358,9 @@ A CCV Cell also has a few external pre-requisites for a production grade deploym
| verifier.secrets.bootstrap.gcpSecretStore.secretProviderClass.name | string | `""` | Name of the SecretProviderClass resource to create. |
| verifier.secrets.bootstrap.gcpSecretStore.secretVersionResourceName | string | `""` | Fully-qualified GCP Secret Manager secret version resource name, e.g. `projects//secrets//versions/latest`. |
| verifier.secrets.bootstrap.keystoreBackend | string | `"postgres"` | Keystore backend: `postgres` or `kms`. |
-| verifier.secrets.bootstrap.kms.ecdsaKeyId | string | `""` | AWS KMS key ID for the ECDSA key (only when `keystoreBackend` is `kms`). |
-| verifier.secrets.bootstrap.kms.ed25519KeyId | string | `""` | AWS KMS key ID for the Ed25519 key (only when `keystoreBackend` is `kms`). |
+| verifier.secrets.bootstrap.kms.ecdsaKeyId | string | `""` | KMS key for the ECDSA (secp256k1) signing key. Required when `keystoreBackend` is `kms`. AWS: a Key ID or ARN. GCP: a CryptoKeyVersion resource name (`projects//locations//keyRings//cryptoKeys//cryptoKeyVersions/`). Scope the workload's credentials to exactly this key. See [KeystoreConfig](https://github.com/smartcontractkit/chainlink-ccv/blob/main/bootstrap/config.go) for the per-cloud IAM guidance. |
+| verifier.secrets.bootstrap.kms.ed25519KeyId | string | `""` | KMS key for the Ed25519 (CSA) key, same format as `ecdsaKeyId`. Only needed when running against a Job Distributor. Leave empty for this chart, which runs `local_app_config`. |
+| verifier.secrets.bootstrap.kms.provider | string | `""` | Cloud KMS provider: `aws` or `gcp`. Required when `keystoreBackend` is `kms`. |
| verifier.secrets.bootstrap.labels | object | `{}` | Labels to add to the verifier bootstrap Secret. |
| verifier.secrets.bootstrap.type | string | `"externalSecret"` | Secret provisioning strategy: `externalSecret`, `existingSecret`, `gcpSecretStore`, `awsSecretStore`, or `azureKeyVault`. Configure the values below for the chosen type. |
| verifier.secrets.bootstrapConfig.annotations | object | `{}` | Annotations to add to the verifier bootstrap-config Secret (non-values types only). |
diff --git a/charts/ccv-cell/README.md.gotmpl b/charts/ccv-cell/README.md.gotmpl
index 99c16e5..7ad7396 100644
--- a/charts/ccv-cell/README.md.gotmpl
+++ b/charts/ccv-cell/README.md.gotmpl
@@ -62,6 +62,9 @@ A CCV Cell also has a few external pre-requisites for a production grade deploym
- A Key Management Service (KMS) solution:
- While the application supports holding the signing key in PostgreSQL, this is not recommended for production.
- Instead, use a managed service for signing.
+ - Configure it with `verifier.secrets.bootstrap.keystoreBackend: kms`, or by writing the `[keystore.kms]`
+ block in `secrets.toml` yourself. See the [runbook](../../RUNBOOK.md#keystore-backend) and
+ [`secrets.documented.toml`](https://github.com/smartcontractkit/chainlink-ccv/blob/main/docs/config/bootstrap/secrets.documented.toml).
- **We strongly recommend that, for production, you configure alerts for unexpected use of this key. Only the ccv-cell
should be accessing this service.**
- A Cloud IAM Service Account:
diff --git a/charts/ccv-cell/templates/verifier/externalsecret.yaml b/charts/ccv-cell/templates/verifier/externalsecret.yaml
index 58794f4..4245679 100644
--- a/charts/ccv-cell/templates/verifier/externalsecret.yaml
+++ b/charts/ccv-cell/templates/verifier/externalsecret.yaml
@@ -86,8 +86,11 @@ spec:
password = "{{ `{{ .keystore_password }}` }}"
{{- else if eq .Values.verifier.secrets.bootstrap.keystoreBackend "kms" }}
[keystore.kms]
+ provider = {{ required "verifier.secrets.bootstrap.kms.provider is required when keystoreBackend is kms (aws or gcp)" .Values.verifier.secrets.bootstrap.kms.provider | quote }}
ecdsa_key_id = {{ .Values.verifier.secrets.bootstrap.kms.ecdsaKeyId | quote }}
- ed25519_key_id = {{ .Values.verifier.secrets.bootstrap.kms.ed25519KeyId | quote }}
+ {{- with .Values.verifier.secrets.bootstrap.kms.ed25519KeyId }}
+ ed25519_key_id = {{ . | quote }}
+ {{- end }}
{{- else }}
{{- fail (print "Storage backend '" .Values.verifier.secrets.bootstrap.keystoreBackend "' is invalid") }}
{{- end }}
diff --git a/charts/ccv-cell/values.schema.json b/charts/ccv-cell/values.schema.json
index a89e23a..30c0de8 100644
--- a/charts/ccv-cell/values.schema.json
+++ b/charts/ccv-cell/values.schema.json
@@ -279,6 +279,7 @@
"kms": {
"type": "object",
"properties": {
+ "provider": { "type": "string", "enum": ["", "aws", "gcp"] },
"ecdsaKeyId": { "type": "string" },
"ed25519KeyId": { "type": "string" }
}
diff --git a/charts/ccv-cell/values.yaml b/charts/ccv-cell/values.yaml
index cc2ed6f..a0013a1 100644
--- a/charts/ccv-cell/values.yaml
+++ b/charts/ccv-cell/values.yaml
@@ -980,10 +980,18 @@ verifier:
keystoreBackend: postgres
kms:
- # -- AWS KMS key ID for the ECDSA key (only when `keystoreBackend` is `kms`).
- ecdsaKeyId: "" # "arn:aws:kms:us-east-1:...:key/abc123-..."
- # -- AWS KMS key ID for the Ed25519 key (only when `keystoreBackend` is `kms`).
- ed25519KeyId: "" # "arn:aws:kms:us-east-1:...:key/def456-..."
+ # -- Cloud KMS provider: `aws` or `gcp`. Required when `keystoreBackend` is `kms`.
+ provider: ""
+ # -- KMS key for the ECDSA (secp256k1) signing key. Required when `keystoreBackend` is `kms`.
+ # AWS: a Key ID or ARN. GCP: a CryptoKeyVersion resource name
+ # (`projects//locations//keyRings//cryptoKeys//cryptoKeyVersions/`).
+ # Scope the workload's credentials to exactly this key. See
+ # [KeystoreConfig](https://github.com/smartcontractkit/chainlink-ccv/blob/main/bootstrap/config.go)
+ # for the per-cloud IAM guidance.
+ ecdsaKeyId: ""
+ # -- KMS key for the Ed25519 (CSA) key, same format as `ecdsaKeyId`. Only needed when running
+ # against a Job Distributor. Leave empty for this chart, which runs `local_app_config`.
+ ed25519KeyId: ""
# -- Secret provisioning strategy: `externalSecret`, `existingSecret`, `gcpSecretStore`, `awsSecretStore`, or `azureKeyVault`.
# Configure the values below for the chosen type.