agent: Adding ACL block configuration
This commit is contained in:
parent
bc697dc50e
commit
9cd8ac832f
|
@ -63,6 +63,7 @@ client {
|
|||
}
|
||||
server {
|
||||
enabled = true
|
||||
authoritative_region = "foobar"
|
||||
bootstrap_expect = 5
|
||||
data_dir = "/tmp/data"
|
||||
protocol_version = 3
|
||||
|
@ -82,6 +83,11 @@ server {
|
|||
rejoin_after_leave = true
|
||||
encrypt = "abc"
|
||||
}
|
||||
acl {
|
||||
enabled = true
|
||||
token_ttl = "30s"
|
||||
policy_ttl = "30s"
|
||||
}
|
||||
telemetry {
|
||||
statsite_address = "127.0.0.1:1234"
|
||||
statsd_address = "127.0.0.1:2345"
|
||||
|
|
|
@ -67,6 +67,9 @@ type Config struct {
|
|||
// Server has our server related settings
|
||||
Server *ServerConfig `mapstructure:"server"`
|
||||
|
||||
// ACL has our acl related settings
|
||||
ACL *ACLConfig `mapstructure:"acl"`
|
||||
|
||||
// Telemetry is used to configure sending telemetry
|
||||
Telemetry *Telemetry `mapstructure:"telemetry"`
|
||||
|
||||
|
@ -228,11 +231,35 @@ type ClientConfig struct {
|
|||
NoHostUUID *bool `mapstructure:"no_host_uuid"`
|
||||
}
|
||||
|
||||
// ACLConfig is configuration specific to the ACL system
|
||||
type ACLConfig struct {
|
||||
// Enabled controls if we are enforce and manage ACLs
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
|
||||
// TokenTTL controls how long we cache ACL tokens. This controls
|
||||
// how stale they can be when we are enforcing policies. Defaults
|
||||
// to "30s". Reducing this impacts performance by forcing more
|
||||
// frequent resolution.
|
||||
TokenTTL string `mapstructure:"token_ttl"`
|
||||
tokenTTL time.Duration `mapstructure:"-"`
|
||||
|
||||
// PolicyTTL controls how long we cache ACL policies. This controls
|
||||
// how stale they can be when we are enforcing policies. Defaults
|
||||
// to "30s". Reducing this impacts performance by forcing more
|
||||
// frequent resolution.
|
||||
PolicyTTL string `mapstructure:"policy_ttl"`
|
||||
policyTTL time.Duration `mapstructure:"-"`
|
||||
}
|
||||
|
||||
// ServerConfig is configuration specific to the server mode
|
||||
type ServerConfig struct {
|
||||
// Enabled controls if we are a server
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
|
||||
// AuthoritativeRegion is used to control which region is treated as
|
||||
// the source of truth for global tokens and ACL policies.
|
||||
AuthoritativeRegion string `mapstructure:"authoritative_region"`
|
||||
|
||||
// BootstrapExpect tries to automatically bootstrap the Consul cluster,
|
||||
// by withholding peers until enough servers join.
|
||||
BootstrapExpect int `mapstructure:"bootstrap_expect"`
|
||||
|
@ -565,6 +592,11 @@ func DefaultConfig() *Config {
|
|||
RetryInterval: "30s",
|
||||
RetryMaxAttempts: 0,
|
||||
},
|
||||
ACL: &ACLConfig{
|
||||
Enabled: false,
|
||||
TokenTTL: "30s",
|
||||
PolicyTTL: "30s",
|
||||
},
|
||||
SyslogFacility: "LOCAL0",
|
||||
Telemetry: &Telemetry{
|
||||
CollectionInterval: "1s",
|
||||
|
@ -676,6 +708,14 @@ func (c *Config) Merge(b *Config) *Config {
|
|||
result.Server = result.Server.Merge(b.Server)
|
||||
}
|
||||
|
||||
// Apply the acl config
|
||||
if result.ACL == nil && b.ACL != nil {
|
||||
server := *b.ACL
|
||||
result.ACL = &server
|
||||
} else if b.ACL != nil {
|
||||
result.ACL = result.ACL.Merge(b.ACL)
|
||||
}
|
||||
|
||||
// Apply the ports config
|
||||
if result.Ports == nil && b.Ports != nil {
|
||||
ports := *b.Ports
|
||||
|
@ -902,6 +942,22 @@ func isTooManyColons(err error) bool {
|
|||
return err != nil && strings.Contains(err.Error(), tooManyColons)
|
||||
}
|
||||
|
||||
// Merge is used to merge two ACL configs together
|
||||
func (a *ACLConfig) Merge(b *ACLConfig) *ACLConfig {
|
||||
result := *a
|
||||
|
||||
if b.Enabled {
|
||||
result.Enabled = true
|
||||
}
|
||||
if b.TokenTTL != "" {
|
||||
result.TokenTTL = b.TokenTTL
|
||||
}
|
||||
if b.PolicyTTL != "" {
|
||||
result.PolicyTTL = b.PolicyTTL
|
||||
}
|
||||
return &result
|
||||
}
|
||||
|
||||
// Merge is used to merge two server configs together
|
||||
func (a *ServerConfig) Merge(b *ServerConfig) *ServerConfig {
|
||||
result := *a
|
||||
|
@ -909,6 +965,9 @@ func (a *ServerConfig) Merge(b *ServerConfig) *ServerConfig {
|
|||
if b.Enabled {
|
||||
result.Enabled = true
|
||||
}
|
||||
if b.AuthoritativeRegion != "" {
|
||||
result.AuthoritativeRegion = b.AuthoritativeRegion
|
||||
}
|
||||
if b.BootstrapExpect > 0 {
|
||||
result.BootstrapExpect = b.BootstrapExpect
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
"vault",
|
||||
"tls",
|
||||
"http_api_response_headers",
|
||||
"acl",
|
||||
}
|
||||
if err := checkHCLKeys(list, valid); err != nil {
|
||||
return multierror.Prefix(err, "config:")
|
||||
|
@ -118,6 +119,7 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
delete(m, "vault")
|
||||
delete(m, "tls")
|
||||
delete(m, "http_api_response_headers")
|
||||
delete(m, "acl")
|
||||
|
||||
// Decode the rest
|
||||
if err := mapstructure.WeakDecode(m, result); err != nil {
|
||||
|
@ -159,6 +161,13 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Parse ACL config
|
||||
if o := list.Filter("acl"); len(o.Items) > 0 {
|
||||
if err := parseACL(&result.ACL, o); err != nil {
|
||||
return multierror.Prefix(err, "acl ->")
|
||||
}
|
||||
}
|
||||
|
||||
// Parse telemetry config
|
||||
if o := list.Filter("telemetry"); len(o.Items) > 0 {
|
||||
if err := parseTelemetry(&result.Telemetry, o); err != nil {
|
||||
|
@ -514,6 +523,7 @@ func parseServer(result **ServerConfig, list *ast.ObjectList) error {
|
|||
"retry_interval",
|
||||
"rejoin_after_leave",
|
||||
"encrypt",
|
||||
"authoritative_region",
|
||||
}
|
||||
if err := checkHCLKeys(listVal, valid); err != nil {
|
||||
return err
|
||||
|
@ -541,6 +551,55 @@ func parseServer(result **ServerConfig, list *ast.ObjectList) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseACL(result **ACLConfig, list *ast.ObjectList) error {
|
||||
list = list.Elem()
|
||||
if len(list.Items) > 1 {
|
||||
return fmt.Errorf("only one 'acl' block allowed")
|
||||
}
|
||||
|
||||
// Get our server object
|
||||
obj := list.Items[0]
|
||||
|
||||
// Value should be an object
|
||||
var listVal *ast.ObjectList
|
||||
if ot, ok := obj.Val.(*ast.ObjectType); ok {
|
||||
listVal = ot.List
|
||||
} else {
|
||||
return fmt.Errorf("acl value: should be an object")
|
||||
}
|
||||
|
||||
// Check for invalid keys
|
||||
valid := []string{
|
||||
"enabled",
|
||||
"token_ttl",
|
||||
"policy_ttl",
|
||||
}
|
||||
if err := checkHCLKeys(listVal, valid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var m map[string]interface{}
|
||||
if err := hcl.DecodeObject(&m, listVal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var config ACLConfig
|
||||
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
|
||||
WeaklyTypedInput: true,
|
||||
Result: &config,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dec.Decode(m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*result = &config
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseTelemetry(result **Telemetry, list *ast.ObjectList) error {
|
||||
list = list.Elem()
|
||||
if len(list.Items) > 1 {
|
||||
|
|
|
@ -84,6 +84,7 @@ func TestConfig_Parse(t *testing.T) {
|
|||
},
|
||||
Server: &ServerConfig{
|
||||
Enabled: true,
|
||||
AuthoritativeRegion: "foobar",
|
||||
BootstrapExpect: 5,
|
||||
DataDir: "/tmp/data",
|
||||
ProtocolVersion: 3,
|
||||
|
@ -103,6 +104,11 @@ func TestConfig_Parse(t *testing.T) {
|
|||
RetryMaxAttempts: 3,
|
||||
EncryptKey: "abc",
|
||||
},
|
||||
ACL: &ACLConfig{
|
||||
Enabled: true,
|
||||
TokenTTL: "30s",
|
||||
PolicyTTL: "30s",
|
||||
},
|
||||
Telemetry: &Telemetry{
|
||||
StatsiteAddr: "127.0.0.1:1234",
|
||||
StatsdAddr: "127.0.0.1:2345",
|
||||
|
|
|
@ -27,6 +27,7 @@ func TestConfig_Merge(t *testing.T) {
|
|||
Telemetry: &Telemetry{},
|
||||
Client: &ClientConfig{},
|
||||
Server: &ServerConfig{},
|
||||
ACL: &ACLConfig{},
|
||||
Ports: &Ports{},
|
||||
Addresses: &Addresses{},
|
||||
AdvertiseAddrs: &AdvertiseAddrs{},
|
||||
|
@ -91,6 +92,7 @@ func TestConfig_Merge(t *testing.T) {
|
|||
},
|
||||
Server: &ServerConfig{
|
||||
Enabled: false,
|
||||
AuthoritativeRegion: "global",
|
||||
BootstrapExpect: 1,
|
||||
DataDir: "/tmp/data1",
|
||||
ProtocolVersion: 1,
|
||||
|
@ -100,6 +102,11 @@ func TestConfig_Merge(t *testing.T) {
|
|||
MinHeartbeatTTL: 30 * time.Second,
|
||||
MaxHeartbeatsPerSecond: 30.0,
|
||||
},
|
||||
ACL: &ACLConfig{
|
||||
Enabled: true,
|
||||
TokenTTL: "60s",
|
||||
PolicyTTL: "60s",
|
||||
},
|
||||
Ports: &Ports{
|
||||
HTTP: 4646,
|
||||
RPC: 4647,
|
||||
|
@ -223,6 +230,7 @@ func TestConfig_Merge(t *testing.T) {
|
|||
},
|
||||
Server: &ServerConfig{
|
||||
Enabled: true,
|
||||
AuthoritativeRegion: "global2",
|
||||
BootstrapExpect: 2,
|
||||
DataDir: "/tmp/data2",
|
||||
ProtocolVersion: 2,
|
||||
|
@ -238,6 +246,11 @@ func TestConfig_Merge(t *testing.T) {
|
|||
RetryInterval: "10s",
|
||||
retryInterval: time.Second * 10,
|
||||
},
|
||||
ACL: &ACLConfig{
|
||||
Enabled: true,
|
||||
TokenTTL: "20s",
|
||||
PolicyTTL: "20s",
|
||||
},
|
||||
Ports: &Ports{
|
||||
HTTP: 20000,
|
||||
RPC: 21000,
|
||||
|
|
Loading…
Reference in New Issue