Day 1: Security and Network Operations

Manage ACL Policies

This guide is for Operators with the responsibility of creating and managing ACL tokens. It includes several recommendations on how to discover the minimum privileges required to complete operations. Throughout the guide we'll provide examples and use cases that you can adapt to your environment, however, it does not include environment specific recommendations. After completing this guide, you will have a better understanding of how to effectively manage ACL policies and tokens.

We expect operators to automate the policy and token generation process in production environments. Additionally, if you are using a container orchestrator, the process will vary even though the concepts in this guide will still be applicable. If you are using the official Consul-Kubernetes Helm chart to deploy Consul, use the authentication method documentation instead of generating policies manually or automating the methods here.

Prerequisites

We provide high-level recommendations in this guide, however, we will not describe the command by command token generation process. To learn how to create tokens, read the ACL bootstrapping guide.

This guide assumes the default_policy of deny is set on all agents, in accordance to the security model documentation.

Security and Usability

The examples in this guide illustrate how to create multiple policies that can be used to accomplish the same task. For example, using an exact match resource rule, is the most secure. It grants the least privileges necessary to accomplish the task. Generally, creating policies and tokens with the least privileges will result in more policy definitions. Alternatively, for a simplified process, the prefix resources rules can apply to zero-to-many objects. The trade-off of a less complicated token creation process is wider potential blast radius on token or workload compromise.

Discover Required Privileges

After bootstrapping the ACL system and configuring Consul agents with tokens, you will need to create tokens to complete any additional task within the datacenter including registering services.

Before discovering the minimum acceptable privileges, it's important to understand the basic components of a token. A rule is a specific privilege and the basic unit of a token. Rules are combined to create policies. There are two main parts of a rule: the resource and policy disposition. The resource is the object that the rule applies to and the policy dispositions dictates privileges. The example below applies to any service object named "web". The policy disposition grants read privileges.

service "web" {
    policy = "read"
}

To discover the minimum privileges required for a specific operation, we have three recommendations.

First, focus on the data in your environment that needs to be secured. Ensure your sensitive data has policies that are specific and limited. Since policies can be combined to create tokens, you will usually write more policies for sensitive data. Sensitive data could be a specific application or a set of values in the key-value store.

Second, reference the Consul docs, both the rules page and API pages, often to understand the required privileges for any given operation.

The rules documentation explains all of the rule resources. The following four resource types are critical for any operating datacenter with ACLs enabled.

RuleSummary
aclACL rules grant privileges for ACL operations including to create,update, or view tokens and policies.
node and node_prefixNode rules grant privileges for node-level registration, including adding agents to the datacenter and catalog.
service and service_prefixService rules grant privileges for service-level registration, including adding services to the catalog.
operatorThe operator grants privileges for datacenter operations, including interacting with Raft.

On the API pages, each endpoint will have a table that includes required ACLs. The node health endpoint, shown below, requires node and service read to view all checks for the specified node.

API Health Endpoint

Finally, before using a token in production, you should test that it has the correct privileges. If the token being used is missing a privilege, then Consul will issue a permission denied error.

$ consul operator raft list-peers
Error getting peers: Failed to retrieve raft configuration:
Unexpected response code: 403 (rpc error making call: Permission denied)

Depending on the the operation and type of data, you will see either a 404 or 403.

Operations Example: Listing Consul Agents

To view all Consul agents in the datacenter, you can use the consul members CLI command.

$ consul members
Node         Address             Status  Type    Build  Protocol  DC    Segment
server.one    18.220.91.175:8302   alive   server  1.6.0  2         dc1   <all>
client.one    18.223.155.113:8302  alive   client  1.6.0  2         dc1   <all>
client.two    18.220.91.175:8302   alive   client  1.6.0  2         dc1   <all>
client.three  18.223.155.113:8302  alive   client  1.6.0  2         dc1   <all>

For this command to succeed, you will need at least read privileges for every agent in the datacenter. Depending on your threat model you could have either of the following policies.

