hashicorp/consul
ACL system
Consul ACLs control who can read and write what — services, KV keys, intentions, sessions, peerings, and so on. The system supports tokens, policies, roles, auth methods (for federated identity), binding rules, and templated policies.
Pieces
| Piece | Where |
|---|---|
| Authorizer engine | acl/acl.go (55 KB), acl/acl_cache.go |
| Templated policies | acl/acl_templated_policy.go, acl/acltemplatedpolicy/ |
| Authorizer filtering | acl/aclfilter/ |
| RPC endpoint | agent/consul/acl_endpoint.go (65 KB), agent/consul/acl.go (36 KB) |
| HTTP endpoint | agent/acl_endpoint.go (39 KB) |
| State store | agent/consul/state/acl.go (52 KB), agent/consul/state/acl_schema.go |
| Auth methods | agent/consul/authmethod/, agent/consul/auth/ |
| Token store (per-agent) | agent/token/ |
| ACL replication | agent/consul/acl_replication.go, agent/consul/replication.go |
| Public Go API | api/acl.go |
| CLI | command/acl/... (token, policy, role, auth-method, binding-rule, templated-policy) |
Concepts
graph LR
Token[Token<br/>uuid + accessor id]
Policy[Policy<br/>HCL/JSON rules]
Role[Role<br/>collection of policies]
Service[Service identity]
Node[Node identity]
AuthMethod[Auth method<br/>OIDC, JWT, K8s SA]
BindingRule[Binding rule]
Templated[Templated policy]
Token -->|attached| Policy
Token -->|attached| Role
Token -->|attached| Service
Token -->|attached| Node
Token -->|attached| Templated
Role -->|references| Policy
Role -->|references| Service
Role -->|references| Node
AuthMethod -.login.-> Token
BindingRule -.maps claims.-> TokenA token is the credential. It can attach policies and roles directly (the simple case) and/or service identities and node identities (which expand into well-known templated permissions).
A policy holds HCL rules:
service_prefix "web-" { policy = "write" }
key_prefix "myapp/" { policy = "read" }
node_prefix "" { policy = "read" }A role is a named bundle of policies, services, and nodes — useful when many tokens share the same permission set.
An auth method (OIDC, JWT, K8s ServiceAccount) lets external identities exchange a credential for a Consul token via POST /v1/acl/login. Binding rules map claims from the auth method into roles, services, or namespaces.
Templated policies are reusable parameterized policies (e.g., builtin/service takes a service name and grants read+write on that service). They were introduced to compress the most common policy shapes.
Authorizer engine
acl/acl.go defines the Authorizer interface and a tree-of-policies implementation. The interface is rich:
type Authorizer interface {
ServiceWrite(name string, ctx *AuthorizerContext) EnforcementDecision
KeyRead(key string, ctx *AuthorizerContext) EnforcementDecision
NodeRead(node string, ctx *AuthorizerContext) EnforcementDecision
PreparedQueryRead(name string, ctx *AuthorizerContext) EnforcementDecision
OperatorWrite(ctx *AuthorizerContext) EnforcementDecision
// ... many more
}When a request arrives, the agent or server resolves the token to an Authorizer (cached in acl/acl_cache.go) and calls the relevant method. Decisions are Allow, Deny, or Default (fall through to the cluster default policy).
Token resolution
sequenceDiagram
participant Caller as Client
participant Agent as Agent
participant Cache as ACL token cache
participant Server as Server
participant State as state store
Caller->>Agent: HTTP request, X-Consul-Token: <token>
Agent->>Cache: lookup authorizer
alt cache miss
Cache->>Server: ACL.TokenRead
Server->>State: token + policies + roles
State-->>Server: resolved
Server-->>Cache: authorizer (compiled)
end
Cache-->>Agent: authorizer
Agent->>Agent: enforce per endpointThe agent caches authorizers for performance (acl/acl_cache.go) and invalidates on token / policy / role updates via streaming subscribe events (agent/consul/acl_events.go).
Auth methods
Built-in types:
- JWT (
agent/consul/authmethod/kubernetes,agent/consul/authmethod/oidc,agent/consul/authmethod/jwt) - Kubernetes service account — verifies a JWT against a K8s API server.
- OIDC — does discovery + JWKS verification.
The flow:
- External identity presents a credential at
POST /v1/acl/loginwithauth_methodset. - The auth method validates and returns claims.
- Binding rules (
agent/consul/state/acl.go::ACLBindingRule) match claim selectors and bind the resulting token to roles/services. - A token is minted with a TTL and returned.
Replication
In multi-DC setups one DC is the primary: it owns ACL writes for global tokens/policies/roles. Secondary DCs run a replication loop (agent/consul/acl_replication.go) that pulls global definitions and locally caches them. Local tokens (created in a non-primary DC) don't replicate.
Operator workflow
# Bootstrap (only once per cluster)
consul acl bootstrap
# Create a policy
consul acl policy create -name web -rules @web.policy.hcl
# Create a token attached to a policy
consul acl token create -description "web app" -policy-name web
# Use it
CONSUL_HTTP_TOKEN=<token> consul kv put myapp/foo barThe CLI surface is the largest of any subsystem (see CLI).
Integration points
- Every endpoint — virtually every RPC has an ACL check. Look for
authz.<Action>in*_endpoint.go. - DNS — uses the agent default token to filter responses.
- Service mesh — the Connect CA leaf signing is gated by
service:writeon the requested identity. - V2 resource framework — uses the same
acl.Authorizervia per-type ACL hooks. - Streaming — token mutations push invalidation events to subscribers.
Entry points for modification
- Add a new authorizer method: extend
acl.Authorizer(be ready to update many call sites). - Add a new auth method type: implement under
agent/consul/authmethod/<type>/and register inagent/consul/auth/. - Add a new templated policy: see
acl/acltemplatedpolicy/— it's a small DSL. - Tune the cache:
acl/acl_cache.go. Be aware of staleness vs. throughput trade-offs.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.