How to change REDASH_SECRET_KEY?

Hi.

Is there a feature to re-encrypt data source options with new REDASH_SECRET_KEY?

If REDASH_SECRET_KEY is leaked, I want to change REDASH_SECRET_KEY and encrypt data source options with the new REDASH_SECRET_KEY.

I checked documents and source code but I can’t find about it.

Could you help me?
Thanks.

1 Like

Welcome to the forum. I think one of these could work. Definitely back up your Redash metadata before attempting either of these.

Use the API

  1. Decrypt and extract the data source info from the current database. Also pull info on which queries use those sources. Drop the data sources. Kill Redash.
  2. Change the REDASH_SECRET_KEY located in redash.settings.DATA_SOURCE_SECRET_KEY and restart Redash.
  3. Create new data sources with the API and the decrypted connection information
  4. Cycle through the queries from step 1 and update each data_source_id.

Alternatively:

We use sqlalchemy_utils’s EncryptedType to implement the encryption.

From their documentation:

The key parameter accepts a callable to allow for the key to change per-row instead of being fixed for the whole table.

This suggests you can use more than one SECRET_KEY on the same table, as long as SQLAlchemy has access to both secret keys. It follows that you could write a database migration to re-encrypt the data source connection information in place.

But in my opinion, the API pattern would be easier.

2 Likes

Thank you for your reply.

I wrote a script to reencrypt data source options with sqlalchemy_utils.
The script is https://github.com/shinsuke-nara/redash/blob/change-secret-script/change-secret.py
I think this will help other redash users.

I’m glad to make PR if you can accept this.
How do you think about my suggestion?

1 Like

Thanks, @shinsuke-nara! This is a clever use of SQLAlchemy :slight_smile: You’re welcome to make a PR and add this as a new CLI command.

There is one more way, which has some benefits as it allows doing these changes without downtime. The downside is that it requires a bit more effort, but here’s the details in case someone wants to take a stab:

  • We’re using sqlalchemy-utils's FernetEngine, which in turn uses Fernet from cryptography.
  • cryptography has another implementation: MultiFernet. It works the same way as Fernet, except that it can take multiple keys (and try to decrypt with all of them) along with a rotate method which will re-encrypt with the new key.
  • FernetEngine is quite simple and we can create a version of it that uses MultiFernet instead and accepts multiple keys. Just need to figure out how to expose the rotate method.
2 Likes

Thank you for your reply.

I made a PR for this: https://github.com/getredash/redash/pull/4190

Your suggestion which is runtime reencryption is interesting.
I want to make an issue in github if you can allow it.