If you have a dynamic or very large environment, you may want to consider creating one policy that can apply to all agents, to reduce the Operation Team’s workload.

agent_prefix "" {
  policy = "read"
  }

Note, the empty "" allows this rule to apply to any agent in the datacenter. In the example above, this rule will apply to: server.one, client.one, client.two, and client.three.

If you have a static environment or for maximum security, you many want to create an individual rule for each agent. This could require you to to create a new token every time a new agent is added to the datacenter.

agent "server.one" {
  policy = "read"
  }
agent "client.one" {
  policy = "read"
  }
agent "client.two" {
  policy = "read"
  }
agent "client.three" {
  policy = "read"
  }

Secure Access Control: Operator-Only Access

The most secure access control implementation restricts tokens with acl="write" policies to only one or a few trusted operators. Tokens with the policy acl = "write" grant the holder unlimited privileges, because they can generate tokens with any other resource and policy. The operators are responsible for creating all other policies and tokens that grant limited access to the datacenter. We refer to this implementation as the operator-only implementation. This implementation type is the most secure, and most complex to manage.

For this implementation type operators are responsible for managing policies and tokens for:

  • service and Connect proxy registration
  • intention management
  • agent management
  • API, CLI, and UI access

Operator-Only Implementation Example

In the following example, Operators retain responsibility for service token management, but delegate access control between Connect-enabled services to the Security Team.

Initially, the Operator creates a single token with intention management privileges for the Security Team. Developers will be given separate tokens to enable them to register their applications without having access to manage Intentions.

The Security Team's token must include the intention policy disposition in the service rule for any services they are allowed to manage the intentions.

service "wordpress" {
    policy = "read"
    intentions = "write"
  }

This enables the security team to create an intention that allows the wordpress service to open new connections to the upstream mysql service.

$ consul intention create wordpress mysql

The Security Team responsible for managing intentions would need to create allow intentions when the default_policy is set to deny, since deny all will be inherited from the ACL configuration.

In this implementation type, Developers are responsible for requesting a token for their service. For a Connect enabled service, the Operator would need to create a policy that provides write privileges for the service and proxy, and read privileges for all services and nodes to enable discovery of other upstream dependencies.

service "mysql" {
  policy = "write"
}

service "mysql-sidecar-proxy" {
  policy = "write"
}

service_prefix "" {
    policy = "read"
}

node_prefix "" {
    policy = "read"
}

With the token the Developer can then register the service with Consul using the register command.

$ consul services register mysql

The Operator example above illustrates creating policies on the security spectrum. The first example, using an exact match resource rule, is the most secure. It grants the least privileges necessary to accomplish the task. Generally, creating policies and tokens with the least privileges will result in more policy definitions. However, this will help you create the most secure environment. Alternatively, the prefix rule can apply to zero-to-many objects. The trade-off of a less complicated token creation process is security. Note, this applies to all rules not just for agents.

Required Privileges for Datacenter Operations

Below is a table with the minimum required privileges for a set of common operations. You can also use exact match rules when creating specific policies that are less flexible.

CLI OperationRequired Privilege
consul reloadagent_prefix "": policy = "write"
consul monitoragent_prefix "": policy = "read"
consul leaveagent_prefix "": policy = "write"
consul membersnode_prefix "": policy = "read"
consul aclacl = "write"
consul catalog servicesservice_prefix "": policy = "read"
consul catalog nodesnode_prefix "": policy = "read"
consul services registerservice_prefix "": policy = "write"
consul services register (Connect proxy)service_prefix "": policy = "write", node_prefix "": policy = "read"
consul connect intentionservice_prefix "": intention = "write"
consul kv getkey_prefix "": policy = "read"
consul kv putkey_prefix "": policy = "write"

Next Steps

After setting up access control processes, you will need to implement a token rotation policy. If you are using third-party tool to generate tokens, such as Vault, Consul ACL tokens will adhere to the TTLs set in that third party tool. If you are manually rotating tokens or need to revoke access, you can delete a token at any time with the API. Note, token rotation requires re-registration with the new token.