HashiCorp Certified: Consul Associate Certification

Secure Services with Basic ACLs

Creating ACL Policies

Learn how to define and manage ACL policies in HashiCorp Consul to enforce fine-grained access control and enhance security.

What Is a Policy?

An ACL policy in Consul is a named collection of rules that govern the permissions of one or more tokens. Policies are:

  • Reusable: Attach the same policy to multiple tokens.
  • Composable: A token’s effective permissions are the union of all its policies.
  • Modular: In production, you might create distinct policies for:
    • Each Consul server node
    • Different client applications
    • The Consul Snapshot Agent (for backups)
    • Any other process interacting with Consul

Each policy includes:

  • ID: Auto-generated, immutable public identifier
  • Name: Unique within the Consul cluster
  • Description (optional): Human-readable notes
  • Rules: HCL or JSON granting or denying permissions
  • Datacenters (optional): Scopes where the policy applies
  • Namespace (Enterprise only): Limits policy to a namespace

Default Consul Policies

When you bootstrap Consul’s ACL system, two built-in policies are created by default:

The image is a slide detailing default policies for "Global-Management" and "Namespace-Management (Ent)" in a system, highlighting access permissions and policy management features.

  1. Global-Management

    • Policy ID: 00000000-0000-0000-0000-000000000001
    • Unrestricted access to the entire cluster
    • Cannot be deleted or modified (rename allowed)
    • Auto-assigned to the bootstrap master token
  2. Namespace-Management (Enterprise only)

    • Created per namespace
    • Manages policies and tokens within its namespace
    • Behaves like a user-defined policy

Policy Control Levels

Control levels determine how rules interact with resources. Consul supports four levels:

Control LevelDescription
readRetrieve resource data
writeModify or create resources and read them
denyBlock access regardless of other policies
listEnumerate keys or resources under a given prefix

The image illustrates policy control levels with permissions: READ, WRITE, DENY, and LIST, each with a brief description, alongside a cartoon character.

ACL Resource Types

Consul ACL rules apply to various resource types. Below is a breakdown of common and advanced resources:

Resource TypeDescriptionUse Case
key, key_prefixKV store operationsCommon
node, node_prefixNode registration and catalogCommon
service, service_prefixService discovery and health checksCommon
acl, agent, event, keyringACL management, agent operations, eventsAdvanced scenarios
operator, query, session, prepared_queryCluster control, queries, and sessionsAdvanced scenarios

The image is a colorful chart listing various ACL resources available for rules, such as ACL, AGENT, EVENT, and others, each with a brief description of their operations. Some resources are marked with a yellow star, indicating they are commonly used for basic operations.

Exact vs. Prefix Matching

Exact Match

Grant permissions on a single, named resource:

key "kv/apps/web-app-01" {
  policy = "write"
}

service "customer-db" {
  policy = "read"
}
  • Only the key at kv/apps/web-app-01 is writable.
  • Only the service customer-db is readable.

Prefix Match

Cover multiple resources under a common prefix:

key_prefix "kv/" {
  policy = "read"
}

service_prefix "" {
  policy = "read"
}
  • Any key under kv/ is readable.
  • All services (empty prefix) are readable.

Full Policy Example

Below is a complete policy granting specific rights to a web server and application:

# Allow only web-server-01 to register itself
node "web-server-01" {
  policy = "write"
}

# Grant write access to the eCommerce KV subtree
key_prefix "kv/apps/eCommerce" {
  policy = "write"
}

# Allow creating any new session
session_prefix "" {
  policy = "write"
}

# Allow managing the eCommerce-Front-End service
service "eCommerce-Front-End" {
  policy = "write"
}

Creating Policies via CLI

Use the consul acl policy command to create a policy from your HCL file:

$ consul acl policy create \
    --name "ecommerce" \
    --description "eCommerce App" \
    --rules @rules.hcl
ID:          06acc965-df4b-5a99-58cb-3250930c6324
Name:        eCommerce
Description: eCommerce App
Datacenters:
Rules:
  service "eCommerce" {
    policy = "write"
  }

Note

You can also supply rules inline using --rules 'service "eCommerce" { policy = "write" }' if you prefer not to use a file.

Creating Policies via API

Send a PUT request to the ACL policy endpoint:

$ curl -X PUT \
  --header "X-Consul-Token: 45a3bd52-07c7-47a4-52fd-0745e0cfe967" \
  --data @payload.json \
  https://consul.example.com:8500/v1/acl/policy
// payload.json
{
  "Name":        "eCommerce",
  "Description": "eCommerce App",
  "Rules":       "service \"eCommerce\" { policy = \"write\" }"
}

Note

If your default ACL policy is allow, you can omit the X-Consul-Token header.

Anonymous Token Policy

When no token is provided, Consul uses the anonymous token. Typical read-only permissions include:

service_prefix "" {
  policy = "read"
}

query_prefix "" {
  policy = "read"
}

node_prefix "" {
  policy = "read"
}

Warning

Grant only minimal privileges to the anonymous token to avoid exposing sensitive data.

Node-Specific Policies

HashiCorp best practice is to create one policy per node to tightly control registration and catalog operations:

# Policy for web-server-01
node "web-server-01" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}

# Policy for web-server-02
node "web-server-02" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}

Assign each policy to its node’s token so only that node can perform registration and catalog updates.


We will explore a hands-on lab to practice creating and managing ACL policies in Consul.

Watch Video

Watch video content

Previous
Demo Enable and Configure the Consul ACL System