Using & Overriding Secrets

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

We have successfully added the SENTRY_DSN secret value to both the dev and prod vaults.

Listing the Secrets

How can I prove that? By running:

php bin/console secrets:list

Because we're in the dev environment, this reads the dev vault. There's our one secret. To see its value, add --reveal:

php bin/console secrets:list --reveal

Behind-the-scenes, that used the dev "decrypt" key to decrypt the value: it's an empty string. Ignore this "local value" thing for a minute.

We can do the same thing for the prod vault by passing --env=prod:

php bin/console secrets:list --env=prod

Including adding --reveal to see the value.

php bin/console secrets:list --env=prod --reveal

Reading Secrets in your App

Ok: because we're in the dev environment, the dev secret - the empty string - is the one that should be used. Refresh the page, check the dump, and expand it a few times. It's still using the production value.

Go back into config/packages/sentry.yaml:

sentry:
dsn: '%env(SENTRY_DSN)%'

We're still using the syntax for reading environment variables. How can we tell it to read the SENTRY_DSN secret instead? Surprise! To tell Symfony to read a SENTRY_DSN secret, we use the exact same syntax.

Environment Variables vs Secrets

Let me explain: when Symfony sees the %env()% syntax, it first looks to see if an environment variable called SENTRY_DSN exists. If it does, it uses it. If there is not, it then looks for a secret in the vault called SENTRY_DSN. So reading environment variables and secrets uses the same syntax, but environment variables take priority.

This means one important thing: when you identify an environment variable that you want to convert into a secret, you need to remove it entirely as an environment variable. Set a value as an environment variable or a secret, but not both. Delete the SENTRY_DSN entry from .env and .env.local:

26 lines .env
... lines 1 - 22
###> sentry/sentry-symfony ###
SENTRY_DSN=
###

2 lines .env.local
SENTRY_DSN=https://7f45741877f3498eab0ae2bee6463d57@o372370.ingest.sentry.io/5186941

Now Symfony should be read from our dev vault. Refresh... expand the object and... yes! All the values are null! It works!

Let's try out production. Until now, to switch to the prod environment, I've been updating the .env file:

26 lines .env
... lines 1 - 15
###> symfony/framework-bundle ###
APP_ENV=dev
... lines 18 - 20
###
... lines 22 - 26

But now that we understand .env.local, let's add APP_ENV=prod there instead:

2 lines .env.local
APP_ENV=prod

Next, clear your cache:

php bin/console cache:clear

Then spin back to your browser and refresh. This time the dump is on top. If I expand it... yes! It's using the production values. Booya! That works because my project has the prod decrypt key. If that was not there, we would get an error.

Go ahead and take out the APP_ENV= line in .env.local to get back to the dev environment:

2 lines .env.local
APP_ENV=prod

And in QuestionController, let's cleanup: remove the dump(), the new Exception and the HubInterface argument:

... lines 1 - 12
class QuestionController extends AbstractController
{
... lines 15 - 42
public function show($slug, MarkdownHelper $markdownHelper)
{
if ($this->isDebug) {
$this->logger->info('We are in debug mode!');
}
$answers = [
'Make sure your cat is sitting `purrrfectly` still 🤣',
'Honestly, I like furry shoes better than MY cat',
'Maybe... try saying the spell backwards?',
];
... lines 54 - 62
}
}

After this... things are working again.

Overriding Secrets Locally

You are now ready to use Symfony's secrets system. But! The fact that environment variables take precedent over secrets is something that we can use to our advantage.

Find your terminal and run:

php bin/console secrets:list --reveal

In the dev environment, the SENTRY_DSN value is set to an empty string. Let's pretend that, while developing, I want to temporarily set SENTRY_DSN to a real value so I can test that integration.

We could use secrets:set to override the value... but that would update the secrets file... and then we would have to be super careful to avoid committing that change.

There's a better way. In .env.local, set SENTRY_DSN to the real value. Well, I'll put "FOO" here so it's obvious when this value is being used.

Now run that command again:

php bin/console secrets:list --reveal

The "Value" is still empty quotes, but now it has a "Local Value" set to the string we just used! The "Local Value" is the one that will be used. Why? Because our new environment variable overrides the secret: environment variables always win over secrets. This "Local Value" is a fancy way of saying that.

I'll take that value out of .env.local so that my secret is once again used.

Next: let's have some fun! We're going to install MakerBundle and start generating some code!

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.2.5",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "knplabs/knp-markdown-bundle": "^1.8", // 1.8.1
        "sensio/framework-extra-bundle": "^5.5", // v5.5.4
        "sentry/sentry-symfony": "^3.4", // 3.4.4
        "symfony/asset": "5.0.*", // v5.0.8
        "symfony/console": "5.0.*", // v5.0.8
        "symfony/debug-bundle": "5.0.*", // v5.0.8
        "symfony/dotenv": "5.0.*", // v5.0.8
        "symfony/flex": "^1.3.1", // v1.6.2
        "symfony/framework-bundle": "5.0.*", // v5.0.8
        "symfony/monolog-bundle": "^3.0", // v3.5.0
        "symfony/profiler-pack": "*", // v1.0.4
        "symfony/twig-pack": "^1.0", // v1.0.0
        "symfony/var-dumper": "5.0.*", // v5.0.8
        "symfony/webpack-encore-bundle": "^1.7", // v1.7.3
        "symfony/yaml": "5.0.*" // v5.0.8
    },
    "require-dev": {
        "symfony/maker-bundle": "^1.15", // v1.15.0
        "symfony/profiler-pack": "^1.0" // v1.0.4
    }
}