Consul ACLs – an Introduction

// Steven Borrelli // Consul

HashiCorp’s Consul is a popular service discovery and key/value storage tool that has become a core component of many distributed applications.

However, if Consul is not secured an intruder could register their own service and capture traffic. For example, if you have an auth service, the intruder could register another service with the same DNS entry auth.service.consul and collect login information.

Consul does not implement access controls on the key-value data or service discovery endpoints by default. This means anyone (including intruders) are able to connect to a Consul host, register services, and modify data.

But don’t despair! Consul has an Access Control List (ACL) system that can be used to control who can read and write data. This means we can keep intruders from registering services without authenticating to the Consul server.

Introduction to Consul ACLs

Let’s take a look at a sample ACL. In this case we want to secure the vault key so that unauthorized users cannot write to it. We’ll assume Consul is configured to deny by default.

An ACL that allows write access to the vault key would look like this:

  "ID": "d414c3e6-c498-64fa-5a2e-1a942425a410",
  "Name": "control access to vault backend",
  "Type": "client",
  "Rules": "{\"key\":{\"vault\":{\"Policy\":\"write\"}}}"

Consul ACLs are composed of a “token” (shown as ID), a “name”, a “type”, and a set of “rules”.

The token is a unique value that should be hard to guess. In common practice Consul tokens are UUIDs, but they can be any value. You can generate uuids on most Unix-like systems with the uuid command:

$ uuid

The name is an optional description of the ACL, like control access to vault backend.

Rules can be one of three values: read, write and deny. When write is set the token will also be able to read.

One thing you’ll note is the rules from the example look a little odd in JSON. Let’s make it more readable:

  "key": {
    "vault": {
      "Policy": "write"

Here’s a more complex rule example. In this case we’ll have a default "" key policy of read and a deny policy on the vault key. We’ll also allow writes to the service discovery backend:

  "key": {
    "": {
      "policy": "read"
    "vault": {
      "Policy": "deny"
  "service": {
    "": {
      "policy": "write"

Token Types

There are three different types of Consul tokens:

Management tokens are similar to a UNIX “root” user. They can create, modify, and delete ACLs, and perform any action on the system. These should be used sparingly.

Client tokens are tokens that can only perform actions based on associated rules. A management token is required to create client tokens.

The third type of token is an anonymous token. Consul uses anonymous tokens for any unauthenticated request.

Using Tokens to Authenticate to Consul

In order to be able to get data from an ACL protected resource, you’ll need to supply a token.

Consul Command Line Client

Consul commands use the -token parameter or the CONSUL_TOKEN environment variable. If not supplied, consul will use the agent’s token.

$ consul watch -token="d414c3e6-c498-64fa-5a2e-1a942425a410" -type=key -key=my/watch /usr/bin/

Consul Agents

Consul agents can be configured to automatically use a token by creating a json file (like agent-acl.json) in the consul configuration directory:

  "acl_token": "d414c3e6-c498-64fa-5a2e-1a942425a410"

Using Tokens with curl

There are a two ways to send Consul tokens when making API calls, either via a named parameter token, or using the X-Consul-Token header.

$ curl -is localhost:8500/v1/agent/self?token=abc123

$ curl -is localhost:8500/v1/agent/self -H "X-Consul-Token: abc123"

The preferred method is using the X-Consul-Token method, as the token is less likely to be captured in http or proxy logs.

Using Tokens with consul-cli

Asteris, in partnership with Cisco, has developed consul-cli, which makes it easier to work with Consul servers.

For consul cli, the token can be set via the CONSUL_HTTP_TOKEN environment variable or by using the --token cli option:

$ consul-cli acl list --token=ccc67226-2462-4804-b944-4d728c7bad03


In this post we learned:

Want More Sleep?

Is your deployment keeping you up a night? Is it secure? Reliable? We'll help you keep the lights on with timely tutorials and tips to give you peace of mind that your cluster is running how it's supposed to.