Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

The Variable Vault

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

The symfony_secret variable needs to be secret! I don't want to commit things like this to my repository in plain text!

Creating the Vault

One really cool solution to this is the vault: an encrypted variables file.

To create a vault file, go back to your main machine's terminal and run:

ansible-vault create ansible/vars/vault.yml

It'll ask you to create a vault password. We'll use - of course - beefpass. Keep this handy: it's needed to decrypt the vault.

Nice! It opens up an editor. Once you're inside, treat this like a normal variable file: add ---, then a new variable: vault_symfony_secret:

# ansible/vars/vault.yml
---
vault_symfony_secret: 

I am purposely starting the variable name with vault_ - we'll talk about why in a minute.

Then, set the value to udderly secret $tring:

# ansible/vars/vault.yml
---
vault_symfony_secret: "udderly secret $tring"

Save with :wq Enter.

As soon as we do that, we have a vars/vault.yml file... and it is not human-readable: it's encrypted:

$ANSIBLE_VAULT;1.1;AES256
62313836626639653563363463316530346563316361316633613938626563373934363834336639
3735343165343739653866643763376431666239643435330a343234396138373965323537633333
61616261336138356436663266383533373166393837373561393365363130633864323262333531
6563633238636465640a643337316361393132633963303361653434613462353363373234336333
38636163653630343665363537663334643137626336633435336566316565623464346239343961
61366666636131373164316436396664646437353635343464653030626432373939353439353433
633563663465306666303638663931666637

You can use the vault again to view it:

ansible-vault view ansible/vars/vault.yml

It, of course, needs your password: beefpass. Or, you can edit it:

ansible-vault edit ansible/vars/vault.yml

Importing the vault File

In vars.yml, we can now remove the secret string and use the variable instead: {{ vault_symfony_secret }}:

---
... lines 2 - 5
symfony_secret: "{{ vault_symfony_secret }}"

To make that variable available, import it like a normal variable file: vars/vault.yml:

---
- hosts: vb
vars_files:
- ./vars/vault.yml
- ./vars/vars.yml
... lines 7 - 171

Make sure the vault is loaded first so we can use its variables inside vars.yml.

Let's walk through this: import vault.yml, then in vars.yml use the vault_symfony_secret variable to set symfony_secret. Then, that variable is used elsewhere.

Why the big dance? Why not just call the variable symfony_secret in the vault? Well, the vault_ prefix is nice because it's really easy to know that it came from the vault. That makes it easier to track things down.

Running a Vaulted Playbook

Let's try it! Run the playbook like before, with -t deploy and a new flag: --ask-vault-pass:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -t deploy --ask-vault-pass

Nice! Enter beefpass for the password, use the prod environment, then let it run! Nice! The "Set Symfony secret in parameters.yml" task reported Changed!

In the VM, let's check out that file:

cat app/config/parameters.yml
# app/config/parameters.yml
# This file is auto-generated during the composer install
parameters:
    # ...
    secret: udderly secret $tring
    # ...

Woohoo! There's our ridiculous secret string.

Using a Secret Loggly Token

Let's do one more fun example. In your browser, remove the app_dev.php from the URL. It still works!

Now, open app/config/parameters.yml. The last key is called loggly_token:

# app/config/parameters.yml
# This file is auto-generated during the composer install
parameters:
    # ...
    loggly_token: 12345
    # ...

This is used in config_prod.yml:

... lines 1 - 9
monolog:
handlers:
... lines 12 - 21
loggly:
... line 23
token: '%loggly_token%'
... lines 25 - 26

Basically, in the prod environment, the system is already setup to send all logs to Loggly: a cloud log collector. Right now... there's not too much in my account.

The only thing we need to do to get this to work is replace this line in parameters.yml with a working Loggly token. That's perfect for the vault!

Adding more to the Vault

Edit the vault!

ansible-vault edit ansible/vars/vault.yml

Add a new variable - vault_loggly_token:

---
# ...
vault_loggly_token:

I'll paste a real token for my account and save:

---
# ...
vault_loggly_token: fb4aa5b2-30a3-4bd8-8902-1aba5a683d62

And as much fun as it would be for me to to see all of your logs, you'll need to create your own token - I'll revoke this one after recording.

We know the next step: open vars.yml and set loggly_token to vault_loggly_token:

---
... lines 2 - 6
loggly_token: "{{ vault_loggly_token }}"

And finally, we can use loggly_token in symfony-bootstrap.yml. Copy the previous lineinfile task, paste it, and rename it to "Set Loggly token in parameters.yml":

... lines 1 - 20
- name: Set Symfony secret in parameters.yml
... lines 22 - 28
- name: Set Loggly token in parameters.yml
... lines 30 - 66

Update the keys to loggly_token, and the variable to loggly_token:

... lines 1 - 28
- name: Set Loggly token in parameters.yml
lineinfile:
dest: "{{ symfony_root_dir }}/app/config/parameters.yml"
regexp: "^ loggly_token:"
line: " loggly_token: {{ loggly_token }}"
tags:
- deploy
... lines 36 - 66

Ok, try it!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -t deploy --ask-vault-pass

Fill in beefpass and use the prod environment again.

Ding! Head to your VM and look at the parameters.yml file:

cat app/config/parameters.yml

Nice! So... it should work, right? Refresh Mootube to fill in some logs. Now, reload the Loggly dashboard. Hmm... nothing! What's going on?

Actually, we have another mistake in our playbook. Once again, I got too smart! We only clear the cache when the code has changed:

---
... lines 2 - 59
- name: Clear cache
... lines 61 - 64
when: code_changed

But in this situation, parameters.yml changed... which is not technically part of our code. In other words, this isn't working because we have not yet cleared our prod cache.

I'll comment out the when under "Cache Clear" to make it always clear. Then, just for right now, in the VM, clear the cache manually:

./bin/console cache:clear --env=prod

If you get an error about permissions, that's fine: it's just having problems clearing out the old cache directory. You can delete that:

sudo rm -rf var/cache/pro~

Let's see if that was the problem! Refresh MooTube. Then, try the Loggly dashboard. Got it! So cool! If you're coding with me, it might take a few minutes to show up, so be patient!

Our playbook is really powerful. Could we use it to deploy to a cloud server like AWS? Why not!? Let's do it!

Leave a comment!

2
Login or Register to join the conversation
Default user avatar
Default user avatar Huimin ZENG | posted 5 years ago

Thanks for the sharing, but this doesn't work for me....
I just keep getting "Attempting to decrypt but no vault secrets found". I also opened an issue at github. I will appreciate it, if you could please have a look. Here is the link: https://github.com/ansible/...

Reply

Hey Huimin,

I see you include your vault as:


  vars_files:
    - vault.yml
    - vars.yml

Are those files with your playbook in the same directory? If so, can you try to add a "./" before each file like:


  vars_files:
    - ./vault.yml
    - ./vars.yml

Also, how do you execute your playbook? Do you use "--ask-vault-pass" option like?


ansible-playbook ./playbook.yml -i ./hosts.ini --ask-vault-pass

I personally didn't see this issue before, probably you're doing something wrong. Btw, could you upgrade to the latest Ansible version?

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built using an older version of Symfony, but the core concepts of Ansible are still valid. New versions of Ansible may contain some features that we don't use here.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.12
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.0
        "snc/redis-bundle": "^2.0", // 2.0.0
        "predis/predis": "^1.1", // v1.1.1
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.8
        "symfony/phpunit-bridge": "^3.0", // v3.1.4
        "doctrine/data-fixtures": "^1.1", // 1.3.3
        "hautelook/alice-bundle": "^1.3" // v1.4.1
    }
}
userVoice