Advices on AppRole use with Ansible

Hi !

I set up a Vault server mainly to store secrets and to enable access to a dedicated server (an Ansible server, which can only access, read secrets and then use them inside a playbook).

I manually succeed to create a Policy, an AppRole and link them together from vault CLI.

My policy is quite easy, it just allows read and list capabilities on a path.
My AppRole is quite easy too as it just restrict the use from a single IP address (my ansible server) and set token ttl to 1h.

Then, i’m manually able to retrieve RoleID, write a SecretID and then generate a token that i can use from Ansible server, inside a playbook.

Here’s some interrogation :
At the moment, to generate token for my AppRole, i must manually connect to my Vault server (and use root token which isn’t a good thing i guess) then launch those commands :

vault read auth/approle/role/My-approle/role-id
vault write -force auth/approle/role/My-approle/secret-id

vault write auth/approle/login role_id="xxxxxx" secret_id="YYYYYYY"

First of all, is it possible to avoid to use root token to authenticate to my vault server ?

In a second time, is it possible to automatically retrieve (if allowed) an approle token from my Ansible server ?

Thanks a lot for your help and ideas.

Gael

Hi @motorbass,

Yes, you’re right. You shouldn’t be using your root token for normal daily operation. Ideally, you should have an admin role with create/read/update/delete/list/patch/sudo access to most configuration endpoints but not all of them (which is essentially what the root token’s policy does).

Now, you may want to start with a restricted admin policy and add capabilities to it as you go (you’ll need the root token for that) or just try to figure out 99% of all possible use-cases that you may have and configure that policy right from the start.

Check out this great Vault policy guide for more info.

Specifically about your use case above, to generate a new secret-id for your AppRole, you’ll need to know its role_name and have the permissions create and update on the path /auth/approle/role/:role_name/secret-id.

If you’re gonna be managing multiple AppRoles, you may want to include the below in your admin policy (you may also want to tweak it a little bit):

# List all available AppRoles
path "auth/approle/role" {
  capabilities = ["list"]
}

# Manage all AppRoles and Secrets IDs
path "auth/approle/role/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

You may also consider Secret ID response wrapping as described in this blog for a more secure approach (but it’s not mandatory for this to work).

Once you have the role-id and the secret-id, the app that will be authenticating against Vault (Ansible), will need to POST those to /auth/approle/login to get a client token (Reference).

One way of achieving that is to run Vault agent on your Ansible server with auto-auth to retrieve the client token and store it somewhere locally where Ansible would have access to.

Alternatively, you could try adding Vault lookups to your playbooks.

1 Like

Hi @macmiranda
Wow that is a great explanation, thanks a lot , it’s really clear, thanks a lot !

(One thing i may not understand 100% is that, token retrieved by an approle should still be generated manually ? for instance i create an admin role which i retrieve a token to make common action. i still have to get it manually before login into vault)

Just a confirmation about the Secret ID part: as the SecretID act as a password, and as you need to “write” it once you get the RoleID, does it mean that I have to “write” it thanks to admin token/account in order to retrieve an approle token that i can use in app ?
What i mean is, i still need a manual part to generate token for my approle ?

I usually use “lookup” in Ansible, but the auto-auth feature with Vault agent seems quite interesting, i wasn’t aware of that.

You can think of the role-id and the secret-id as an OAuth app’s client_id and client_secret. They basically tell Vault, if a client is authenticating using these IDs, it’s ok to issue them a token (with the configured policy attached to it). You still need to store those IDs secretly even though they are not the token that you’ll be using in your following requests.

The token that is generated by the login operation has a few constraints that may require you to re-login (after a while). They are:

That’s something the Vault agent manages automatically for you. It’s able to renew a certain token until it reaches token_max_ttl and re-authenticate using the role-id and secret-id though you may need to set remove_secret_id_file_after_reading to false (I’m not particularly endorsing this though).

1 Like

You only need the second part of this policy, that covers listing AppRoles on its own, without the first part.

I would suggest also that you don’t include sudo in this policy, as it is redundant as well. The function of sudo is to make policy authors take extra notice when enabling access to special endpoints, so it loses its value if you add it in places where it does nothing.

1 Like

Think of it this way: The RoleID is a username. The SecretID is a password. All the AppRole auth method is really, is fancy usernames and passwords. Specifically, built-in ways to have the usernames and passwords auto-generated as random data, and support for multiple passwords on the same account. (Every time you write to the auth/approle/role/<rolename>/secret-id endpoint, a new password/SecretID is created. Do be aware of this, otherwise you can unwittingly end up with thousands of valid credentials, which is bad security hygiene.)

This means that something in your overall Ansible environment is going to have to perform an auth/approle/login operation when it starts running, use the resulting token for the duration of the playbook, and then discard it.

Bear in mind that the default kind of Vault token uses a small amount of storage on the Vault server side, until it expires. Perhaps not a big deal at first - but if you start having hundreds of playbook runs per hour, it can become a problem. In which case, revoke your tokens when they are no longer required, or use batch tokens (which are cryptographically signed certificates that aren’t stored on the Vault server side at all).

1 Like

Hi @maxb thanks a lot for all those details.

I better understand that my ansible server should authenticate first to Vault, and if authentication is successful, Vault give it a token corresponding to the AppRole (actually i’m able to do this/test manually at the moment)

I succeed to do it with curl cli and parsing with jq, it works pretty well.

The main interrogation, is how to manage the SecretID.
I mean, basically I got my playbook hosted on GitLab, with empty RoleID/SecretID. So it means everytime i want to execute it (after cloning) i have to tell Ansible to write a new SecretID, (thanks to my admin role for example) before requesting a token, and this step should be automatic ?

  • Should you generate a new SecretID (password) for each operation?

  • Or just do it once and re-use it forever?

That’s entirely up to you - whatever suits your environment and security properties.

I normally like to separate the paths. One could use a single auth/approle/* path though.
If you need to LIST auth/approle/role (no trailing slash), the path auth/approle/role/* isn’t enough.

Can’t remember why I thought it was needed for tidying up secret-ids but, in any case, it would have a different path: /auth/approle/tidy/secret-id. Will remove it from the original comment. Thanks.

1 Like

But it is, though, because Vault implicitly and automatically forces a trailing slash on all list operations before they reach the policy layer. (And then it also tries chopping the trailing slash off again if no policy matches… but it only does this if the path is matched without + wildcards… which can be very confusing.)

Here is some more details I wrote previously about this topic: Documentation: unclear meaning of "list" capability in policy page · Issue #13011 · hashicorp/vault · GitHub

1 Like

:scream:

And no one at Hashicorp thought for a second of documenting that!?

Sadly, more often than I would like, the best documentation for Vault is reading the source code itself.

@macmiranda @maxb thanks a lot for your insights and your help guys, i do really appreciate !

Week end is over and everything is working (and almost crystal clear to me) on monday :slight_smile:

1 Like