Geek Culture
Published in

Geek Culture

Symfony secrets vault explained in less than 5 minutes

Learn how works Symfony’s vault for your production sensitive information while your coffee is cooling down

Photo by Brock Wegner on Unsplash

A bit of context

Keeping sensitive information in secured places has always been a bit tricky. Where do you store your production database password? Where do you store all the required credentials for your application to work? During my everyday job, I often have to set-up CIs (continuous integrations) and CDs (continuous delivery) with a multitude of tools. These can be Gitlab CI, Bitbucket CI or Github Actions for example. And dealing with sensitive information is always a challenge.

Indeed, you won’t store sensitive production information directly in your source code. It is a security breach, it is way too risky and it just doesn’t work if you’re working on an open-source project.

Talking about open-source, let’s remind that security should never be based on a black-box concept, and all common security algorithms like SHA and alike are open-source. Anybody can know exactly how they works, and it doesn’t mean it isn’t secured. In fact, it’s way more secured, because security researchers and curious people can spot security breaches and fix them.

Keys of Symfony vault

Since Symfony 4.4 (released November 2019), secrets management has been implemented directly in the framework. This powerful solution provides an integrated component to keep your sensitive information secret.

Note: we’re talking about information like database password, API keys, etc. We’re not talking about database encrypted columns, for which you must use other tools specialized for this, like this one.

Here is how it works. For each environment (dev, prod, etc), you’ll generate 2 keys in config/secrets/{env}:

  • One encryption key: to add new encrypted variables to your application ;
  • One decryption key: to retrieve these variables from the vault.

You can commit these two keys for the dev environment (as long as your dev environment doesn’t need sensitive information), and only the encryption key of the production environment. You must never commit the production decryption key to your versioning system. By committing the encryption key, it will allow any developer of the project to add and encrypt new variables for all environment, but nobody will be able to decrypt already existing production variables. That’s exactly what we want. Nobody actually needs the production decryption key, aside the production server itself.

The production decryption key must only be stored on your secured production server (and maybe securely backed up somewhere else), in the config/secrets/prod directory (you can also put the decryption key in an environment variable as described here). What’s powerful is you don’t need to memorize any kind of password nor passphrase. You just need to put the decryption key to the right place and Symfony will find it and do the work for you.

If you open the default .gitignore file at the root of your Symfony project, you may find the line config/secrets/prod/prod.decrypt.private.php , which will block you from committing this precious file.

If you need, at some point, to change the production decryption key (e.g. stolen key, a developper not working on your project anymore, etc), Symfony offers the secrets:generate-keys --rotate command to generate both new encryption and decryption keys, and automatically “migrate” all your current encrypted information to these new keys.

In practice, how does it work?

Each time you’re using the secrets:set command, Symfony prompts you to enter the value of your secret. Let’s say you’re providing your database password in a environment variable called DATABASE_PASSWORD. Once the information is typed, Symfony will use the encryption key (the one you can commit) to create a file named in the following format: {env}.DATABASE_PASSWORD.{hash}.php. This file can be committed to your versioning system. It contains the encrypted database password, and no one is able to read it without the decryption key (the one you must not commit). You can easily fill in which environment your variable is attached to with the usual command argument --env=dev|prod|your_env.

You can now reference this variable in your configuration files thanks to %env(DATABASE_PASSWORD)%, like you would do with unencrypted environment variables. In production, Symfony will use the decryption key that you copied manually earlier to get the value at runtime.

Just so you know: one file will be created for each variable, and existing ones are referenced in the file config/secrets/prod/prod.list.php. Simple as that!

Let’s conclude

There are many advantages with this vault:

  • Fully integrated to Symfony ;
  • You don’t have to remind any password or passphrase ;
  • Easy key-regeneration, if it’s compromised or you have a strict security policy ;
  • One key for encryption and one for decryption so developers can add new values to the vault without being able to access the actual vault content ;
  • Really easy to set up, in just a few minutes ;
  • And many more you’ll find while using this system!

Find more by reading the Symfony documentation about it.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store