[Cells 1.0] Iteration 1: Introduce encryption key services and support multiple `db_key_base`

This adds support for defining db_key_base as an array instead of a single key. This is a pre-requisite for a proper Encryption key management.

The db_key_base secret is now wrapped in an array even if it's a single string, but you can already define an array directly in config/secrets.yml. For now, actually defining multiple keys will raise an error because we first need to record what key was used to encrypt data before we can actually support multiple keys (so that we can know what data needs to be re-encrypted when a new key is introduced). For more details, see the proposal at gitlab-com/content-sites/handbook!10303 (merged).

The is MR introduces a Gitlab::Database::Encryption::KeyProviderService class that acts as a builder class for key providers given a key type. The returned key provider service respond to #encryption_key and #decryption_keys, similarly to ActiveRecord::Encryption::KeyProvider. The services allows to hide the details about what actual secrets are passed to each key provider. We're only relying on ActiveRecord::Encryption's native providers:

  • ActiveRecord::Encryption::KeyProvider
  • ActiveRecord::Encryption::DerivedSecretKeyProvider

We're using Gitlab::Database::Encryption::KeyProviderService to get the encryption/decryption key(s) in all the places where we would fetch the key directly from Settings before.

Encryption

The encryption key will always be the last value in the array.

Decryption

All db_key_base secrets will be used in turn until one can decrypt the encrypted value, starting from the first (i.e. oldest) element to last (i.e. newest). In practice, since we always use the first key to encrypt (and since we limit to one key), it should also be the key used for decryption.

References

Please include cross links to any resources that are relevant to this MR. This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.

Edited by Rémy Coutable