Consul ACLs – an Introduction
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
524ab698-a53b-11e6-bffb-0242ac110003
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/my-key-handler.sh
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
Summary
In this post we learned:
-
the types of consul tokens (anonymous, management, and agent)
-
how to send a token with an API request