---
layout: docs
page_title: Use Vault for ACL management with Consul on VMs
description: >-
  Configure the Consul secrets engine in Vault to deliver Vault-managed Consul Access Control tokens.
---

# Use Vault for ACL management with Consul on VMs

HashiCorp's Vault has a secrets engine for generating short-lived Consul tokens, the [Consul Secrets Engine](/vault/docs/secrets/consul). This engine generates Consul Access Control (ACL) tokens dynamically based on Consul ACL policies.

<Tip title="Vault token consideration">

 This tutorial uses Vault `root` token to perform the Vault related operations including the Consul token generation. In practice, use [authentication methods](/vault/tutorials/auth-methods) to validate the identity of the users or orchestration systems to acquire a token from Vault instead of using the `root` token for non-development environments.

</Tip>

In this tutorial, you will configure the Consul secrets engine in Vault to generate Consul tokens.

The integration with Vault's Consul secrets engine has the following workflow,

1. create a Consul ACL policy to define tokens' privileges
1. create a Vault role to map the policy
1. create a token with Vault
1. verify that the token got synced with Consul

Before using this workflow, you must bootstrap the Consul ACL system and configure the Vault's Consul secrets engine, the tutorial provides you with steps for both requirements.

## Prerequisites

- **Consul:** to complete this tutorial, you can use a [local Consul dev agent](/consul/tutorials/get-started-vms/virtual-machine-gs-deploy) or an existing Consul deployment.
- **Vault:** this tutorial assumes you already have a running Vault cluster in your network. You can use a [local Vault dev server](/vault/tutorials/getting-started/getting-started-dev-server) or an existing Vault deployment.

The diagram below shows the minimal architecture needed to demonstrate the functionality.

![Architectural diagram showing a Consul server and a Vault server with an operator issuing a command to start an automation](/img/vault-consul/consul-vault-acl.png)

<InteractiveLabCallout />

<Note title="Security Warning">

 This tutorial is not for production use. By default, the lab will install an insecure configuration of Consul.

</Note>

### Configure Consul ACL

As a prerequisite for the integration you must bootstrap the Consul ACL system in your datacenter.

#### ACL configuration file

To be able to configure Consul tokens and policies, you will need to enable ACLs in your Consul datacenter using a configuration similar to the following:

```hcl
# ACL configuration
acl = {
    enabled = true
    default_policy = "deny"
    enable_token_persistence = true
}
```

Verify that the Consul server started correctly by checking the logs. You should get a log message like the following when ACLs are correctly enabled:

```log hideClipboard
agent.server: initializing acls
```

#### Bootstrap the ACL system

First, configure your environment to be able to interact with the Consul agent.

```shell-session
$ export CONSUL_HTTP_ADDR=localhost:8500
```

Then, bootstrap the ACL system to start using tokens.

```shell-session
$ consul acl bootstrap | tee consul.bootstrap

AccessorID:       e57b446b-2da0-bce2-f01c-6c0134d8e19b
SecretID:         bba19e7c-9f47-2b08-f0ea-e1bca43ba9c5
Description:      Bootstrap Token (Global Management)
Local:            false
Create Time:      2020-02-20 17:01:13.105174927 +0000 UTC
Policies:
   00000000-0000-0000-0000-000000000001 - global-management
```

<Warning title="Security Warning">

 In this tutorial, you are redirecting the output of the `consul acl bootstrap` command to a file to simplify operations in the next steps. In a real-life scenario, you should ensure the bootstrap token is stored securely. If it is compromised, the ACL system can be abused.

</Warning>

Finally, set the token for the command using the `CONSUL_HTTP_TOKEN`
environment variable.

```shell-session
$ export CONSUL_HTTP_TOKEN=$(cat consul.bootstrap | grep SecretID | awk '{print $2}')
```

You can now use the bootstrap token to create other ACL policies and tokens for the rest of your datacenter. You will also use the same token to configure the Vault secrets engine.

