New in Symfony 4.4: Encrypted Secrets Management
October 24, 2019 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Contributed by
Tobias Schultze,
Jérémy Derussé
Nicolas Grekas
in #33997.
Storing sensitive application information (passwords, tokens, certificates, etc.) is a challenging task. You cannot rely on traditional configuration files and you cannot rely either on environment variables. That's why in Symfony 4.4 we've added a new encryption-based feature to manage secrets.
Imagine that you want to keep the entire DATABASE_URL
content secret to
avoid leaking the database connection credentials. This is how you can do that:
Step 1. Generate the keys used to encrypt/decrypt secrets (this feature is based on a traditional public-key cryptography and uses the libsodium library):
1
$ php bin/console secrets:generate-keys
This command generates a pair of keys in config/secrets/dev/
(or
config/secrets/prod/
). The public key is used to encrypt secrets and you
should commit it to your shared repository. The private key should not be
committed to the repository and should not be shared in any way.
Step 2. Upload the private key to your remote server using SSH or any other
safe means and store it in the same config/secrets/<environment>/
directory.
Step 3. Create a new secret to store the contents of DATABASE_URL
:
1 2 3 4 5 6
$ php bin/console secrets:set DATABASE_URL
Please type the secret value:
> **************
[OK] Secret "DATABASE_URL" encrypted in "config/secrets/dev/"; you can commit it.
Each secret is stored in its own file inside the config/secrets/<environment>/
directory. You can commit these files to the repository because their contents
are not accessible unless you also have the private key.
That's all. Use this new secret as any other normal env var in your configuration files and Symfony will decrypt the value transparently when needed:
1 2 3 4 5
# config/packages/doctrine.yaml
doctrine:
dbal:
url: "%env(DATABASE_URL)%"
# ...
Repeat the step 3 for all the configuration values that you want to turn into
secrets. Use the other commands to complete the whole secret management
experience: secrets:remove
to delete secrets, secrets:list
to show all
the secrets managed by the application, generate-keys --rotate
to change the
existing keys by new ones and re-encrypt all secrets automatically, etc.
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
However, this blog post can be misleading for developer not well versed in security and should explain imho a bit better the context.
For a starter: what does this feature protect against?
A: It will not change anything for any attacker who gains access to the source code files on the server, can do remote-code-execution or even snoop on the in-memory executing code. It will otoh be useful to prevent the common case of developers storing passwords in plain within the codebase.
Then: why is this feature any safer than using env variables?
Why? Is this feature aimed for the cases where using environment variables is not possible? (Shared hosting, I imagine) Or has using environment variables (or locally stored .env files for that matter) for configuration strings is out of vogue now?
Is the goal to have separated encrypted sensitive data and key to decrypt this data in different folders but probably accessible from same point?
If someone change e.g. password to database then the new password must be committed to repository?
Maybe I missing something. I would by glad to clarify the benefits.
Thank you for the work you are doing
This feature is about making it easier to deal with secrets appropriately by using the same git workflow ppl are used to for the code (ie git).
They are part of deployment and should be managed totally separately.
Still, I'm not sure I'm fully convinced. Environment variables seem to be easier to override on different environments or installs.
I'll keep using environment variables for the time being, which are more tightly integrated with deployment mechanics and more standard anyway.
Not a huge fan of this being added to "best practices". I think it's a bit like going back to the days of "doing things the Symfony way instead of the industry standard way".
I guess all secrets should have its keys in the .env file that is committed?
I mean if I encrypt the env FOO='bar', in .env file I should include FOO= just for reference, right?