Nomad
ACL Policy Specification
The Secure Nomad with Access Control guide includes step-by-step instructions for bootstrapping Nomad's Access Control List (ACL) system, authoring policies, and granting policies. This document is a detailed reference of the expected policy structure and available options.
ACL policies are written using HashiCorp Configuration Language (HCL). The HCL interpreter can also parse JSON to facilitate machine-generated configuration. A detailed syntax specification for HCL can be found at HCL Native Syntax Specification.
All content of an ACL policy is case-sensitive.
An ACL policy contains one or more rules. Each rule block contains a
combination of policy
and capabilities
fields. The specific values permitted
are described for each rule definition below. An example structure of an ACL
policy is as follows:
# this is a namespace rule for the "foo" namespace
namespace "foo" {
policy = "write" # this is a policy field
capabilities = ["alloc-exec"] # this is a capabilities list
# this block controls access to variables in this namespace
variables {
path "project/*" {
capabilities = ["read", "write"]
}
}
}
# this is a namespace rule, with a wildcard label
namespace "*" {
policy = "read"
}
node {
policy = "read"
}
agent {
policy = "read"
}
operator {
policy = "read"
}
quota {
policy = "read"
}
# this is a host_volume rule, with a wildcard label
host_volume "*" {
policy = "read"
}
plugin {
policy = "write"
}
Namespace Rules
Namespace rules are defined with a namespace
block. An ACL policy can include
zero, one, or more namespace rules.
Namespace rules control access to APIs in Nomad that are namespaced: Jobs, Allocations, Deployments, Evaluations, Recommendations, Scaling Policies, Services, and CSI Volumes. Namespace rules also filter items related to the above APIs from the Event Stream and Search APIs.
Each namespace rule is labeled with the namespace name it applies to. If no
namespace label is specified, the rule will apply to the "default"
namespace. You may use wildcard globs ("*"
) in the namespace label, to apply a
rule to multiple namespaces.
Only one namespace rule can apply. When an action is checked against the ACL Policy, the namespace rule is selected by first checking for an exact match, before falling back to a glob-based lookup. When looking up the namespace by glob, the matching rule with the greatest number of matched characters will be chosen.
For example the following policy will evaluate to deny for production-web
,
because it is 9 characters different from the "*-web"
rule, but 13 characters
different from the "*"
rule.
namespace "*-web" {
policy = "deny"
}
namespace "*" {
policy = "write"
}
Each namespace rule can include a coarse-grained policy
field, a fine-grained
capabilities
field, a variables
block, or all three.
The policy
field for namespace rules can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
In addition to the coarse-grained policy
, you can provide a fine-grained list
of capabilities
. This includes:
deny
- When multiple policies are associated with a token, deny will take precedence and prevent any capabilities.list-jobs
- Allows listing the jobs and seeing coarse grain status. This implicitly grantscsi-list-volume
.parse-job
- Allows parsing a job from HCL to JSON.read-job
- Allows inspecting a job and seeing fine grain status. This implicitly grantscsi-read-volume
.submit-job
- Allows jobs to be submitted, updated, or stopped.dispatch-job
- Allows jobs to be dispatchedread-logs
- Allows the logs associated with a job to be viewed.read-fs
- Allows the filesystem of allocations associated to be viewed. Implicitly grantsread-logs
.alloc-exec
- Allows an operator to connect and run commands in running allocations.alloc-node-exec
- Allows an operator to connect and run commands in allocations running without filesystem isolation, for example, raw_exec jobs.alloc-lifecycle
- Allows an operator to stop individual allocations manually.csi-register-plugin
- Allows jobs to be submitted that register themselves as CSI plugins.csi-write-volume
- Allows CSI volumes to be registered or deregistered. This implicitly grantscsi-read-volume
.csi-read-volume
- Allows inspecting a CSI volume, seeing fine grain status, and listing external volumes and snapshots. This implicitly grantscsi-list-volume
.csi-list-volume
- Allows listing CSI volumes, seeing coarse grain status, and listing external volumes and snapshots.csi-mount-volume
- Allows jobs to be submitted that claim a CSI volume. This implicitly grantscsi-read-volume
.list-scaling-policies
- Allows listing scaling policies.read-scaling-policy
- Allows inspecting a scaling policy.read-job-scaling
- Allows inspecting the current scaling of a job.scale-job
: Allows scaling a job up or down.sentinel-override
- Allows soft mandatory policies to be overridden.submit-recommendation
- Allows submitting vertical job scaling recommendations.
The coarse-grained policy permissions are shorthand for the following fine- grained namespace capabilities:
Policy | Capabilities |
---|---|
deny | deny |
read | list-jobs parse-job read-job csi-list-volume csi-read-volume list-scaling-policies read-scaling-policy read-job-scaling |
write | list-jobs parse-job read-job submit-job dispatch-job read-logs read-fs alloc-exec alloc-lifecycle csi-write-volume csi-mount-volume list-scaling-policies read-scaling-policy read-job-scaling scale-job submit-recommendation |
scale | list-scaling-policies read-scaling-policy read-job-scaling scale-job |
If you provide both a policy
and capabilities
list, the capabilities are
merged. For example, the policy below adds the submit-job
capability to the read
policy disposition, which provides the list-job
and read-job
capabilities:
# Allow reading jobs and submitting jobs, without allowing access
# to view log output or inspect the filesystem
namespace "default" {
policy = "read"
capabilities = ["submit-job"]
}
A similar policy could also be expressed as:
# Allow reading jobs and submitting jobs, without allowing access
# to view log output or inspect the filesystem
namespace "default" {
capabilities = ["submit-job","list-jobs","read-job"]
}
Variables
The variables
block in the namespace
rule controls access to
Variables. The variables block is optional, but you can specify only one
variables block per namespace rule.
A variables
block includes one or more path
blocks. Each path
block is
labeled with the path it applies to. You may use wildcard globs ("*"
) in the
path label, to apply the block to multiple paths in the namespace.
Each path has a list of capabilities
. The available capabilities for Variables
are as follows:
Capability | Notes |
---|---|
write | Create or update Variables at this path. Includes the "list" capability but not the "read" or "destroy" capabilities. |
read | Read the decrypted contents of Variables at this path. Also includes the "list" capability |
list | List the metadata but not contents of Variables at this path. |
destroy | Delete Variables at this path. |
deny | No permissions at this path. Deny takes precedence over other capabilities. |
For example, the policy below allows full access to variables at all paths in the "dev" namespace that are prefixed with "project/", but only read access to paths prefixed with "system/". Note that the glob can match an empty string but all other characters are strictly matched. This policy grants read access to paths prefixed with "system/" but not a path named "system" (without a trailing slash). This policy does not grant any other coarse-grained policy or fine-grained capabilities.
namespace "dev" {
variables {
# full access to secrets in all "project" paths
path "project/*" {
capabilities = ["write", "read", "destroy", "list"]
}
# read/list access within a "system/" path belonging to administrators
path "system/*" {
capabilities = ["read"]
}
}
}
Node rules
The node
rule controls access to the Node API such as listing
nodes or triggering a node drain. The node rule is optional, but you can specify
only one node rule per ACL Policy.
node {
policy = "read"
}
The policy
field for the node rule can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
Agent rules
The agent
rule controls access to the Agent API such as join and
leave. The agent rule is optional, but you can specify only one agent rule per
ACL Policy.
agent {
policy = "read"
}
The policy
field for the agent rule can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
Operator rules
The operator
rule controls access to the Operator API such
raft or scheduler configuration. The operator rule is optional, but you can
specify only one operator rule per ACL Policy.
operator {
policy = "read"
}
The policy
field for the operator rule can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
In the example above, the token could be used to query the operator endpoints for diagnostic purposes but not make any changes.
Quota rules
The quota
rule controls access to the Quota API such as quota
creation and deletion. The quota rule is optional, but you can specify only one
quota rule per ACL Policy.
quota {
policy = "read"
}
The policy
field for the quota rule can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
Host Volume rules
The host_volume
rule controls access to mounting and accessing host
volumes. An ACL Policy can include zero, one, or more host volume
rules.
host_volume "*" {
policy = "write"
}
host_volume "prod-*" {
policy = "deny"
}
host_volume "prod-ca-certificates" {
policy = "read"
}
Host volume rules are labeled with the volume names that they apply to. As with namespaces, you may use wildcards to reuse the same configuration across a set of volumes.
The policy
field for host volume rules can have one of the following values:
read
: allow the resource to be read but not modifiedwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
In addition to the coarse grained policy, host volume rules can include a list
of fine-grained capabilities
. These include:
deny
- Do not allow a user to mount a volume in any way.mount-readonly
- Only allow the user to mount the volume asreadonly
mount-readwrite
- Allow the user to mount the volume asreadonly
orreadwrite
if thehost_volume
configuration allows it.
The coarse-grained policy permissions are shorthand for the fine grained capabilities:
Policy | Capabilities |
---|---|
deny | deny |
read | mount-readonly |
write | mount-readonly mount-readwrite |
When both the policy short hand and a capabilities list are provided, the capabilities are merged.
Note: Host Volume policies are applied when attempting to use a volume.
Regardless of this configuration, users with access to the Node API will be able
to list available volumes using the nomad node status
command or API call. .
Plugin rules
The plugin
rule controls access to CSI plugins, such as listing
plugins or getting plugin status. The plugin rule is optional, but you can
specify only one plugin rule per ACL policy.
plugin {
policy = "read"
}
The policy
field for the plugin rule can have one of the following values:
read
: allow the resource to be read but not modifiedlist
: allow the resource to be listed, but not inspected in detailwrite
: allow the resource to be read and modifieddeny
: do not allow the resource to be read or modified. Deny takes precedence when multiple policies are associated with a token.
Configuring ACLs for the web UI
The Nomad web UI uses the API endpoints /v1/agent
and /v1/node
for nearly
every page. ACL policies for users who will use the Nomad UI should include the
following rules.
node {
policy = "read"
}
agent {
policy = "read"
}