Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions agent/config/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,17 +886,17 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
},

ACLEnableKeyListPolicy: boolVal(c.ACL.EnableKeyListPolicy),
ACLInitialManagementToken: stringVal(c.ACL.Tokens.InitialManagement),
ACLInitialManagementToken: b.stringValOrFile(c.ACL.Tokens.InitialManagement, c.ACL.Tokens.InitialManagementFile, "acl.tokens.initial_management"),

ACLTokenReplication: boolVal(c.ACL.TokenReplication),

ACLTokens: token.Config{
DataDir: dataDir,
EnablePersistence: boolValWithDefault(c.ACL.EnableTokenPersistence, false),
ACLDefaultToken: stringVal(c.ACL.Tokens.Default),
ACLAgentToken: stringVal(c.ACL.Tokens.Agent),
ACLAgentRecoveryToken: stringVal(c.ACL.Tokens.AgentRecovery),
ACLReplicationToken: stringVal(c.ACL.Tokens.Replication),
ACLDefaultToken: b.stringValOrFile(c.ACL.Tokens.Default, c.ACL.Tokens.DefaultFile, "acl.tokens.default"),
ACLAgentToken: b.stringValOrFile(c.ACL.Tokens.Agent, c.ACL.Tokens.AgentFile, "acl.tokens.agent"),
ACLAgentRecoveryToken: b.stringValOrFile(c.ACL.Tokens.AgentRecovery, c.ACL.Tokens.AgentRecoveryFile, "acl.tokens.agent_recovery"),
ACLReplicationToken: b.stringValOrFile(c.ACL.Tokens.Replication, c.ACL.Tokens.ReplicationFile, "acl.tokens.replication"),
ACLConfigFileRegistrationToken: stringVal(c.ACL.Tokens.ConfigFileRegistration),
ACLDNSToken: stringVal(c.ACL.Tokens.DNS),
},
Expand Down Expand Up @@ -1625,6 +1625,28 @@ func (b *builder) warn(msg string, args ...interface{}) {
b.Warnings = append(b.Warnings, fmt.Sprintf(msg, args...))
}

// stringValOrFile returns the token from the given value. If tokenFile is provided,
// it reads the token from the file (trimming whitespace). If both token and tokenFile
// are provided, tokenFile takes precedence (with a warning).
func (b *builder) stringValOrFile(token *string, tokenFile *string, name string) string {
tokenVal := stringVal(token)
tokenFileVal := stringVal(tokenFile)

if tokenFileVal != "" {
if tokenVal != "" {
b.warn("%s is set and %s_file is also set. %s_file will be used.", name, name, name)
}
data, err := os.ReadFile(tokenFileVal)
if err != nil {
b.err = multierror.Append(b.err, fmt.Errorf("%s_file: %w", name, err))
return ""
}
return strings.TrimSpace(string(data))
}

return tokenVal
}

func (b *builder) checkVal(v *CheckDefinition) *structs.CheckDefinition {
if v == nil {
return nil
Expand Down
5 changes: 5 additions & 0 deletions agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,10 +793,15 @@ type ACL struct {

type Tokens struct {
InitialManagement *string `mapstructure:"initial_management"`
InitialManagementFile *string `mapstructure:"initial_management_file"`
Replication *string `mapstructure:"replication"`
ReplicationFile *string `mapstructure:"replication_file"`
AgentRecovery *string `mapstructure:"agent_recovery"`
AgentRecoveryFile *string `mapstructure:"agent_recovery_file"`
Default *string `mapstructure:"default"`
DefaultFile *string `mapstructure:"default_file"`
Agent *string `mapstructure:"agent"`
AgentFile *string `mapstructure:"agent_file"`
ConfigFileRegistration *string `mapstructure:"config_file_service_registration"`
DNS *string `mapstructure:"dns"`

Expand Down
1 change: 1 addition & 0 deletions agent/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func AddFlags(fs *flag.FlagSet, f *LoadOpts) {
add(&f.FlagValues.Ports.SerfWAN, "serf-wan-port", "Sets the Serf WAN port to listen on.")
add(&f.FlagValues.ServerMode, "server", "Switches agent to server mode.")
add(&f.FlagValues.EnableSyslog, "syslog", "Enables logging to syslog.")
add(&f.FlagValues.ACL.Tokens.DefaultFile, "token-file", "Path to a file containing the ACL token to use as the default token. This can also be specified via the CONSUL_HTTP_TOKEN_FILE environment variable.")
add(&f.FlagValues.UIConfig.Enabled, "ui", "Enables the built-in static web UI server.")
add(&f.FlagValues.UIConfig.ContentPath, "ui-content-path", "Sets the external UI path to a string. Defaults to: /ui/ ")
add(&f.FlagValues.UIConfig.Dir, "ui-dir", "Path to directory containing the web UI resources.")
Expand Down
73 changes: 73 additions & 0 deletions agent/config/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,79 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
rt.DataDir = dataDir
},
})
run(t, testCase{
desc: "-token-file",
args: []string{
`-token-file=` + filepath.Join(dataDir, "token-file"),
`-data-dir=` + dataDir,
},
setup: func() {
writeFile(filepath.Join(dataDir, "token-file"), []byte("my-test-token\n"))
},
expected: func(rt *RuntimeConfig) {
rt.ACLTokens.ACLDefaultToken = "my-test-token"
rt.DataDir = dataDir
},
})
run(t, testCase{
desc: "acl.tokens.default_file in config",
args: []string{
`-data-dir=` + dataDir,
},
setup: func() {
writeFile(filepath.Join(dataDir, "token-file"), []byte(" token-from-file \n"))
},
hcl: []string{`
acl {
tokens {
default_file = "` + filepath.Join(dataDir, "token-file") + `"
}
}
`},
json: []string{`{
"acl": {
"tokens": {
"default_file": "` + filepath.Join(dataDir, "token-file") + `"
}
}
}`},
expected: func(rt *RuntimeConfig) {
rt.ACLTokens.ACLDefaultToken = "token-from-file"
rt.DataDir = dataDir
},
})
run(t, testCase{
desc: "acl.tokens.default and default_file both set",
args: []string{
`-data-dir=` + dataDir,
},
setup: func() {
writeFile(filepath.Join(dataDir, "token-file"), []byte("token-from-file"))
},
hcl: []string{`
acl {
tokens {
default = "inline-token"
default_file = "` + filepath.Join(dataDir, "token-file") + `"
}
}
`},
json: []string{`{
"acl": {
"tokens": {
"default": "inline-token",
"default_file": "` + filepath.Join(dataDir, "token-file") + `"
}
}
}`},
expectedWarnings: []string{
"acl.tokens.default is set and acl.tokens.default_file is also set. acl.tokens.default_file will be used.",
},
expected: func(rt *RuntimeConfig) {
rt.ACLTokens.ACLDefaultToken = "token-from-file"
rt.DataDir = dataDir
},
})
run(t, testCase{
desc: "-ui",
args: []string{
Expand Down