<Warning title="Production check">

 At this time you only have one token in Consul; the _bootstrap token_. While it is possible to use only this token for all the configuration in a testing or dev environment, it is not recommended for a production environment. This token should only be used for the initial ACL setup, and to create tokens with lower permissions.

</Warning>

## Configure the Consul secrets engine in Vault

In order to communicate with the Vault server, you will need to set the address and token.

```shell-session
$ export VAULT_ADDR='http://127.0.0.1:8200'
```

```shell-session
$ export VAULT_TOKEN="root"
```

#### Enable secrets engine

The Consul secrets engine must be enabled before it can perform its functions.

```shell-session
$ vault secrets enable consul

Success! Enabled the consul secrets engine at: consul/
```

#### Configure secrets engine access

Once you have the Consul secrets engine enabled, configure access with Consul's address and management token.

```shell-session
$ vault write consul/config/access address=${CONSUL_HTTP_ADDR} token=${CONSUL_HTTP_TOKEN}

Success! Data written to: consul/config/access
```

## Create a Consul server policy

Once the ACL system is initialized, you should still observe warnings in your Consul logs similar to the following example.

```log hideClipboard
 [WARN]  agent: Node info update blocked by ACLs: node=c19d6af9-760b-a3cc-bbdd-b4f7209a79de accessorID=00000000-0000-0000-0000-000000000002
 [WARN]  agent: Coordinate update blocked by ACLs: accessorID=00000000-0000-0000-0000-000000000002
```

These warnings indicate that:

- the agent is trying to update its info in your Consul datacenter, but has been denied by the ACL system because it does not have the correct permissions.
- the agent does not have an assigned token to perform the request (because `00000000-0000-0000-0000-000000000002` is the anonymous policy used when no token is presented)

The first step towards a more fine grained ACL approach is to create individual tokens for the server agents so that they can interact properly with the rest of the Consul datacenter without being assigned an administrative token.

For this tutorial, you will create a policy that permits server agents to register themselves. The servers will follow the naming pattern `server-<count_or_id>`, and have the necessary permissions to locate other agents and discover services.

This policy will be used by Vault when creating tokens for Consul.

Create a file named `server_policy.hcl`with the following content.

<CodeBlockConfig filename="server_policy.hcl">


```hcl
node_prefix "server-" {
  policy = "write"
}
node_prefix "" {
  policy = "read"
}
service_prefix "" {
  policy = "read"
}
```

</CodeBlockConfig>


Create the policy with the `consul acl` command.

```shell-session
$ consul acl policy create \
  -name consul-servers \
  -rules @server_policy.hcl
```

Once the policy is created you need to associate it to a token in order to use it.

<Tip>

 In a standalone scenario, where Vault is not deployed yet, you can still configure your ACL system by creating tokens in Consul. You can use the `consul acl token create` command or the `/acl/token` REST API resource.

</Tip>

## Create a Vault server role

In the previous step, you created a policy named `consul-servers` to define the server agents' permissions.

You are going to use that policy when creating tokens for Consul servers.

If you want to generate numerous tokens with identical policies we recommend you associate each policy with a common role.

Roles allow you to group a set of policies and service identities into a reusable higher-level entity that can be applied to many tokens.

For this tutorial, you are going to configure a role that maps a name
in Vault to a set of Consul ACL policies. If users generate credentials associated with this role, they will be associated with the policies of that role.

```shell-session
$ vault write consul/roles/consul-server-role policies=consul-servers

Success! Data written to: consul/roles/consul-server-role
```

<Warning>

 The tokens will only be associated with the policies that are represented by the role at token creation time. If you change the role configuration, for example by associating it with a new policy, the change will only be reflected by the tokens you generate after it. Previous tokens will not be affected. This prevents you from mistakenly associating extra permissions to pre-existing tokens.

</Warning>

## Obtain and test a Consul ACL token

#### Create token from Vault

Create a Consul token using the existing Vault token.

