Security Hardening

Third-party Daml apps

Warning

As an SV operator, you are most welcome to review, install, and use third-party Daml apps provided you install third-party Daml apps on a validator node separate from your SV node.

Installing additional Daml apps on an SV node is not supported and may compromise its secure operations. In particular, please refrain from manually uploading additional .dar files to your SV node or manually connecting it to third-party synchronizers.

Using an external KMS for managing participant keys

By default, Canton participants use cryptographic keys that are generated by the participant itself and stored in the regular database used by the participant. To improve key security, participants can be configured to use an external Key Management System (KMS) to generate and store keys. Please consult the official Canton documentation on KMS support for additional details and a list of supported KMS providers. Participants deployed as part of a Splice deployment support the External Key Storage mode of KMS usage.

In the following, we describe how to configure an SV so that its participant keys are managed by an external KMS. This guide assumes that you are following Kubernetes-Based Deployment of a Super Validator node for deploying your SV.

Official support for the KMS-based operation of sequencers and mediators that are part of an SV deployment is planned for a future release.

Migrating an existing SV to use an external KMS for participant keys

It is not supported to migrate an existing participant from “non-KMS-based” to “KMS-based” operation, or to migrate from one KMS provider to another. The main reason for this is that a participant’s root namespace key cannot be rotated, and importing it from a potentially unsafe location into a KMS would diminish the security gain of using the KMS. Moreover, some KMS providers do not support importing existing keys at all and can only be used for managing keys generated by the KMS itself.

One approach for switching to use KMS for SV participant keys while minimizing the risk of losing rewards is to:

  1. Set up a fresh SV from scratch with the desired KMS configuration. (Rest of this guide.) Coordinate with the other SV operators to onboard it with weight 0.

  2. Coordinate with the other SV operators to move your SV weight to the new SV, setting the weight of the older SV to 0.

  3. Transfer all relevant assets from the older SV to a validator or the new KMS-enabled SV.

  4. Coordinate with the other SV operators to offboard the older SV.

  5. Retire the older SV.

Configuring a fresh SV to use an external KMS

In addition to configuration changes to the participant Helm chart itself, you will also need to change the way in which your CometBFT governance key is managed compared to the default setup.

External management of CometBFT governance key

By default, the CometBFT governance key is managed transparently by the SV app, using the participant for key generation and storage. The specific way in which this is realized is not supported for KMS-enabled participants. Therefore, SV operators that wish to use an external KMS for managing their participant keys must manage the CometBFT governance key of their SV externally.

This involves the following steps:

  1. Generate a new CometBFT governance key.

  2. Configure your SV app to use this externally generated key.

Generating a CometBFT governance key

Use the following shell commands to generate a keypair in the expected format:

# Generate the private key
openssl genpkey -algorithm ed25519 -out cometbft-governance-keys.pem

# Extract and encode the keys
public_key_base64=$(openssl pkey -in cometbft-governance-keys.pem -pubout -outform DER | tail -c 32 | base64 | tr -d "\n")
private_key_base64=$(openssl pkey -in cometbft-governance-keys.pem -outform DER | tail -c 32 | base64 | tr -d "\n")

echo "{"
# Output the keys
echo "  \"publicKey\": \"$public_key_base64\","
echo "  \"privateKey\": \"$private_key_base64\""
echo "}"

# Clean up
rm cometbft-governance-keys.pem

These commands should result in an output similar to

{
  "public": "A9tWyYq/HIJ3B73ym1eIUV8yqnDBligGJUE8463CBUM=",
  "private": "FDG16PaSh9hGLu2fXzEHmTECMjSyQuZnEg+w5HKCEtg="
}

Save this output to a file, e.g., cometbft-governance-keys.json.

Configuring SV app to use the externally generated CometBFT governance key

You inject the externally generated CometBFT governance key into the SV app via storing it in a k8s secret named splice-app-sv-cometbft-governance-key.

Assuming that your SV deployment resides in the sv namespace, use the following command to create the secret from the JSON file generated above:

kubectl create secret --namespace sv generic splice-app-sv-cometbft-governance-key \
  --from-literal=publicKey="$(jq -r .public cometbft-governance-keys.json)" \
  --from-literal=privateKey="$(jq -r .private cometbft-governance-keys.json)"

To instruct the SV app to use the externally managed CometBFT governance key instead of generating a fresh one itself, set the cometBFT.externalGovernanceKey value in the splice-sv-node Helm chart to true. (You can comment out the respective line in splice-node/examples/sv-helm/sv-values.yaml.)

Configuring participant to use an external KMS

Beyond the changes to the SV app deployment described above, the setup of an SV participant to use an external KMS is identical to the setup of a validator participant with KMS. It involves configuration changes to the splice-participant Helm chart that depend on the KMS provider you choose.

