It's been a while. Let's not make a big thing out of it.

I've just finished setting up Hashicorp Vault in my lab and figure a brain dump of what I learnded would useful.

The base install was done via docker. Nothing particularly complicated, and plenty of guides out there.

As usual, I would like to link this back to my ldaps servers. Here's one I did earlier.

Unseal the vault and login. Enable a new secrets engine, of type "KV". This will store key/value pairs.

Click next. Under "Path", type in an identifier string. In this instance, we will use ansible-secrets. Under "Method Options", make sure Version 2 is selected. Enter a description if you wish, and click on "Enable Engine".

You will now see "ansible-secrets" on the Secrets Engines tab.

Click on it, and create a new secret. This secret can contain multiple key/pair values. I created a new secret called "zato" and added a few keypairs.


Note "ansible-secrets/zato" is the path to these secrets, and is indicated on screen. This will be handy later.

LDAP Config

Ok, now let's enable LDAPS up in here.

A bit of context. I want to allow logins using my Active Directory accounts, and I want to assign policies based on groups from my domain. A policy defines what a group is permitted to do. We haven't defined a policy yet, so let's do that. I've already created the groups in AD and named them "hv-vault-admins" and "hc-vault-readonly". Pretty self explanatory what each group will be used for".

Click on "Policies -> Create ACL Policy -> Name it 'admin-policy'" and insert the following text:

# Read/write all ansible secrets
path "ansible-secrets/*"
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]

For path, we've defined "ansible-secrets/*" to indicate that this policy applies all secrets under the ansible-secrets path. For capabilities, we're essentially giving full access to do pretty much anything.

Now repeat the process, and create a new policy named "secret-reader" and give it the following text:

# Read/List all ansible secrets
path "ansible-secrets/*"
  capabilities = ["read", "list"]

Ok, now let's get ldap set up.

Click on "Access -> Auth Medthods ->  Enable new method -> Select LDAP -> leave the default text of "ldap" -> Click "Enable Method". Edit the configuration as follows:

For testing, you may want to increase the tokens life as its pretty short by default.

Note, I'm using ldap over ssl, and have provided my root ca certificate. Click save.

This is enough to allow you to log in with any domain account. To manage permissions, or in this instance, policies, we need to bind our active directory groups to hashicorp vault policies. This felt needlessly convoluted, but here's the process.

First, go to "Access -> Auth Methods -> ldap -> Create group"

You'll want 2 groups created here. The names here should match the names you gave the associated AD groups. Leave policies BLANK and save.

Next, go to "Access -> Groups -> Create group". Create 2 groups. They can be named whatever.

The type should be "external" and under policies, assign one of the polcies you created earlier and click save.

Then click on "Aliases -> Add alias -> Name it to match you AD group -> Auth Backend set to ldap/ (ldap)".

Do the same for both groups.

You should now be able to log in to the web ui and be able to view the secrets you originally created.


Use in Ansible Playbook

Ok, finally, using it in a playbook.

You'll want to install hvac via pip, and the hashi_vault plugin on your Ansible control node.

# Use whicever works for you. Throw sudo at it if it doesn't work.
pip install hvac
pip3 install hvac

# Install hashi_vault plugin
ansible-galaxy collection install community.hashi_vault

Cool. Now, we want to set a couple environment variables. The first will point to our hashicorp vault server, and the second will be an api token. Log in to your hashicorp vault webui -> click on the profile icon in the top right -> Copy Token.

Type the following on your ansible control node.

export VAULT_ADDR=https://<hashi-corp-vault-url>.com
export VAULT_TOKEN=<copied-token>

Hopefully you set a sane token lifetime for the purpose of this test......

Next up, well want to run a playbook to pull a value from our hc-vault. Here's how we do that.

- name: Lookup and Output Specific Secret from Vault
    msg: "{{ lookup('hashi_vault', 'secret=ansible-secrets/data/zato') }}"

NOTE: If, as suggested earlier, you set the KV engine to be version 2, your path will look like the above with /data/ sandwitched between the path to the secrets.

Well, that's cool and all, but how about an actually useful task in ansible? Ok. How about populating passwords into a jinja2 template? Yeah, Ok. Here's how we do that.

Create a template in your ansible playbooks template directory. Here's the one I'm using for this guide.

ZT_SSH_PASSWORD={{ lookup('hashi_vault', 'secret=ansible-secrets/data/zato:ssh') }}
ZT_WEB_ADMIN_PASSWORD={{ lookup('hashi_vault', 'secret=ansible-secrets/data/zato:webui') }}
ZT_IDE_PUBLISHER_PASSWORD={{ lookup('hashi_vault', 'secret=ansible-secrets/data/zato:idepublisher') }}
ZT_ODB_PASSWORD={{ lookup('hashi_vault', 'secret=ansible-secrets/data/zato:dbpassword') }}

Then in your playbook tasks, you'll want something like:

- name: Copy the dynamically generated .env file to host
    src: ./templates/env.j2
    dest: /home/deploy/zato/.env