```shell-session
$ vault read consul/creds/consul-server-role | tee consul.server

Key                Value
---                -----
lease_id           consul/creds/consul-server-role/bHDVG24vCO8BJ90ONjxrbKP6
lease_duration     768h
lease_renewable    true
accessor           2b9bb86a-d632-ea28-3890-7d1e0690ff57
local              false
token              5ea5eadc-807d-68c2-e47f-a1ac37e906b7
```

#### Verify token was created in Consul

Verify that the token is created correctly in Consul by looking it up by its accessor.

```shell-session
$ export CONSUL_SERVER_ACCESSOR=$(cat consul.server | grep accessor | awk '{print $2}')
```

```shell-session
$ consul acl token read -id ${CONSUL_SERVER_ACCESSOR}

AccessorID:       2b9bb86a-d632-ea28-3890-7d1e0690ff57
SecretID:         5ea5eadc-807d-68c2-e47f-a1ac37e906b7
Description:      Vault consul-server-role token 1598547759570180867
Local:            false
Create Time:      2020-08-27 17:02:39.572006543 +0000 UTC
Policies:
   6fa2c574-6951-51db-310a-672e328f2aba - consul-servers
```

Any user or process with access to Vault can now create
short lived Consul tokens in order to carry out operations,
thus centralizing the management of Consul tokens.

### Understand the differences in token representations

The way Vault and Consul refer to tokens in the command output is slightly different. The following table expresses the relationship between the two outputs.

| Consul       | Vault      | Meaning                                                       |
| ------------ | ---------- | ------------------------------------------------------------- |
| `AccessorID` | `accessor` | The unique identifier for the token inside Consul and Vault.  |
| `SecretID`   | `token`    | The actual token to be used for configuration and operations. |

Using the Consul secrets engine with Vault ensures that these values are kept consistent when the tokens are replicated to Consul.

## Set Consul server agent token

For this tutorial you saved the token inside the `consul.server` file.

You can retrieve it and store it in an environment variable.

```shell-session
$ export CONSUL_SERVER_TOKEN=$(cat consul.server | grep token | awk '{print $2}')
```

Finally, register the token with the server as its `agent` token.

```shell-session
$ consul acl set-agent-token agent $(cat consul.server | grep token | awk '{print $2}')

ACL token "agent" set successfully
```

Once the token is applied, check the Consul logs once more and verify that the warning lines are not being logged anymore.

```log hideClipboard
...
[INFO]  agent: Updated agent's ACL token: token=agent
[INFO]  agent: Synced node info
...
```

## Token lease duration and rotation

Using Vault's secret engine you can uniform the process of token creation using Vault but you will still need to take care of token rotation inside your Consul datacenter.

The tokens created using the integration with Vault's Consul secrets engine are created with a Time To Live (TTL) of 30 days.

You can verify the lease duration and expiration time on Vault UI:

![Vault UI Consul tokens](/img/vault-consul/vault-ui-consul-token-lease.png)

At this moment this value is not configurable, the recommended approach for operators is to rotate the tokens by creating a new token using:

```shell-session
$ vault read consul/creds/consul-server-role
```

and then, once the token is synchronized with Consul apply the token to the agents using the `consul acl` command as showed earlier in this tutorial.

Rotating tokens is a core activity for keeping your Consul datacenter secured against secrets leaking. You should consider defining an internal policy that regulates the rotation interval and make sure is respected.

## Next steps

In this tutorial, you configured Vault's Consul secrets engine so that you could generate Consul tokens using Vault.

To continue securing your datacenter with Vault, you can follow [Generate mTLS Certificates for Consul using Vault](/consul/tutorials/vault-secure/vault-pki-consul-secure-tls) tutorial.

To learn how to configure gossip encryption for Consul using Vault for secrets storage and management, refer to the [Secure Consul gossip communication with Vault](/consul/tutorials/vault-secure/vault-kv-consul-secure-gossip) tutorial.