Moving Secrets out of the Database with Drupal's Key Module
On the Drupal platform I work on, search runs on SearchStax. Every site has its own search app with its own update token, plus a separate key for search analytics. After the migration to SearchStax, those values lived where Drupal keeps most settings: in each site's configuration.
Configuration is the wrong place for a secret. It's stored in the database, so it's in every database backup and every copy of a site pulled down to a laptop. It can end up in a config export and from there in git. And anyone with access to the right admin form can read it. On a platform with dozens of sites and three environments, that's a lot of copies of a lot of tokens.
What the Key module does
The Key module separates "a module needs a secret" from "where the secret is stored". A module that supports Key doesn't store the token itself. It stores a reference to a key, and the key decides where the value comes from: configuration, an environment variable, or a file.
# key.key.searchstax_solr_connector.yml (simplified)
id: searchstax_solr_connector
label: 'SearchStax Solr connector'
key_type: authentication
key_provider: file
key_provider_settings:
file_location: 'private://keys/searchstax-solr-connector.key'
strip_line_breaks: trueThe file provider is the interesting one. The key's config only holds a path. The secret is in a file that isn't in the database, isn't in config exports and isn't in git.
Key's documentation is clear about where that file should live: outside the webroot, and not reachable over HTTP. Otherwise you've moved the secret from the database to a URL.
Where to put key files on a multisite
On a single server you'd create a directory above the docroot and be done. On Acquia Site Factory, the codebase is shared by every site, and a site can't have its own directory next to it. But each site does have its own private file system. It's outside the docroot, it's not accessible over HTTP, and Drupal already knows it per site as private://.
That gave every site a natural place for its own keys:
private://keys/searchstax-solr-connector.key
private://keys/searchstax-analytics.keySame paths on every site, different contents per site. The configuration that refers to the keys can then be identical across the whole platform, because nothing site-specific is in it anymore.
Rolling it out with two migrations
Doing this by hand meant opening two settings forms on every site, copying out tokens, creating files over SSH and pointing the settings at new keys. That's exactly the kind of manual work where one site ends up half done. So the rollout was two migrations that run on every site:
- Write the key files. Read the current Solr connector and analytics settings from the site's config, and write them to the two key files in that site's private file system.
- Switch the settings to Key. Once the files exist, select the new keys in the SearchStax Solr connector and the SearchStax settings, so both read from the files.
Splitting it in two kept each step easy to check: after the first one, every site should have two files. After the second, every site should be reading its tokens through Key. After the deploy, every site on the platform was using Key, and all tokens came from the key files.
Only as far as module support goes
Key only helps with modules that know how to use it. In our case, that was the SearchStax module, so that's where we started. Other integrations still keep their credentials in config until they gain Key support or we add it ourselves. It's worth checking that list before promising "all secrets are out of the database".
The trade-off: who can set up search
There's one operational change people should know about up front. Before, anyone with the right admin permission could paste a token into a form. Now the token is a file on the server, and creating or changing it needs server access. In practice, setting up search for a new site moved from the site builders to me.
That's a feature as much as a cost. Fewer people handle the tokens, and the place where they live is no longer copied with every backup. But tell the team before you deploy, not after the first time someone can't find the field.
Checklist
- Check which of your modules support Key before you plan the rollout.
- Use the file provider, and put the files outside the webroot. On Site Factory, the per-site private file system is the right place.
- Use the same key names and paths on every site, so the configuration can be shared.
- Migrate in two steps: write the files, then switch the settings. Verify after each.
- Remember that old database backups still contain the old tokens. Rotate them once the move is done.