Encrypt Data Source Credentials

Data source credentials are vital pieces of metadata that must be safeguarded. While in GoodData Cloud we ensure your credentials are encrypted and stored securely on our end, in GoodData.CN the responsibility falls on the deployment administrator. This article explains how to secure your data source credentials in GoodData.CN.

The encryption applies to data source credentials and organization OIDC client secrets. We use the Google Tink library to encrypt this metadata, with the keyset passed as a metadata-api service configuration parameter.

Follow these steps to ensure your data source credentials stored in GoodData.CN are encrypted:

  1. Create and Manage Keysets
  2. Configure Helm Chart

Create and Manage Keysets

Google Tink provides a key management tool, Tinkey. Use Tinkey to manage your keys.

Install Tinkey

Download and extract the Tinkey key management tool:

curl -fsL https://storage.googleapis.com/tinkey/tinkey-1.9.0.tar.gz | tar xzvf -

Create New Keyset

Generate a new keyset, with one key set as primary and enabled:

tinkey create-keyset --key-template AES256_GCM --out output_keyset.json

You can now configure the Helm chart.

Rotate Keysets

Key rotation is essential for maintaining the security of distributed systems. However, this process can be prone to race conditions. Follow these steps to ensure a smooth rotation:

  1. Add New Key
  2. Promote New Key
  3. Encrypt Secrets
  4. (Optional) Remove the oldest key

Add New Key

Add a new key to the keyset and propagate this change to all metadata-api services.

Steps:

  1. Identify all existing keys in keyset:

    tinkey list-keyset --in live_keyset.json |grep '  key_id:'
    

    The output may look something like this:

    key_id: 1088398113
    key_id: 343627806
    
  2. Add a new key to keyset:

    tinkey add-key --key-template AES256_GCM --in live_keyset.json --out added_key_keyset.json
    
  3. Perform a check by re-identifiying all existing keys in keyset:

    tinkey list-keyset --in added_key_keyset.json |grep '  key_id:'
    

    The output may look something like this:

    key_id: 1088398113
    key_id: 343627806
    key_id: 1292234114
    

    where key_id: 1292234114 is the new key.

Distribute the updated added_key_keyset.json to GoodData.CN deployments. Ensure all metadata-api services restart after the Secret is modified.

Promote New Key

Promoting a key means making it the primary key for encryption. After adding a new key, you’ll need to promote it:

tinkey promote-key --key-id <RECENTLY_ADDED_KEY_ID> --in added_key_keyset.json --out rotated_keyset.json

Replace <RECENTLY_ADDED_KEY_ID> with the actual ID of the recently added key (e.g., 1292234114 from the previous step).

Distribute the rotated_keyset.json to GoodData.CN deployments and ensure all metadata-api services restart.

Encrypt Secrets

With the new primary key set, older secrets remain encrypted with previous keys. Re-encrypt old data to ensure outdated keys aren’t utilized:

See Encrypt Credentials.

(Optional) Remove the Oldest Key

As the keyset grows with each rotation, it might be efficient to limit the number of keys by removing older ones. However, remember:

  • Ensure the key isn’t encrypting any secret.
  • SQL-level DB backups encrypted with a removed key will be rendered unusable.
tinkey delete-key --key-id <OLDEST_KEY_ID> --in added_key_keyset.json --out removed_old_key_keyset.json

Other Useful Commands

You may also use the following commands to list and delete keys:

List Keys

To view all keys in the keyset:

tinkey list-keyset --in keyset.json

The output, for example, shows the key ids and indicates the primary key:

primary_key_id: 343627806
key_info {
  type_url: "type.googleapis.com/google.crypto.tink.AesGcmKey"
  status: ENABLED
  key_id: 1088398113
  output_prefix_type: TINK
}
key_info {
  type_url: "type.googleapis.com/google.crypto.tink.AesGcmKey"
  status: ENABLED
  key_id: 343627806
  output_prefix_type: TINK
}

Delete Key

Reduce the keyset size by removing a key. Before doing so, confirm all data encrypted by this key has been re-encrypted by the current primary key:

tinkey delete-key --key-set input_keyset.json --key-id number --out output_keyset.json

Configure Helm Chart

Once you have your Tink keyset, update the following parameters in the helm chart options for GoodData.CN to enable the encryption of data source credentials in your GoodData.CN deployment:

  • metadataApi.encryptor.enabled

    Enable or disable the use of encryption for your data source credentials. Enabled by default.

  • metadataApi.encryptor.existingSecret

    Store your Tink keyset as a secret here. See Secret Management.

  • metadataApi.encryptor.keySet

    Or store your Tink keyset as plain text here.

For security reasons we recommend you store your keyset using a secret. In case both existingSecret and keySet fields are populated, the backend will use existingSecret.

Note that if the encryption is enabled, but no keyset is provided, the metadata-api deployment will fail.

Encrypt Credentials

Whenever you store a new keyset, you have to (re)encrypt your data source credentials by calling the API endpoint http://localhost:9008/actuator/reencrypt:

kubectl exec <pod> -n <namespace> -- /bin/bash -c "curl -X POST -v http://localhost:9008/actuator/reencrypt"

For example:

kubectl -n gooddata-cn exec -c metadata-api deployments/gooddata-cn-metadata-api -- curl -X POST -v http://localhost:9008/actuator/reencrypt