Please refer to the Canton documentation on configuring KMS support for determining the right configuration options to match your desired KMS provider and setup. We provide minimal Helm configuration examples for Google Cloud (GCP) KMS and Amazon Web Services (AWS) KMS below.

Warning

The GCP and AWS KMS drivers are available only for licensed users of Canton Enterprise.

Whatever KMS provider you choose, please note:

  • Values in the kms section of the participant Helm chart are implicitly mapped to the Canton participant crypto.kms config. This implies that all configuration keys supported by Canton are supported, not only the ones shown in the examples above. Key names in camelCase are automatically converted to kebab-case.

  • For setting extra environment variables and mounting files to configure authentication to the KMS, you can use the .additionalEnvVars, .extraVolumeMounts, and .extraVolumes fields of the Splice participant Helm chart (see the examples).

  • Make sure that your KMS configuration is always included in the values files you pass to helm install participant ... or helm upgrade participant ....

Also recall that you need to deploy a fresh participant in order for KMS to be used correctly, which implies that you will need to set up the remaining SV components afresh as well (see above).

Google Cloud KMS

The mock configuration below for GCP KMS is included in splice-node/examples/sv-helm/kms-participant-gcp-values.yaml:

# Participant using GCP KMS (mock values; please modify to match your setup)
# See https://docs.daml.com/canton/usermanual/kms/kms_gcp_setup.html

kms:
  type: gcp
  # Replace LOCATION_ID, PROJECT_ID, and KEY_RING_ID based on your GCP KMS setup
  locationId: LOCATION_ID
  projectId: PROJECT_ID
  keyRingId: KEY_RING_ID
  # All other Canton options are supported as well;
  # camelCase keys here are automatically converted to kebab-case

# Example for configuring authentication to the GCP KMS.
# Adds an env var on the participant pod that points to the location of the Google
# credentials file and mounts that file as a volume, reading its contents from a secret.
# In order for this to work as-is, you need to create the appropriate k8s secret
# and ensure that it holds the contents of a valid Google credentials file
# (under the `googleCredentials` key).
additionalEnvVars:
  - name: GOOGLE_APPLICATION_CREDENTIALS
    value: "/app/gcp-credentials.json"
extraVolumeMounts:
  - name: gcp-credentials
    mountPath: "/app/gcp-credentials.json"
    subPath: googleCredentials
extraVolumes:
  - name: gcp-credentials
    secret:
      secretName: gke-credentials

Please refer to the Canton documentation for a list of supported configuration options and their meaning, as well as for instructions on configuring authentication to the KMS. Note again that Splice participants support the External Key Storage mode of KMS usage, so that (per the relevant Canton docs) the authentication credentials you supply must correspond to a GCP service account with the following IAM permissions:

  • cloudkms.cryptoKeyVersions.create

  • cloudkms.cryptoKeyVersions.useToDecrypt

  • cloudkms.cryptoKeyVersions.useToSign

  • cloudkms.cryptoKeyVersions.get

  • cloudkms.cryptoKeyVersions.viewPublicKey

For example, you can grant the Cloud KMS Admin and Cloud KMS Crypto Operator roles to the validator KMS service account.

Amazon Web Services KMS

The mock configuration below for AWS KMS is included in splice-node/examples/sv-helm/kms-participant-aws-values.yaml:

# Participant using AWS KMS (mock values; please modify to match your setup)
# See https://docs.daml.com/canton/usermanual/kms/kms_aws_setup.html
kms:
  type: aws
  # Replace REGION based on your AWS KMS setup
  region: REGION
  # All other Canton options are supported as well;
  # camelCase keys here are automatically converted to kebab-case

# Example for configuring authentication to the AWS KMS.
# Adds env vars on the participant pod with credentials read from a k8s secret.
# In order for this to work as-is, you need to create the appropriate k8s secret
# and ensure that it holds valid credentials
# (under the `accessKeyId` and `secretAccessKey` keys).
additionalEnvVars:
  - name: AWS_ACCESS_KEY_ID
    valueFrom:
      secretKeyRef:
        name: aws-credentials
        key: accessKeyId
  - name: AWS_SECRET_ACCESS_KEY
    valueFrom:
      secretKeyRef:
        name: aws-credentials
        key: secretAccessKey

Please refer to the Canton documentation for a list of supported configuration options and their meaning, as well as for instructions on configuring authentication to the KMS. Note again that Splice participants support the External Key Storage mode of KMS usage, so that (per the relevant Canton docs) the authentication credentials you supply must correspond to an entity with the following IAM permissions:

  • kms:CreateKey

  • kms:TagResource

  • kms:Decrypt

  • kms:Sign

  • kms:DescribeKey

  • kms:GetPublicKey

Comments