Rename `master` and `agent_master` ACL tokens in the config file format (#11665)

This commit is contained in:
Dan Upton 2021-12-01 21:08:14 +00:00 committed by GitHub
parent 67eacee31e
commit e1829a8706
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 216 additions and 77 deletions

3
.changelog/11665.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:deprecation
config: `acl.tokens.master` has been renamed to `acl.tokens.initial_management`, and `acl.tokens.agent_master` has been renamed to `acl.tokens.agent_recovery` - the old field names are now deprecated and will be removed in a future major release
```

View File

@ -65,12 +65,14 @@ func translateConfig(c *pbconfig.Config) config.Config {
}
result.ACL.Tokens = config.Tokens{
Master: stringPtrOrNil(t.Master),
Replication: stringPtrOrNil(t.Replication),
AgentMaster: stringPtrOrNil(t.AgentMaster),
Default: stringPtrOrNil(t.Default),
Agent: stringPtrOrNil(t.Agent),
ManagedServiceProvider: tokens,
DeprecatedTokens: config.DeprecatedTokens{
Master: stringPtrOrNil(t.Master),
AgentMaster: stringPtrOrNil(t.AgentMaster),
},
}
}
}

View File

@ -129,9 +129,7 @@ func TestTranslateConfig(t *testing.T) {
EnableKeyListPolicy: boolPointer(true),
EnableTokenPersistence: boolPointer(true),
Tokens: config.Tokens{
Master: stringPointer("99e7e490-6baf-43fc-9010-78b6aa9a6813"),
Replication: stringPointer("51308d40-465c-4ac6-a636-7c0747edec89"),
AgentMaster: stringPointer("e012e1ea-78a2-41cc-bc8b-231a44196f39"),
Default: stringPointer("8781a3f5-de46-4b45-83e1-c92f4cfd0332"),
Agent: stringPointer("ddb8f1b0-8a99-4032-b601-87926bce244e"),
ManagedServiceProvider: []config.ServiceProviderToken{
@ -140,6 +138,10 @@ func TestTranslateConfig(t *testing.T) {
SecretID: stringPointer("e28b820a-438e-4e2b-ad24-fe59e6a4914f"),
},
},
DeprecatedTokens: config.DeprecatedTokens{
Master: stringPointer("99e7e490-6baf-43fc-9010-78b6aa9a6813"),
AgentMaster: stringPointer("e012e1ea-78a2-41cc-bc8b-231a44196f39"),
},
},
},
AutoEncrypt: config.AutoEncrypt{

View File

@ -861,7 +861,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
},
ACLEnableKeyListPolicy: boolVal(c.ACL.EnableKeyListPolicy),
ACLMasterToken: stringVal(c.ACL.Tokens.Master),
ACLMasterToken: stringVal(c.ACL.Tokens.InitialManagement),
ACLTokenReplication: boolVal(c.ACL.TokenReplication),
@ -870,7 +870,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
EnablePersistence: boolValWithDefault(c.ACL.EnableTokenPersistence, false),
ACLDefaultToken: stringVal(c.ACL.Tokens.Default),
ACLAgentToken: stringVal(c.ACL.Tokens.Agent),
ACLAgentMasterToken: stringVal(c.ACL.Tokens.AgentMaster),
ACLAgentMasterToken: stringVal(c.ACL.Tokens.AgentRecovery),
ACLReplicationToken: stringVal(c.ACL.Tokens.Replication),
},

View File

@ -111,7 +111,11 @@ func TestValidateEnterpriseConfigKeys(t *testing.T) {
config: Config{
ReadReplica: &boolVal,
SegmentName: &stringVal,
ACL: ACL{Tokens: Tokens{AgentMaster: &stringVal}},
ACL: ACL{
Tokens: Tokens{
DeprecatedTokens: DeprecatedTokens{AgentMaster: &stringVal},
},
},
},
badKeys: []string{"read_replica (or the deprecated non_voting_server)", "segment"},
},

View File

@ -742,14 +742,23 @@ type ACL struct {
}
type Tokens struct {
Master *string `mapstructure:"master"`
InitialManagement *string `mapstructure:"initial_management"`
Replication *string `mapstructure:"replication"`
AgentMaster *string `mapstructure:"agent_master"`
AgentRecovery *string `mapstructure:"agent_recovery"`
Default *string `mapstructure:"default"`
Agent *string `mapstructure:"agent"`
// Enterprise Only
ManagedServiceProvider []ServiceProviderToken `mapstructure:"managed_service_provider"`
DeprecatedTokens `mapstructure:",squash"`
}
type DeprecatedTokens struct {
// DEPRECATED (ACL) - renamed to "initial_management"
Master *string `mapstructure:"master"`
// DEPRECATED (ACL) - renamed to "agent_recovery"
AgentMaster *string `mapstructure:"agent_master"`
}
// ServiceProviderToken groups an accessor and secret for a service provider token. Enterprise Only

View File

@ -34,11 +34,21 @@ func applyDeprecatedConfig(d *decodeTarget) (Config, []string) {
dep := d.DeprecatedConfig
var warns []string
if dep.ACLAgentMasterToken != nil {
if d.Config.ACL.Tokens.AgentMaster == nil {
d.Config.ACL.Tokens.AgentMaster = dep.ACLAgentMasterToken
// TODO(boxofrad): The DeprecatedConfig struct only holds fields that were once
// on the top-level Config struct (not nested fields e.g. ACL.Tokens) maybe we
// should rethink this a bit?
if d.Config.ACL.Tokens.AgentMaster != nil {
if d.Config.ACL.Tokens.AgentRecovery == nil {
d.Config.ACL.Tokens.AgentRecovery = d.Config.ACL.Tokens.AgentMaster
}
warns = append(warns, deprecationWarning("acl_agent_master_token", "acl.tokens.agent_master"))
warns = append(warns, deprecationWarning("acl.tokens.agent_master", "acl.tokens.agent_recovery"))
}
if dep.ACLAgentMasterToken != nil {
if d.Config.ACL.Tokens.AgentRecovery == nil {
d.Config.ACL.Tokens.AgentRecovery = dep.ACLAgentMasterToken
}
warns = append(warns, deprecationWarning("acl_agent_master_token", "acl.tokens.agent_recovery"))
}
if dep.ACLAgentToken != nil {
@ -55,11 +65,18 @@ func applyDeprecatedConfig(d *decodeTarget) (Config, []string) {
warns = append(warns, deprecationWarning("acl_token", "acl.tokens.default"))
}
if dep.ACLMasterToken != nil {
if d.Config.ACL.Tokens.Master == nil {
d.Config.ACL.Tokens.Master = dep.ACLMasterToken
if d.Config.ACL.Tokens.Master != nil {
if d.Config.ACL.Tokens.InitialManagement == nil {
d.Config.ACL.Tokens.InitialManagement = d.Config.ACL.Tokens.Master
}
warns = append(warns, deprecationWarning("acl_master_token", "acl.tokens.master"))
warns = append(warns, deprecationWarning("acl.tokens.master", "acl.tokens.initial_management"))
}
if dep.ACLMasterToken != nil {
if d.Config.ACL.Tokens.InitialManagement == nil {
d.Config.ACL.Tokens.InitialManagement = dep.ACLMasterToken
}
warns = append(warns, deprecationWarning("acl_master_token", "acl.tokens.initial_management"))
}
if dep.ACLReplicationToken != nil {

View File

@ -15,12 +15,10 @@ data_dir = "/foo"
acl_datacenter = "dcone"
acl_agent_master_token = "token1"
acl_agent_token = "token2"
acl_token = "token3"
acl_agent_token = "token1"
acl_token = "token2"
acl_master_token = "token4"
acl_replication_token = "token5"
acl_replication_token = "token3"
acl_default_policy = "deny"
acl_down_policy = "async-cache"
@ -35,13 +33,11 @@ acl_enable_key_list_policy = true
require.NoError(t, err)
expectWarns := []string{
deprecationWarning("acl_agent_master_token", "acl.tokens.agent_master"),
deprecationWarning("acl_agent_token", "acl.tokens.agent"),
deprecationWarning("acl_datacenter", "primary_datacenter"),
deprecationWarning("acl_default_policy", "acl.default_policy"),
deprecationWarning("acl_down_policy", "acl.down_policy"),
deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"),
deprecationWarning("acl_master_token", "acl.tokens.master"),
deprecationWarning("acl_replication_token", "acl.tokens.replication"),
deprecationWarning("acl_token", "acl.tokens.default"),
deprecationWarning("acl_ttl", "acl.token_ttl"),
@ -55,11 +51,9 @@ acl_enable_key_list_policy = true
rt := result.RuntimeConfig
require.Equal(t, true, rt.ACLsEnabled)
require.Equal(t, "dcone", rt.PrimaryDatacenter)
require.Equal(t, "token1", rt.ACLTokens.ACLAgentMasterToken)
require.Equal(t, "token2", rt.ACLTokens.ACLAgentToken)
require.Equal(t, "token3", rt.ACLTokens.ACLDefaultToken)
require.Equal(t, "token4", rt.ACLMasterToken)
require.Equal(t, "token5", rt.ACLTokens.ACLReplicationToken)
require.Equal(t, "token1", rt.ACLTokens.ACLAgentToken)
require.Equal(t, "token2", rt.ACLTokens.ACLDefaultToken)
require.Equal(t, "token3", rt.ACLTokens.ACLReplicationToken)
require.Equal(t, "deny", rt.ACLResolverSettings.ACLDefaultPolicy)
require.Equal(t, "async-cache", rt.ACLResolverSettings.ACLDownPolicy)
require.Equal(t, 3*time.Hour, rt.ACLResolverSettings.ACLTokenTTL)
@ -91,3 +85,91 @@ enable_acl_replication = true
rt := result.RuntimeConfig
require.Equal(t, true, rt.ACLTokenReplication)
}
func TestLoad_DeprecatedConfig_ACLMasterTokens(t *testing.T) {
t.Run("top-level fields", func(t *testing.T) {
require := require.New(t)
opts := LoadOpts{
HCL: []string{`
data_dir = "/foo"
acl_master_token = "token1"
acl_agent_master_token = "token2"
`},
}
patchLoadOptsShims(&opts)
result, err := Load(opts)
require.NoError(err)
expectWarns := []string{
deprecationWarning("acl_master_token", "acl.tokens.initial_management"),
deprecationWarning("acl_agent_master_token", "acl.tokens.agent_recovery"),
}
require.ElementsMatch(expectWarns, result.Warnings)
rt := result.RuntimeConfig
require.Equal("token1", rt.ACLMasterToken)
require.Equal("token2", rt.ACLTokens.ACLAgentMasterToken)
})
t.Run("embedded in tokens struct", func(t *testing.T) {
require := require.New(t)
opts := LoadOpts{
HCL: []string{`
data_dir = "/foo"
acl {
tokens {
master = "token1"
agent_master = "token2"
}
}
`},
}
patchLoadOptsShims(&opts)
result, err := Load(opts)
require.NoError(err)
expectWarns := []string{
deprecationWarning("acl.tokens.master", "acl.tokens.initial_management"),
deprecationWarning("acl.tokens.agent_master", "acl.tokens.agent_recovery"),
}
require.ElementsMatch(expectWarns, result.Warnings)
rt := result.RuntimeConfig
require.Equal("token1", rt.ACLMasterToken)
require.Equal("token2", rt.ACLTokens.ACLAgentMasterToken)
})
t.Run("both", func(t *testing.T) {
require := require.New(t)
opts := LoadOpts{
HCL: []string{`
data_dir = "/foo"
acl_master_token = "token1"
acl_agent_master_token = "token2"
acl {
tokens {
master = "token3"
agent_master = "token4"
}
}
`},
}
patchLoadOptsShims(&opts)
result, err := Load(opts)
require.NoError(err)
rt := result.RuntimeConfig
require.Equal("token3", rt.ACLMasterToken)
require.Equal("token4", rt.ACLTokens.ACLAgentMasterToken)
})
}

View File

@ -77,7 +77,7 @@ type RuntimeConfig struct {
// on the servers in the PrimaryDatacenter. When the leader comes online, it ensures
// that the Master token is available. This provides the initial token.
//
// hcl: acl.tokens.master = string
// hcl: acl.tokens.initial_management = string
ACLMasterToken string
// ACLtokenReplication is used to indicate that both tokens and policies

View File

@ -5343,7 +5343,7 @@ func TestLoad_FullConfig(t *testing.T) {
DataDir: dataDir,
ACLDefaultToken: "418fdff1",
ACLAgentToken: "bed2377c",
ACLAgentMasterToken: "64fd0e08",
ACLAgentMasterToken: "1dba6aba",
ACLReplicationToken: "5795983a",
},
@ -5361,7 +5361,7 @@ func TestLoad_FullConfig(t *testing.T) {
ACLRoleTTL: 9876 * time.Second,
},
ACLEnableKeyListPolicy: true,
ACLMasterToken: "8a19ac27",
ACLMasterToken: "3820e09a",
ACLTokenReplication: true,
AdvertiseAddrLAN: ipAddr("17.99.29.16"),
AdvertiseAddrWAN: ipAddr("78.63.37.19"),
@ -6020,10 +6020,12 @@ func TestLoad_FullConfig(t *testing.T) {
expectedWarns := []string{
deprecationWarning("acl_datacenter", "primary_datacenter"),
deprecationWarning("acl_agent_master_token", "acl.tokens.agent_master"),
deprecationWarning("acl_agent_master_token", "acl.tokens.agent_recovery"),
deprecationWarning("acl.tokens.agent_master", "acl.tokens.agent_recovery"),
deprecationWarning("acl_agent_token", "acl.tokens.agent"),
deprecationWarning("acl_token", "acl.tokens.default"),
deprecationWarning("acl_master_token", "acl.tokens.master"),
deprecationWarning("acl_master_token", "acl.tokens.initial_management"),
deprecationWarning("acl.tokens.master", "acl.tokens.initial_management"),
deprecationWarning("acl_replication_token", "acl.tokens.replication"),
deprecationWarning("enable_acl_replication", "acl.enable_token_replication"),
deprecationWarning("acl_default_policy", "acl.default_policy"),

View File

@ -21,7 +21,9 @@ acl = {
msp_disable_bootstrap = true
tokens = {
master = "8a19ac27",
initial_management = "3820e09a",
agent_master = "64fd0e08",
agent_recovery = "1dba6aba",
replication = "5795983a",
agent = "bed2377c",
default = "418fdff1",

View File

@ -22,7 +22,9 @@
"msp_disable_bootstrap": true,
"tokens" : {
"master" : "8a19ac27",
"initial_management" : "3820e09a",
"agent_master" : "64fd0e08",
"agent_recovery" : "1dba6aba",
"replication" : "5795983a",
"agent" : "bed2377c",
"default" : "418fdff1",

View File

@ -16,7 +16,7 @@ the [ACL tutorial](https://learn.hashicorp.com/tutorials/consul/access-control-s
## Bootstrap ACLs
This endpoint does a special one-time bootstrap of the ACL system, making the first
management token if the [`acl.tokens.master`](/docs/agent/options#acl_tokens_master)
management token if the [`acl.tokens.initial_management`](/docs/agent/options#acl_tokens_initial_management)
configuration entry is not specified in the Consul server configuration and if the
cluster has not been bootstrapped previously. This is available in Consul 0.9.1 and later,
and requires all Consul servers to be upgraded in order to operate.

View File

@ -642,19 +642,25 @@ Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'."
- `tokens` ((#acl_tokens)) - This object holds all of the configured
ACL tokens for the agents usage.
- `master` ((#acl_tokens_master)) - Only used for servers in the [`primary_datacenter`](#primary_datacenter).
This token will be created with management-level permissions if it does not
exist. It allows operators to bootstrap the ACL system with a token Secret
ID that is well-known.
- `initial_management` ((#acl_tokens_initial_management)) - This is available in
Consul 1.11 and later. In prior versions, use [`acl.tokens.master`](#acl_tokens_master).
The `master` token is only installed when a server acquires cluster
leadership. If you would like to install or change the `acl_master_token`,
set the new value for `master` in the configuration for all servers. Once
this is done, restart the current leader to force a leader election. If
the `master` token is not supplied, then the servers do not create a
master token. When you provide a value, it should be a UUID. To maintain
backwards compatibility and an upgrade path this restriction is not
currently enforced but will be in a future major Consul release.
Only used for servers in the [`primary_datacenter`](#primary_datacenter).
This token will be created with management-level permissions if it does not exist.
It allows operators to bootstrap the ACL system with a token Secret ID that is
well-known.
The `initial_management` token is only installed when a server acquires cluster
leadership. If you would like to install or change it, set the new value for
`initial_management` in the configuration for all servers. Once this is done,
restart the current leader to force a leader election. If the `initial_management`
token is not supplied, then the servers do not create an initial management token.
When you provide a value, it should be a UUID. To maintain backwards compatibility
and an upgrade path this restriction is not currently enforced but will be in a
future major Consul release.
- `master` ((#acl_tokens_master)) **Renamed in Consul 1.11 to
[`acl.tokens.initial_management`](#acl_tokens_initial_management).**
- `default` ((#acl_tokens_default)) - When provided, the agent will
use this token when making requests to the Consul servers. Clients can override
@ -670,8 +676,16 @@ Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'."
register as in order to set any of the node-level information in the
catalog such as metadata, or the node's tagged addresses.
- `agent_master` ((#acl_tokens_agent_master)) - Used to access [agent endpoints](/api/agent)
that require agent read or write privileges, or node read privileges, even if Consul servers aren't present to validate any tokens. This should only be used by operators during outages, regular ACL tokens should normally be used by applications.
- `agent_recovery` ((#acl_tokens_agent_recovery)) - This is available in Consul 1.11
and later. In prior versions, use [`acl.tokens.agent_master`](#acl_tokens_agent_master).
Used to access [agent endpoints](/api/agent) that require agent read or write privileges,
or node read privileges, even if Consul servers aren't present to validate any tokens.
This should only be used by operators during outages, regular ACL tokens should normally
be used by applications.
- `agent_master` ((#acl_tokens_agent_master)) **Renamed in Consul 1.11 to
[`acl.tokens.agent_recovery`](#acl_tokens_agent_recovery).**
- `replication` ((#acl_tokens_replication)) - The ACL token used to
authorize secondary datacenters with the primary datacenter for replication
@ -743,17 +757,7 @@ Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'."
by allowing policies to be in place before enforcement begins.
- `acl_master_token` ((#acl_master_token_legacy)) - **Deprecated in Consul
1.4.0. See the [`acl.tokens.master`](#acl_tokens_master) field instead.** Only
used for servers in the [`primary_datacenter`](#primary_datacenter). This token
will be created with management-level permissions if it does not exist. It allows
operators to bootstrap the ACL system with a token ID that is well-known.
The `acl_master_token` is only installed when a server acquires cluster leadership. If
you would like to install or change the `acl_master_token`, set the new value for `acl_master_token`
in the configuration for all servers. Once this is done, restart the current leader to force a
leader election. If the `acl_master_token` is not supplied, then the servers do not create a master
token. When you provide a value, it can be any string value. Using a UUID would ensure that it looks
the same as the other tokens, but isn't strictly necessary.
1.4.0. See the [`acl.tokens.master`](#acl_tokens_master) field instead.**
- `acl_replication_token` ((#acl_replication_token_legacy)) - **Deprecated
in Consul 1.4.0. See the [`acl.tokens.replication`](#acl_tokens_replication) field

View File

@ -493,7 +493,7 @@ with `bar`.
Since [Agent API](/api/agent) utility operations may be required before an agent is joined to
a cluster, or during an outage of the Consul servers or ACL datacenter, a special token may be
configured with [`acl.tokens.agent_master`](/docs/agent/options#acl_tokens_agent_master) to allow
configured with [`acl.tokens.agent_recovery`](/docs/agent/options#acl_tokens_agent_recovery) to allow
write access to these operations even if no ACL resolution capability is available.
### Event Rules

View File

@ -202,16 +202,17 @@ the token itself.
#### Builtin Tokens
During cluster bootstrapping when ACLs are enabled both the special `anonymous` and the `master` token will be
During cluster bootstrapping when ACLs are enabled both the special `anonymous` and the `initial_management` token will be
injected.
- **Anonymous Token** - The anonymous token is used when a request is made to Consul without specifying a bearer token.
The anonymous token's description and policies may be updated but Consul will prevent this token's deletion. When created,
it will be assigned `00000000-0000-0000-0000-000000000002` for its Accessor ID and `anonymous` for its Secret ID.
- **Master Token** - When a master token is present within the Consul configuration, it is created and will be linked
With the builtin Global Management policy giving it unrestricted privileges. The master token is created with the Secret ID
set to the value of the configuration entry.
- **Initial Management Token** - When an initial management token is present within the Consul configuration, it is created
and will be linked with the builtin Global Management policy giving it unrestricted privileges. The initial management
token is created with the Secret ID set to the value of the configuration entry.
In Consul 1.4 - 1.10, this was called the `master` token. It was renamed to `initial_management` token in Consul 1.11.
#### Authorization
@ -292,17 +293,26 @@ A number of special tokens can also be configured which allow for bootstrapping
system, or accessing Consul in special situations:
| Special Token | Servers | Clients | Purpose |
| ------------------------------------------------------------------------ | ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`acl.tokens.agent_master`](/docs/agent/options#acl_tokens_agent_master) | `OPTIONAL` | `OPTIONAL` | Special token that can be used to access [Agent API](/api/agent) when remote bearer token resolution fails; used for setting up the cluster such as doing initial join operations, see the [ACL Agent Master Token](#acl-agent-master-token) section for more details |
| ------------------------------------------------------------------------------------ | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`acl.tokens.agent_recovery`](/docs/agent/options#acl_tokens_agent_recovery) | `OPTIONAL` | `OPTIONAL` | Special token that can be used to access [Agent API](/api/agent) when remote bearer token resolution fails; used for setting up the cluster such as doing initial join operations, see the [ACL Agent Recovery Token](#acl-agent-recovery-token) section for more details |
| [`acl.tokens.agent`](/docs/agent/options#acl_tokens_agent) | `OPTIONAL` | `OPTIONAL` | Special token that is used for an agent's internal operations, see the [ACL Agent Token](#acl-agent-token) section for more details |
| [`acl.tokens.master`](/docs/agent/options#acl_tokens_master) | `OPTIONAL` | `N/A` | Special token used to bootstrap the ACL system, check the [Bootstrapping ACLs](https://learn.hashicorp.com/tutorials/consul/access-control-setup-production) tutorial for more details |
| [`acl.tokens.initial_management`](/docs/agent/options#acl_tokens_initial_management) | `OPTIONAL` | `N/A` | Special token used to bootstrap the ACL system, check the [Bootstrapping ACLs](https://learn.hashicorp.com/tutorials/consul/access-control-setup-production) tutorial for more details |
| [`acl.tokens.default`](/docs/agent/options#acl_tokens_default) | `OPTIONAL` | `OPTIONAL` | Default token to use for client requests where no token is supplied; this is often configured with read-only access to services to enable DNS service discovery on agents |
All of these tokens except the `master` token can all be introduced or updated via the [/v1/agent/token API](/api/agent#update-acl-tokens).
All of these tokens except the `initial_management` token can all be introduced or updated via the [/v1/agent/token API](/api/agent#update-acl-tokens).
#### ACL Agent Master Token
In Consul 1.4 - 1.10, the following special tokens were known by different names:
Since the [`acl.tokens.agent_master`](/docs/agent/options#acl_tokens_agent_master) is designed to be used when the Consul servers are not available, its policy is managed locally on the agent and does not need to have a token defined on the Consul servers via the ACL API. Once set, it implicitly has the following policy associated with it
| New Name (1.11+) | Old Name (1.4 - 1.10) |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| [`acl.tokens.agent_recovery`](/docs/agent/options#acl_tokens_agent_recovery) | [`acl.tokens.agent_master`](/docs/agent/options#acl_tokens_agent_master) |
| [`acl.tokens.initial_management`](/docs/agent/options#acl_tokens_initial_management) | [`acl.tokens.master`](/docs/agent/options#acl_tokens_master) |
#### ACL Agent Recovery Token
Since the [`acl.tokens.agent_recovery`](/docs/agent/options#acl_tokens_agent_recovery) is designed to be used when the Consul servers are not available, its policy is managed locally on the agent and does not need to have a token defined on the Consul servers via the ACL API. Once set, it implicitly has the following policy associated with it
In Consul 1.4 - 1.10, this was called the `agent_master` token. It was renamed to `agent_recovery` token in Consul 1.11.
```hcl
agent "<node name of agent>" {