If you want to use environment variables (ENVs) instead of the credentials files because you're in a cloud service like AWS or Heroku you can still do it and rollover your keys.
Just add your ENVs to your .env and/or .env.development , etc. like so...
PRIMARY_KEY=EGY8WhulUOXixybod7ZWwMIL68R9o5kC
PRIMARY_KEY_ROLLOVER= <- empty until you need to rollover
DETERMINISTIC_KEY="aPA5XyALhf75NNnMzaspW7akTfZp0lPY"
KEY_DERIVATION_SALT=xEY0dt6TZcAMg52K7O84wYzkjvbA62Hz
You don't need the deterministic key if you're not going to use it. I just have it for incase I want to.
You can create your keys in the console:
SecureRandom.alphanumeric(32)
Now that you have the ENVs you can enter them into your Parameter Store however your cloud provider allows.
Now lets boot up our app with the correct configuration.
If you added ENVs to the .env file and you're not going to care about per environment basis then add these configs to your application.rb
config.active_record.encryption.primary_key = ENV["PRIMARY_KEY"]
config.active_record.encryption.deterministic_key = ENV["DETERMINISTIC_KEY"]
config.active_record.encryption.key_derivation_salt = ENV["KEY_DERIVATION_SALT"]
However you probably should do everything by environment and add this to your (environment).rb
unless your deploy process imports different ENVs based on the environment it's deploying.
# development.rb
config.active_record.encryption.primary_key = ENV["PRIMARY_KEY"]
config.active_record.encryption.deterministic_key = ENV["DETERMINISTIC_KEY"]
config.active_record.encryption.key_derivation_salt = ENV["KEY_DERIVATION_SALT"]
But what about rollover?
Lets make a change to your primary key.
# development.rb
config.active_record.encryption.primary_key = [ENV["PRIMARY_KEY"], ENV["PRIMARY_KEY_ROLLOVER"]].compact_blank
config.active_record.encryption.deterministic_key = ENV["DETERMINISTIC_KEY"]
config.active_record.encryption.key_derivation_salt = ENV["KEY_DERIVATION_SALT"]
If you don't want a rollover you can just add PRIMARY_KEY_V2, etc.
and keep the array growing.
As rails initializes the environment, it will have a single value or an array of values, the last index will be the newest key.
.compact_blank
will clear the array of ""
values in the array for when your rollover key is empty. You only need a rollover key when you're going to rollover.
Save a new 32 char random value to your rollover ENV
PRIMARY_KEY_ROLLOVER=LsnKbJ3Gyg9Ee2Klfq1gKa6UUR54aCh6
Every time my rails app deploys it will load ENVs so now the rollover key isn't blank.
Now you need to write a script to encrypt your data to the rollover key.
You can call this script from an admin or write a data migration to run it.
Example:
Documents.find_each do |document| #encrypt in batches of 1000
document.encrypt
end
Calling .encrypt
on a document will decrypt with any key it finds that works and re-encrypt with a new key (highest array index).
For the rollover approach I would copy the primary key temporarily, and then move the rollover key to the primary key env.
PRIMARY_KEY=(ROLLOVER_KEY value)
PRIMARY_KEY_ROLLOVER= (empty)
Re deploy and all code should now be decrypting with the new rolled over key. If it didn't work add that encrypted_key that you temporarily saved back to the ENVs and fix your code, you dummy.
Remember you must add the new keys to the end of the array config.
Now you're set to rollover your keys at whatever interval you decide. Without credential.yml.
Thanks for reading.
Top comments (0)