(dev/core#2258) Add API+hook to rotate keys for encrypted fields #19251
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
Key rotation is the process of phasing-out an old cryptographic-key and phasing-in a new one. This patchset introduces support for rotating the key used for encrypted values in the database.
Many security practitioners regard key-rotation as best-practice because it:
See also: https://lab.civicrm.org/dev/core/-/issues/2258
(NOTE: This builds on #19236, and it is a step towards #19239.)
Before
#19236 was a partial step towards key-rotation. Specifically, it allowed one to define multiple keys. For example, suppose
civicrm.settings.php
starts with the configuration:You could add a higher-priority key in the list:
Any new credential-content will be encrypted with
::bbbb
. However, existing content still uses::aaaa
. There is no defined mechanism for re-encrypting values with::bbbb
.After
The
System.rotateKey
API can migrate data from the old::aaaa
to the new::bbbb
, e.g.This fires
hook_civicrm_cryptoRotateKey('CRED', $log)
to ensure that any data based onCRED
is re-encrypted with the current key (::bbbb
).Comments
Why is there a hook? Consider that there are several bits of content that should be plausibly re-encryped, e.g.
civicrm_settings
, and within the record formailing_backend
, there is a subfield forsmtpPassword
which should be encryptable/rotateable.civicrm_settings
, there are somevalue
s (likely defined in extensions) which should be encryptable/rotateable.civicrm_payment_processor
, thepassword
should be encryptable/rotateable.These are 3 different data-structures, and there is no singular SQL statement to touch all of them. We have to define multiple re-encryption steps (and some of them may be extension-dependent). Using a hook provides a flexible starting point.
Here's pseudocode for a hook-implementation:
For a working example, see #19239 which addresses the
civicrm_setting
.mailing_backend
.smtpPassword
.