452 lines
15 KiB
Plaintext
452 lines
15 KiB
Plaintext
---
|
||
layout: docs
|
||
page_title: Securing Consul with ACLs
|
||
description: This guide walks though securing your production Consul datacenter with ACLs.
|
||
---
|
||
|
||
The [Bootstrapping the ACL System guide](/advanced/day-1-operations/acl-guide)
|
||
walks you through how to set up ACLs on a single datacenter. Because it
|
||
introduces the basic concepts and syntax we recommend completing it before
|
||
starting this guide. This guide builds on the first guide with recommendations
|
||
for production workloads on a single datacenter.
|
||
|
||
After [bootstrapping the ACL
|
||
system](/advanced/day-1-operations/production-acls#bootstrap-the-acl-system),
|
||
you will learn how to create tokens with minimum privileges for:
|
||
|
||
- [Servers and Clients](/advanced/day-1-operations/production-acls#apply-individual-tokens-to-agents)
|
||
- [Services](/advanced/day-1-operations/production-acls#apply-individual-tokens-to-services)
|
||
- [DNS](/advanced/day-1-operations/production-acls#token-for-dns)
|
||
- [Consul KV](/advanced/day-1-operations/production-acls#consul-kv-tokens)
|
||
- [Consul UI](/advanced/day-1-operations/production-acls#consul-ui-tokens)
|
||
|
||
~> **Important:** For best results, use this guide during the [initial
|
||
deployment](/advanced/day-1-operations/deployment-guide) of a Consul (version
|
||
1.4.3 or newer) datacenter. Specifically, you should have already installed all
|
||
agents and configured initial service definitions, but you should not yet rely
|
||
on Consul for any service discovery or service configuration operations.
|
||
|
||
## Bootstrap the ACL System
|
||
|
||
You will bootstrap the ACL system in two steps, enable ACLs and create the
|
||
bootstrap token.
|
||
|
||
### Enable ACLs on the Agents
|
||
|
||
To enable ACLs, add the following [ACL
|
||
parameters](/docs/agent/options#configuration-key-reference)
|
||
to the agent's configuration file and then restart the Consul service. If you
|
||
want to reduce Consul client restarts, you can enable the ACLs
|
||
on them when you apply the token.
|
||
|
||
```
|
||
# agent.hcl
|
||
{
|
||
acl = {
|
||
enabled = true
|
||
default_policy = "deny"
|
||
enable_token_persistence = true
|
||
}
|
||
}
|
||
```
|
||
|
||
~> Note: Token persistence was introduced in Consul 1.4.3. In older versions
|
||
of Consul, you cannot persist tokens when using the HTTP API.
|
||
|
||
In this example, you configured the default policy of "deny", which means you
|
||
are in allowlist mode. You also enabled token persistence when using the HTTP
|
||
API. With persistence enabled, tokens will be persisted to disk and
|
||
reloaded when an agent restarts
|
||
|
||
~> Note: If you are bootstrapping ACLs on an existing datacenter, enable the
|
||
ACLs on the agents first with `default_policy=allow`. Default policy allow will
|
||
enable ACLs, but will allow all operations, allowing the cluster to function
|
||
normally while you create the tokens and apply them. This will reduce downtime.
|
||
You should update the configuration files on all the servers first and then
|
||
initiate a rolling restart.
|
||
|
||
### Create the Initial Bootstrap Token
|
||
|
||
To create the initial bootstrap token, use the `acl bootstrap` command on one
|
||
of the servers.
|
||
|
||
```shell-session
|
||
$ consul acl bootstrap
|
||
```
|
||
|
||
The output gives you important information about the token, including the
|
||
associated policy `global-management` and `SecretID`.
|
||
|
||
~> Note: By default, Consul assigns the `global-management` policy to the
|
||
bootstrap token, which has unrestricted privileges. It is important to have one
|
||
token with unrestricted privileges in case of emergencies; however you should
|
||
only give a small number of administrators access to it. The `SecretID` is a
|
||
UUID that you will use to identify the token when using the Consul CLI or HTTP
|
||
API.
|
||
|
||
While you are setting up the ACL system, set the `CONSUL_HTTP_TOKEN`
|
||
environment variable to the bootstrap token on one server, for this guide
|
||
the example is on server "consul-server-one". This gives you the necessary
|
||
privileges to continue
|
||
creating policies and tokens. Set the environment variable temporarily with
|
||
`export`, so that it will not persist once you’ve closed the session.
|
||
|
||
```shell-session
|
||
$ export CONSUL_HTTP_TOKEN=<your_token_here>
|
||
```
|
||
|
||
Now, all of the following commands in this guide can
|
||
be completed on the same server, in this
|
||
case server "consul-server-one".
|
||
|
||
## Apply Individual Tokens to Agents
|
||
|
||
Adding tokens to agents is a three step process.
|
||
|
||
1. [Create the agent
|
||
policy](/advanced/day-1-operations/production-acls/create-the-agent-policy).
|
||
2. [Create the token with the newly created
|
||
policy](/advanced/day-1-operations/production-acls/create-the-agent-token).
|
||
3. [Add the token to the agent](/advanced/day-1-operations/production-acls/add-the-token-to-the-agent).
|
||
|
||
### Create the Agent Policy
|
||
|
||
We recommend creating agent policies that have write privileges for node
|
||
related actions including registering itself in the catalog, updating node
|
||
level health checks, and having write access on its configuration file. The
|
||
example below has unrestricted privileges for node related actions for
|
||
"consul-server-one" only.
|
||
|
||
```
|
||
# consul-server-one-policy.hcl
|
||
node "consul-server-one" {
|
||
policy = "write"
|
||
}
|
||
```
|
||
|
||
When creating agent policies, review the [node rules](/docs/agent/acl-rules#node-rules). Now that
|
||
you have
|
||
specified the policy, you can initialize it using the Consul
|
||
CLI. To create a programmatic process, you could also use
|
||
the HTTP API.
|
||
|
||
```shell-session
|
||
$ consul acl policy create -name consul-server-one -rules @consul-server-one-policy.hcl
|
||
```
|
||
|
||
The command output will include the policy information.
|
||
|
||
Repeat this process for all servers and clients in the Consul datacenter. Each agent should have its own policy based on the
|
||
node name, that grants write privileges to it.
|
||
|
||
### Create the Agent Token
|
||
|
||
After creating the per-agent policies, create individual tokens for all the
|
||
agents. You will need to include the policy in the `consul acl token create`
|
||
command.
|
||
|
||
```shell-session
|
||
$ consul acl token create -description "consul-server-one agent token" -policy-name consul-server-one
|
||
```
|
||
|
||
This command returns the token information, which should include a description
|
||
and policy information.
|
||
|
||
Repeat this process for each agent. It is the responsibility of the operator to
|
||
save tokens in a secure location; we recommend
|
||
[Vault](https://www.vaultproject.io/).
|
||
|
||
### Add the Token to the Agent.
|
||
|
||
Finally, apply the tokens to the agents using the HTTP API.
|
||
Start with the servers
|
||
and ensure they are working correctly before applying the client tokens. Please
|
||
review the Bootstrapping the ACL System [guide](/advanced/day-1-operations/acl-guide) for example of setting the token in the agent configuration
|
||
file.
|
||
|
||
```shell-session
|
||
$ consul acl set-agent-token -token "<your token here>" agent "<agent token here>"
|
||
```
|
||
|
||
The data file must contain a valid token.
|
||
|
||
```
|
||
# consul-server-one-token.json
|
||
{
|
||
"Token": "adf4238a-882b-9ddc-4a9d-5b6758e4159e"
|
||
}
|
||
```
|
||
|
||
At this point, every agent that has a token can once
|
||
again read and write information to Consul, but only for node-related actions.
|
||
Actions for individual services are not yet allowed.
|
||
|
||
~> Note: If you are bootstrapping ACLs on an existing datacenter, remember to
|
||
update the default policy to `default_policy = deny` and initiate another
|
||
rolling restart. After applying the token.
|
||
|
||
## Apply Individual Tokens to the Services
|
||
|
||
The token creation and application process for services is similar to agents.
|
||
Create a policy. Use that policy to create a token. Add the token to the
|
||
service. Service tokens are necessary for
|
||
agent anti-entropy, registering and deregistering the service, and
|
||
registering and deregistering the service's checks.
|
||
|
||
Review the [service
|
||
rules](/docs/agent/acl-rules#service-rules) before
|
||
getting started.
|
||
|
||
Below is an example service definition that needs a token after bootstrapping
|
||
the ACL system.
|
||
|
||
```json
|
||
{
|
||
"service": {
|
||
"name": "dashboard",
|
||
"port": 9002,
|
||
"check": {
|
||
"id": "dashboard-check",
|
||
"http": "http://localhost:9002/health",
|
||
"method": "GET",
|
||
"interval": "1s",
|
||
"timeout": "1s"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
This service definition should be located in the [configuration
|
||
directory](/docs/agent/options#_config_dir) on one of
|
||
the clients.
|
||
|
||
First, create the policy that will grant write privileges to only the
|
||
"dashboard" service. This means the "dashboard" service can register
|
||
itself, update its health checks, and write any of the fields in the [service
|
||
definition](/docs/agent/services).
|
||
|
||
```shell
|
||
# dashboard-policy.hcl
|
||
service "dashboard" {
|
||
policy = "write"
|
||
}
|
||
```
|
||
|
||
Use the policy definition to initiate the policy.
|
||
|
||
```shell-session
|
||
$ consul acl policy create -name "dashboard-service" -rules @dashboard-policy.hcl
|
||
```
|
||
|
||
Next, create a token with the policy.
|
||
|
||
```shell-session
|
||
$ consul acl token create -description "Token for Dashboard Service" -policy-name dashboard-service
|
||
```
|
||
|
||
The command will return information about the token, which should include a
|
||
description and policy information. As usual, save the token to a secure
|
||
location.
|
||
|
||
Finally, add the token to the service definition.
|
||
|
||
```
|
||
{
|
||
"service": {
|
||
"name": "dashboard",
|
||
"port": 9002,
|
||
"token": "57c5d69a-5f19-469b-0543-12a487eecc66",
|
||
"check": {
|
||
"id": "dashboard-check",
|
||
"http": "http://localhost:9002/health",
|
||
"method": "GET",
|
||
"interval": "1s",
|
||
"timeout": "1s"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
If the service is running, you will need to restart it. Unlike with agent
|
||
tokens, there is no HTTP API endpoint to apply the token directly to the
|
||
service. If the service is registered with a configuration file, you must
|
||
also set the token in the configuration file. However, if you register a
|
||
service with the HTTP API, you can pass the token in the [header](/api#authentication) with
|
||
`X-Consul-Token` and it will be used by the service.
|
||
|
||
If you are using a sidecar proxy, it can inherit the token from the service
|
||
definition. Alternatively, you can create a separate token.
|
||
|
||
## Token for DNS
|
||
|
||
Depending on your use case, the token used for DNS may need policy rules for
|
||
[nodes](/docs/agent/acl-rules#node-rules),
|
||
[services](/docs/agent/acl-rules#service-rules), and
|
||
[prepared queries](/docs/agent/acl-rules#prepared-query-rules).
|
||
You should apply the token to the Consul agent serving DNS requests. When the
|
||
DNS server makes a request to Consul, it will include the token in the request.
|
||
Consul can either authorize or revoke the request, depending on the token's
|
||
privileges. The token creation for DNS is the same three step process you used
|
||
for agents and services, create a policy, create a token, apply the
|
||
token.
|
||
|
||
Below is an example of a policy that provides read privileges for all services,
|
||
nodes, and prepared queries.
|
||
|
||
```
|
||
# dns-request-policy.hcl
|
||
node_prefix "" {
|
||
policy = "read"
|
||
}
|
||
service_prefix "" {
|
||
policy = "read"
|
||
}
|
||
# only needed if using prepared queries
|
||
query_prefix "" {
|
||
policy = "read"
|
||
}
|
||
```
|
||
|
||
First, create the policy.
|
||
|
||
```shell-session
|
||
$ consul acl policy create -name "dns-requests" -rules @dns-request-policy.hcl
|
||
```
|
||
|
||
Next, create the token.
|
||
|
||
```shell-session
|
||
$ consul acl token create -description "Token for DNS Requests" -policy-name dns-requests
|
||
```
|
||
|
||
Finally, apply the token to the Consul agent serving DNS request in default token ACL
|
||
configuration parameter.
|
||
|
||
```shell-session
|
||
$ consul acl set-agent-token -token "<your token here>" default "<dns token>"
|
||
```
|
||
|
||
The data file must contain a valid token.
|
||
|
||
```
|
||
# dns-token.json
|
||
{
|
||
"Token": "5467d69a-5f19-469b-0543-12a487eecc66"
|
||
}
|
||
```
|
||
|
||
Note, if you have multiple agents serving DNS requests you can use the same
|
||
policy to create individual tokens for all of them if they are using the same rules.
|
||
|
||
## Consul KV Tokens
|
||
|
||
The process of creating tokens for Consul KV follows the same three step
|
||
process as nodes and services. First create a policy, then a token, and finally
|
||
apply or use the token. However, unlike tokens for nodes and services Consul KV
|
||
has many varied use cases.
|
||
|
||
- Services may need to access configuration data in the key-value store.
|
||
- You may want to store distributed lock information for sessions.
|
||
- Operators may need access to
|
||
update configuration values in the key-value store. .
|
||
|
||
The [rules for
|
||
KV](/docs/agent/acl-rules#key-value-rules) have four
|
||
policy levels; `deny`, `write`, `read`, and `list`. Let's review several
|
||
examples of `read` and `write`.
|
||
|
||
Depending on the use case, the token will be applied differently. For services
|
||
you will add the token to the HTTP client. For operators use, the
|
||
operator will use the token when issuing commands, either with the CLI or API.
|
||
|
||
### Recursive Reads
|
||
|
||
```
|
||
key_prefix "redis/" {
|
||
policy = "read"
|
||
}
|
||
```
|
||
|
||
In the above example, we are allowing any key with the prefix `redis/` to be
|
||
read. If you issued the command `consul kv get -recurse redis/ -token=<your token>` you would get a list of key/values for `redis/`.
|
||
|
||
This type of policy is good for allowing operators to recursively read
|
||
configuration parameters stored in the KV. Similarly, a "write" policy with the
|
||
same prefix would allow you to update any keys that begin with "redis/".
|
||
|
||
### Write Privileges for One Key
|
||
|
||
```
|
||
key "dashboard-app" {
|
||
policy = "write"
|
||
}
|
||
```
|
||
|
||
In the above example, we are allowing read and write privileges to the
|
||
dashboard-app key. This allows for `get`, `delete`, and `put` operations.
|
||
|
||
This type of token would allow an application to update and read a value in the
|
||
KV store. It would also be useful for operators who need access to set specific
|
||
keys.
|
||
|
||
### Read Privileges for One Key
|
||
|
||
```
|
||
key "counting-app" {
|
||
policy = "read"
|
||
}
|
||
```
|
||
|
||
In the above example, we are setting a read privileges for a single key,
|
||
“counting-app”. This allows for only `get` operations.
|
||
|
||
This type of token allows an application to simply read from a key to get the
|
||
value. This is useful for configuration parameter updates.
|
||
|
||
## Consul UI Token
|
||
|
||
Once you have bootstrapped the ACL system, access to the UI will be limited.
|
||
The anonymous token grants UI access if no [default
|
||
token](/docs/agent/options#acl_tokens_default) is set
|
||
on the agents, and all operations will be denied, including viewing nodes and
|
||
services.
|
||
|
||
You can re-enable UI features (with flexible levels of access) by creating and
|
||
distributing tokens to operators. Once you have a token, you can use it in the
|
||
UI by adding it to the "ACL" page:
|
||
|
||
![Access Controls](/img/guides/access-controls.png 'Access Controls')
|
||
|
||
After saving a new token, you will be able to see your tokens.
|
||
|
||
![Tokens](/img/guides/tokens.png 'Tokens')
|
||
|
||
The browser stores tokens that you add to the UI. This allows you to distribute
|
||
different levels of privileges to operators. Like other tokens, it's up to the
|
||
operator to decide the per-token privileges.
|
||
|
||
Below is an example of policy that
|
||
will allow the operator to have read access to the UI for services, nodes,
|
||
key/values, and intentions. You need to have "acl = read" to view policies
|
||
and tokens. Otherwise you will not be able to access the ACL section of the UI,
|
||
not even to view the token you used to access the UI.
|
||
|
||
```
|
||
# operator-ui.hcl
|
||
service_prefix "" {
|
||
policy = "read"
|
||
}
|
||
key_prefix "" {
|
||
policy = "read"
|
||
}
|
||
node_prefix "" {
|
||
policy = "read"
|
||
}
|
||
```
|
||
|
||
## Summary
|
||
|
||
In this guide you bootstrapped the ACL system for consul and applied tokens to agents and services. You assigned tokens for DNS, Consul KV, and the Consul UI.
|
||
|
||
To learn more about Consul’s security model read the [internals documentation](/docs/internals/security). You can find commands relating to ACLs in our [reference documentation](/commands/acl).
|