github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/agent/config/builder.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"regexp"
    13  	"sort"
    14  	"strings"
    15  	"time"
    16  
    17  	"github.com/hashicorp/consul/agent/connect/ca"
    18  	"github.com/hashicorp/consul/agent/consul"
    19  	"github.com/hashicorp/consul/agent/structs"
    20  	"github.com/hashicorp/consul/ipaddr"
    21  	"github.com/hashicorp/consul/lib"
    22  	"github.com/hashicorp/consul/tlsutil"
    23  	"github.com/hashicorp/consul/types"
    24  	multierror "github.com/hashicorp/go-multierror"
    25  	"github.com/hashicorp/go-sockaddr/template"
    26  	"golang.org/x/time/rate"
    27  )
    28  
    29  // Builder constructs a valid runtime configuration from multiple
    30  // configuration sources.
    31  //
    32  // To build the runtime configuration first call Build() which merges
    33  // the sources in a pre-defined order, converts the data types and
    34  // structures into their final form and performs the syntactic
    35  // validation.
    36  //
    37  // The sources are merged in the following order:
    38  //
    39  //  * default configuration
    40  //  * config files in alphabetical order
    41  //  * command line arguments
    42  //
    43  // The config sources are merged sequentially and later values
    44  // overwrite previously set values. Slice values are merged by
    45  // concatenating the two slices. Map values are merged by over-
    46  // laying the later maps on top of earlier ones.
    47  //
    48  // Then call Validate() to perform the semantic validation to ensure
    49  // that the configuration is ready to be used.
    50  //
    51  // Splitting the construction into two phases greatly simplifies testing
    52  // since not all pre-conditions have to be satisfied when performing
    53  // syntactical tests.
    54  type Builder struct {
    55  	// Flags contains the parsed command line arguments.
    56  	Flags Flags
    57  
    58  	// Head, Sources, and Tail are used to manage the order of the
    59  	// config sources, as described in the comments above.
    60  	Head    []Source
    61  	Sources []Source
    62  	Tail    []Source
    63  
    64  	// Warnings contains the warnings encountered when
    65  	// parsing the configuration.
    66  	Warnings []string
    67  
    68  	// Hostname returns the hostname of the machine. If nil, os.Hostname
    69  	// is called.
    70  	Hostname func() (string, error)
    71  
    72  	// GetPrivateIPv4 and GetPublicIPv6 return suitable default addresses
    73  	// for cases when the user doesn't supply them.
    74  	GetPrivateIPv4 func() ([]*net.IPAddr, error)
    75  	GetPublicIPv6  func() ([]*net.IPAddr, error)
    76  
    77  	// err contains the first error that occurred during
    78  	// building the runtime configuration.
    79  	err error
    80  }
    81  
    82  // NewBuilder returns a new configuration builder based on the given command
    83  // line flags.
    84  func NewBuilder(flags Flags) (*Builder, error) {
    85  	// We expect all flags to be parsed and flags.Args to be empty.
    86  	// Therefore, we bail if we find unparsed args.
    87  	if len(flags.Args) > 0 {
    88  		return nil, fmt.Errorf("config: Unknown extra arguments: %v", flags.Args)
    89  	}
    90  
    91  	newSource := func(name string, v interface{}) Source {
    92  		b, err := json.MarshalIndent(v, "", "    ")
    93  		if err != nil {
    94  			panic(err)
    95  		}
    96  		return Source{Name: name, Format: "json", Data: string(b)}
    97  	}
    98  
    99  	b := &Builder{
   100  		Flags: flags,
   101  		Head:  []Source{DefaultSource()},
   102  	}
   103  
   104  	if b.boolVal(b.Flags.DevMode) {
   105  		b.Head = append(b.Head, DevSource())
   106  	}
   107  
   108  	// Since the merge logic is to overwrite all fields with later
   109  	// values except slices which are merged by appending later values
   110  	// we need to merge all slice values defined in flags before we
   111  	// merge the config files since the flag values for slices are
   112  	// otherwise appended instead of prepended.
   113  	slices, values := b.splitSlicesAndValues(b.Flags.Config)
   114  	b.Head = append(b.Head, newSource("flags.slices", slices))
   115  	for _, path := range b.Flags.ConfigFiles {
   116  		sources, err := b.ReadPath(path)
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  		b.Sources = append(b.Sources, sources...)
   121  	}
   122  	b.Tail = append(b.Tail, newSource("flags.values", values))
   123  	for i, s := range b.Flags.HCL {
   124  		b.Tail = append(b.Tail, Source{
   125  			Name:   fmt.Sprintf("flags-%d.hcl", i),
   126  			Format: "hcl",
   127  			Data:   s,
   128  		})
   129  	}
   130  	b.Tail = append(b.Tail, NonUserSource(), DefaultConsulSource(), DefaultEnterpriseSource(), DefaultVersionSource())
   131  	if b.boolVal(b.Flags.DevMode) {
   132  		b.Tail = append(b.Tail, DevConsulSource())
   133  	}
   134  	return b, nil
   135  }
   136  
   137  // ReadPath reads a single config file or all files in a directory (but
   138  // not its sub-directories) and appends them to the list of config
   139  // sources.
   140  func (b *Builder) ReadPath(path string) ([]Source, error) {
   141  	f, err := os.Open(path)
   142  	if err != nil {
   143  		return nil, fmt.Errorf("config: Open failed on %s. %s", path, err)
   144  	}
   145  	defer f.Close()
   146  
   147  	fi, err := f.Stat()
   148  	if err != nil {
   149  		return nil, fmt.Errorf("config: Stat failed on %s. %s", path, err)
   150  	}
   151  
   152  	if !fi.IsDir() {
   153  		src, err := b.ReadFile(path)
   154  		if err != nil {
   155  			return nil, err
   156  		}
   157  		return []Source{src}, nil
   158  	}
   159  
   160  	fis, err := f.Readdir(-1)
   161  	if err != nil {
   162  		return nil, fmt.Errorf("config: Readdir failed on %s. %s", path, err)
   163  	}
   164  
   165  	// sort files by name
   166  	sort.Sort(byName(fis))
   167  
   168  	var sources []Source
   169  	for _, fi := range fis {
   170  		fp := filepath.Join(path, fi.Name())
   171  		// check for a symlink and resolve the path
   172  		if fi.Mode()&os.ModeSymlink > 0 {
   173  			var err error
   174  			fp, err = filepath.EvalSymlinks(fp)
   175  			if err != nil {
   176  				return nil, err
   177  			}
   178  			fi, err = os.Stat(fp)
   179  			if err != nil {
   180  				return nil, err
   181  			}
   182  		}
   183  		// do not recurse into sub dirs
   184  		if fi.IsDir() {
   185  			continue
   186  		}
   187  
   188  		src, err := b.ReadFile(fp)
   189  		if err != nil {
   190  			return nil, err
   191  		}
   192  		sources = append(sources, src)
   193  	}
   194  	return sources, nil
   195  }
   196  
   197  // ReadFile parses a JSON or HCL config file and appends it to the list of
   198  // config sources.
   199  func (b *Builder) ReadFile(path string) (Source, error) {
   200  	data, err := ioutil.ReadFile(path)
   201  	if err != nil {
   202  		return Source{}, fmt.Errorf("config: ReadFile failed on %s: %s", path, err)
   203  	}
   204  	return Source{Name: path, Data: string(data)}, nil
   205  }
   206  
   207  type byName []os.FileInfo
   208  
   209  func (a byName) Len() int           { return len(a) }
   210  func (a byName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   211  func (a byName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }
   212  
   213  func (b *Builder) BuildAndValidate() (RuntimeConfig, error) {
   214  	rt, err := b.Build()
   215  	if err != nil {
   216  		return RuntimeConfig{}, err
   217  	}
   218  	if err := b.Validate(rt); err != nil {
   219  		return RuntimeConfig{}, err
   220  	}
   221  	return rt, nil
   222  }
   223  
   224  // Build constructs the runtime configuration from the config sources
   225  // and the command line flags. The config sources are processed in the
   226  // order they were added with the flags being processed last to give
   227  // precedence over the other sources. If the error is nil then
   228  // warnings can still contain deprecation or format warnings that should
   229  // be presented to the user.
   230  func (b *Builder) Build() (rt RuntimeConfig, err error) {
   231  	b.err = nil
   232  	b.Warnings = nil
   233  
   234  	// ----------------------------------------------------------------
   235  	// merge config sources as follows
   236  	//
   237  
   238  	configFormat := b.stringVal(b.Flags.ConfigFormat)
   239  	if configFormat != "" && configFormat != "json" && configFormat != "hcl" {
   240  		return RuntimeConfig{}, fmt.Errorf("config: -config-format must be either 'hcl' or 'json'")
   241  	}
   242  
   243  	// build the list of config sources
   244  	var srcs []Source
   245  	srcs = append(srcs, b.Head...)
   246  	for _, src := range b.Sources {
   247  		src.Format = FormatFrom(src.Name)
   248  		if configFormat != "" {
   249  			src.Format = configFormat
   250  		} else {
   251  			// If they haven't forced things to a specific format,
   252  			// then skip anything we don't understand, which is the
   253  			// behavior before we added the -config-format option.
   254  			switch src.Format {
   255  			case "json", "hcl":
   256  				// OK
   257  			default:
   258  				// SKIP
   259  				continue
   260  			}
   261  		}
   262  		if src.Format == "" {
   263  			return RuntimeConfig{}, fmt.Errorf(`config: Missing or invalid file extension for %q. Please use ".json" or ".hcl".`, src.Name)
   264  		}
   265  		srcs = append(srcs, src)
   266  	}
   267  	srcs = append(srcs, b.Tail...)
   268  
   269  	// parse the config sources into a configuration
   270  	var c Config
   271  	for _, s := range srcs {
   272  		if s.Name == "" || s.Data == "" {
   273  			continue
   274  		}
   275  		c2, err := Parse(s.Data, s.Format)
   276  		if err != nil {
   277  			return RuntimeConfig{}, fmt.Errorf("Error parsing %s: %s", s.Name, err)
   278  		}
   279  
   280  		// if we have a single 'check' or 'service' we need to add them to the
   281  		// list of checks and services first since we cannot merge them
   282  		// generically and later values would clobber earlier ones.
   283  		if c2.Check != nil {
   284  			c2.Checks = append(c2.Checks, *c2.Check)
   285  			c2.Check = nil
   286  		}
   287  		if c2.Service != nil {
   288  			c2.Services = append(c2.Services, *c2.Service)
   289  			c2.Service = nil
   290  		}
   291  
   292  		c = Merge(c, c2)
   293  	}
   294  
   295  	// ----------------------------------------------------------------
   296  	// process/merge some complex values
   297  	//
   298  
   299  	var dnsServiceTTL = map[string]time.Duration{}
   300  	for k, v := range c.DNS.ServiceTTL {
   301  		dnsServiceTTL[k] = b.durationVal(fmt.Sprintf("dns_config.service_ttl[%q]", k), &v)
   302  	}
   303  
   304  	soa := RuntimeSOAConfig{Refresh: 3600, Retry: 600, Expire: 86400, Minttl: 0}
   305  	if c.DNS.SOA != nil {
   306  		if c.DNS.SOA.Expire != nil {
   307  			soa.Expire = *c.DNS.SOA.Expire
   308  		}
   309  		if c.DNS.SOA.Minttl != nil {
   310  			soa.Minttl = *c.DNS.SOA.Minttl
   311  		}
   312  		if c.DNS.SOA.Refresh != nil {
   313  			soa.Refresh = *c.DNS.SOA.Refresh
   314  		}
   315  		if c.DNS.SOA.Retry != nil {
   316  			soa.Retry = *c.DNS.SOA.Retry
   317  		}
   318  	}
   319  
   320  	leaveOnTerm := !b.boolVal(c.ServerMode)
   321  	if c.LeaveOnTerm != nil {
   322  		leaveOnTerm = b.boolVal(c.LeaveOnTerm)
   323  	}
   324  
   325  	skipLeaveOnInt := b.boolVal(c.ServerMode)
   326  	if c.SkipLeaveOnInt != nil {
   327  		skipLeaveOnInt = b.boolVal(c.SkipLeaveOnInt)
   328  	}
   329  
   330  	// ----------------------------------------------------------------
   331  	// checks and services
   332  	//
   333  
   334  	var checks []*structs.CheckDefinition
   335  	if c.Check != nil {
   336  		checks = append(checks, b.checkVal(c.Check))
   337  	}
   338  	for _, check := range c.Checks {
   339  		checks = append(checks, b.checkVal(&check))
   340  	}
   341  
   342  	var services []*structs.ServiceDefinition
   343  	for _, service := range c.Services {
   344  		services = append(services, b.serviceVal(&service))
   345  	}
   346  	if c.Service != nil {
   347  		services = append(services, b.serviceVal(c.Service))
   348  	}
   349  
   350  	// ----------------------------------------------------------------
   351  	// addresses
   352  	//
   353  
   354  	// determine port values and replace values <= 0 and > 65535 with -1
   355  	dnsPort := b.portVal("ports.dns", c.Ports.DNS)
   356  	httpPort := b.portVal("ports.http", c.Ports.HTTP)
   357  	httpsPort := b.portVal("ports.https", c.Ports.HTTPS)
   358  	serverPort := b.portVal("ports.server", c.Ports.Server)
   359  	grpcPort := b.portVal("ports.grpc", c.Ports.GRPC)
   360  	serfPortLAN := b.portVal("ports.serf_lan", c.Ports.SerfLAN)
   361  	serfPortWAN := b.portVal("ports.serf_wan", c.Ports.SerfWAN)
   362  	proxyMinPort := b.portVal("ports.proxy_min_port", c.Ports.ProxyMinPort)
   363  	proxyMaxPort := b.portVal("ports.proxy_max_port", c.Ports.ProxyMaxPort)
   364  	sidecarMinPort := b.portVal("ports.sidecar_min_port", c.Ports.SidecarMinPort)
   365  	sidecarMaxPort := b.portVal("ports.sidecar_max_port", c.Ports.SidecarMaxPort)
   366  	if proxyMaxPort < proxyMinPort {
   367  		return RuntimeConfig{}, fmt.Errorf(
   368  			"proxy_min_port must be less than proxy_max_port. To disable, set both to zero.")
   369  	}
   370  	if sidecarMaxPort < sidecarMinPort {
   371  		return RuntimeConfig{}, fmt.Errorf(
   372  			"sidecar_min_port must be less than sidecar_max_port. To disable, set both to zero.")
   373  	}
   374  
   375  	// determine the default bind and advertise address
   376  	//
   377  	// First check whether the user provided an ANY address or whether
   378  	// the expanded template results in an ANY address. In that case we
   379  	// derive an advertise address from the current network
   380  	// configuration since we can listen on an ANY address for incoming
   381  	// traffic but cannot advertise it as the address on which the
   382  	// server can be reached.
   383  
   384  	bindAddrs := b.expandAddrs("bind_addr", c.BindAddr)
   385  	if len(bindAddrs) == 0 {
   386  		return RuntimeConfig{}, fmt.Errorf("bind_addr cannot be empty")
   387  	}
   388  	if len(bindAddrs) > 1 {
   389  		return RuntimeConfig{}, fmt.Errorf("bind_addr cannot contain multiple addresses. Use 'addresses.{dns,http,https}' instead.")
   390  	}
   391  	if isUnixAddr(bindAddrs[0]) {
   392  		return RuntimeConfig{}, fmt.Errorf("bind_addr cannot be a unix socket")
   393  	}
   394  	if !isIPAddr(bindAddrs[0]) {
   395  		return RuntimeConfig{}, fmt.Errorf("bind_addr must be an ip address")
   396  	}
   397  	if ipaddr.IsAny(b.stringVal(c.AdvertiseAddrLAN)) {
   398  		return RuntimeConfig{}, fmt.Errorf("Advertise address cannot be 0.0.0.0, :: or [::]")
   399  	}
   400  	if ipaddr.IsAny(b.stringVal(c.AdvertiseAddrWAN)) {
   401  		return RuntimeConfig{}, fmt.Errorf("Advertise WAN address cannot be 0.0.0.0, :: or [::]")
   402  	}
   403  
   404  	bindAddr := bindAddrs[0].(*net.IPAddr)
   405  	advertiseAddr := b.makeIPAddr(b.expandFirstIP("advertise_addr", c.AdvertiseAddrLAN), bindAddr)
   406  	if ipaddr.IsAny(advertiseAddr) {
   407  
   408  		var addrtyp string
   409  		var detect func() ([]*net.IPAddr, error)
   410  		switch {
   411  		case ipaddr.IsAnyV4(advertiseAddr):
   412  			addrtyp = "private IPv4"
   413  			detect = b.GetPrivateIPv4
   414  			if detect == nil {
   415  				detect = ipaddr.GetPrivateIPv4
   416  			}
   417  
   418  		case ipaddr.IsAnyV6(advertiseAddr):
   419  			addrtyp = "public IPv6"
   420  			detect = b.GetPublicIPv6
   421  			if detect == nil {
   422  				detect = ipaddr.GetPublicIPv6
   423  			}
   424  		}
   425  
   426  		advertiseAddrs, err := detect()
   427  		if err != nil {
   428  			return RuntimeConfig{}, fmt.Errorf("Error detecting %s address: %s", addrtyp, err)
   429  		}
   430  		if len(advertiseAddrs) == 0 {
   431  			return RuntimeConfig{}, fmt.Errorf("No %s address found", addrtyp)
   432  		}
   433  		if len(advertiseAddrs) > 1 {
   434  			return RuntimeConfig{}, fmt.Errorf("Multiple %s addresses found. Please configure one with 'bind' and/or 'advertise'.", addrtyp)
   435  		}
   436  		advertiseAddr = advertiseAddrs[0]
   437  	}
   438  
   439  	// derive other bind addresses from the bindAddr
   440  	rpcBindAddr := b.makeTCPAddr(bindAddr, nil, serverPort)
   441  	serfBindAddrLAN := b.makeTCPAddr(b.expandFirstIP("serf_lan", c.SerfBindAddrLAN), bindAddr, serfPortLAN)
   442  
   443  	// Only initialize serf WAN bind address when its enabled
   444  	var serfBindAddrWAN *net.TCPAddr
   445  	if serfPortWAN >= 0 {
   446  		serfBindAddrWAN = b.makeTCPAddr(b.expandFirstIP("serf_wan", c.SerfBindAddrWAN), bindAddr, serfPortWAN)
   447  	}
   448  
   449  	// derive other advertise addresses from the advertise address
   450  	advertiseAddrLAN := b.makeIPAddr(b.expandFirstIP("advertise_addr", c.AdvertiseAddrLAN), advertiseAddr)
   451  	advertiseAddrWAN := b.makeIPAddr(b.expandFirstIP("advertise_addr_wan", c.AdvertiseAddrWAN), advertiseAddrLAN)
   452  	rpcAdvertiseAddr := &net.TCPAddr{IP: advertiseAddrLAN.IP, Port: serverPort}
   453  	serfAdvertiseAddrLAN := &net.TCPAddr{IP: advertiseAddrLAN.IP, Port: serfPortLAN}
   454  	// Only initialize serf WAN advertise address when its enabled
   455  	var serfAdvertiseAddrWAN *net.TCPAddr
   456  	if serfPortWAN >= 0 {
   457  		serfAdvertiseAddrWAN = &net.TCPAddr{IP: advertiseAddrWAN.IP, Port: serfPortWAN}
   458  	}
   459  
   460  	// determine client addresses
   461  	clientAddrs := b.expandIPs("client_addr", c.ClientAddr)
   462  	dnsAddrs := b.makeAddrs(b.expandAddrs("addresses.dns", c.Addresses.DNS), clientAddrs, dnsPort)
   463  	httpAddrs := b.makeAddrs(b.expandAddrs("addresses.http", c.Addresses.HTTP), clientAddrs, httpPort)
   464  	httpsAddrs := b.makeAddrs(b.expandAddrs("addresses.https", c.Addresses.HTTPS), clientAddrs, httpsPort)
   465  	grpcAddrs := b.makeAddrs(b.expandAddrs("addresses.grpc", c.Addresses.GRPC), clientAddrs, grpcPort)
   466  
   467  	for _, a := range dnsAddrs {
   468  		if x, ok := a.(*net.TCPAddr); ok {
   469  			dnsAddrs = append(dnsAddrs, &net.UDPAddr{IP: x.IP, Port: x.Port})
   470  		}
   471  	}
   472  
   473  	// expand dns recursors
   474  	uniq := map[string]bool{}
   475  	dnsRecursors := []string{}
   476  	for _, r := range c.DNSRecursors {
   477  		x, err := template.Parse(r)
   478  		if err != nil {
   479  			return RuntimeConfig{}, fmt.Errorf("Invalid DNS recursor template %q: %s", r, err)
   480  		}
   481  		for _, addr := range strings.Fields(x) {
   482  			if strings.HasPrefix(addr, "unix://") {
   483  				return RuntimeConfig{}, fmt.Errorf("DNS Recursors cannot be unix sockets: %s", addr)
   484  			}
   485  			if uniq[addr] {
   486  				continue
   487  			}
   488  			uniq[addr] = true
   489  			dnsRecursors = append(dnsRecursors, addr)
   490  		}
   491  	}
   492  
   493  	// Create the default set of tagged addresses.
   494  	if c.TaggedAddresses == nil {
   495  		c.TaggedAddresses = make(map[string]string)
   496  	}
   497  	c.TaggedAddresses["lan"] = advertiseAddrLAN.IP.String()
   498  	c.TaggedAddresses["wan"] = advertiseAddrWAN.IP.String()
   499  
   500  	// segments
   501  	var segments []structs.NetworkSegment
   502  	for _, s := range c.Segments {
   503  		name := b.stringVal(s.Name)
   504  		port := b.portVal(fmt.Sprintf("segments[%s].port", name), s.Port)
   505  		if port <= 0 {
   506  			return RuntimeConfig{}, fmt.Errorf("Port for segment %q cannot be <= 0", name)
   507  		}
   508  
   509  		bind := b.makeTCPAddr(
   510  			b.expandFirstIP(fmt.Sprintf("segments[%s].bind", name), s.Bind),
   511  			bindAddr,
   512  			port,
   513  		)
   514  
   515  		advertise := b.makeTCPAddr(
   516  			b.expandFirstIP(fmt.Sprintf("segments[%s].advertise", name), s.Advertise),
   517  			advertiseAddrLAN,
   518  			port,
   519  		)
   520  
   521  		segments = append(segments, structs.NetworkSegment{
   522  			Name:        name,
   523  			Bind:        bind,
   524  			Advertise:   advertise,
   525  			RPCListener: b.boolVal(s.RPCListener),
   526  		})
   527  	}
   528  
   529  	// Parse the metric filters
   530  	var telemetryAllowedPrefixes, telemetryBlockedPrefixes []string
   531  	for _, rule := range c.Telemetry.PrefixFilter {
   532  		if rule == "" {
   533  			b.warn("Cannot have empty filter rule in prefix_filter")
   534  			continue
   535  		}
   536  		switch rule[0] {
   537  		case '+':
   538  			telemetryAllowedPrefixes = append(telemetryAllowedPrefixes, rule[1:])
   539  		case '-':
   540  			telemetryBlockedPrefixes = append(telemetryBlockedPrefixes, rule[1:])
   541  		default:
   542  			b.warn("Filter rule must begin with either '+' or '-': %q", rule)
   543  		}
   544  	}
   545  
   546  	// raft performance scaling
   547  	performanceRaftMultiplier := b.intVal(c.Performance.RaftMultiplier)
   548  	if performanceRaftMultiplier < 1 || uint(performanceRaftMultiplier) > consul.MaxRaftMultiplier {
   549  		return RuntimeConfig{}, fmt.Errorf("performance.raft_multiplier cannot be %d. Must be between 1 and %d", performanceRaftMultiplier, consul.MaxRaftMultiplier)
   550  	}
   551  	consulRaftElectionTimeout := b.durationVal("consul.raft.election_timeout", c.Consul.Raft.ElectionTimeout) * time.Duration(performanceRaftMultiplier)
   552  	consulRaftHeartbeatTimeout := b.durationVal("consul.raft.heartbeat_timeout", c.Consul.Raft.HeartbeatTimeout) * time.Duration(performanceRaftMultiplier)
   553  	consulRaftLeaderLeaseTimeout := b.durationVal("consul.raft.leader_lease_timeout", c.Consul.Raft.LeaderLeaseTimeout) * time.Duration(performanceRaftMultiplier)
   554  
   555  	// Connect proxy defaults.
   556  	connectEnabled := b.boolVal(c.Connect.Enabled)
   557  	connectCAProvider := b.stringVal(c.Connect.CAProvider)
   558  	connectCAConfig := c.Connect.CAConfig
   559  	if connectCAConfig != nil {
   560  		TranslateKeys(connectCAConfig, map[string]string{
   561  			// Consul CA config
   562  			"private_key":     "PrivateKey",
   563  			"root_cert":       "RootCert",
   564  			"rotation_period": "RotationPeriod",
   565  
   566  			// Vault CA config
   567  			"address":               "Address",
   568  			"token":                 "Token",
   569  			"root_pki_path":         "RootPKIPath",
   570  			"intermediate_pki_path": "IntermediatePKIPath",
   571  			"ca_file":               "CAFile",
   572  			"ca_path":               "CAPath",
   573  			"cert_file":             "CertFile",
   574  			"key_file":              "KeyFile",
   575  			"tls_server_name":       "TLSServerName",
   576  			"tls_skip_verify":       "TLSSkipVerify",
   577  
   578  			// Common CA config
   579  			"leaf_cert_ttl":      "LeafCertTTL",
   580  			"csr_max_per_second": "CSRMaxPerSecond",
   581  			"csr_max_concurrent": "CSRMaxConcurrent",
   582  		})
   583  	}
   584  
   585  	datacenter := strings.ToLower(b.stringVal(c.Datacenter))
   586  
   587  	aclsEnabled := false
   588  	primaryDatacenter := strings.ToLower(b.stringVal(c.PrimaryDatacenter))
   589  	if c.ACLDatacenter != nil {
   590  		b.warn("The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.")
   591  
   592  		if primaryDatacenter == "" {
   593  			primaryDatacenter = strings.ToLower(b.stringVal(c.ACLDatacenter))
   594  		}
   595  
   596  		// when the acl_datacenter config is used it implicitly enables acls
   597  		aclsEnabled = true
   598  	}
   599  
   600  	if c.ACL.Enabled != nil {
   601  		aclsEnabled = b.boolVal(c.ACL.Enabled)
   602  	}
   603  
   604  	aclDC := primaryDatacenter
   605  	if aclsEnabled && aclDC == "" {
   606  		aclDC = datacenter
   607  	}
   608  
   609  	enableTokenReplication := false
   610  	if c.ACLReplicationToken != nil {
   611  		enableTokenReplication = true
   612  	}
   613  
   614  	b.boolValWithDefault(c.ACL.TokenReplication, b.boolValWithDefault(c.EnableACLReplication, enableTokenReplication))
   615  
   616  	proxyDefaultExecMode := b.stringVal(c.Connect.ProxyDefaults.ExecMode)
   617  	proxyDefaultDaemonCommand := c.Connect.ProxyDefaults.DaemonCommand
   618  	proxyDefaultScriptCommand := c.Connect.ProxyDefaults.ScriptCommand
   619  	proxyDefaultConfig := c.Connect.ProxyDefaults.Config
   620  
   621  	enableRemoteScriptChecks := b.boolVal(c.EnableScriptChecks)
   622  	enableLocalScriptChecks := b.boolValWithDefault(c.EnableLocalScriptChecks, enableRemoteScriptChecks)
   623  
   624  	// VerifyServerHostname implies VerifyOutgoing
   625  	verifyServerName := b.boolVal(c.VerifyServerHostname)
   626  	verifyOutgoing := b.boolVal(c.VerifyOutgoing)
   627  	if verifyServerName {
   628  		// Setting only verify_server_hostname is documented to imply
   629  		// verify_outgoing. If it doesn't then we risk sending communication over TCP
   630  		// when we documented it as forcing TLS for RPCs. Enforce this here rather
   631  		// than in several different places through the code that need to reason
   632  		// about it. (See CVE-2018-19653)
   633  		verifyOutgoing = true
   634  	}
   635  
   636  	// ----------------------------------------------------------------
   637  	// build runtime config
   638  	//
   639  	rt = RuntimeConfig{
   640  		// non-user configurable values
   641  		ACLDisabledTTL:             b.durationVal("acl.disabled_ttl", c.ACL.DisabledTTL),
   642  		AEInterval:                 b.durationVal("ae_interval", c.AEInterval),
   643  		CheckDeregisterIntervalMin: b.durationVal("check_deregister_interval_min", c.CheckDeregisterIntervalMin),
   644  		CheckReapInterval:          b.durationVal("check_reap_interval", c.CheckReapInterval),
   645  		Revision:                   b.stringVal(c.Revision),
   646  		SegmentLimit:               b.intVal(c.SegmentLimit),
   647  		SegmentNameLimit:           b.intVal(c.SegmentNameLimit),
   648  		SyncCoordinateIntervalMin:  b.durationVal("sync_coordinate_interval_min", c.SyncCoordinateIntervalMin),
   649  		SyncCoordinateRateTarget:   b.float64Val(c.SyncCoordinateRateTarget),
   650  		Version:                    b.stringVal(c.Version),
   651  		VersionPrerelease:          b.stringVal(c.VersionPrerelease),
   652  
   653  		// consul configuration
   654  		ConsulCoordinateUpdateBatchSize:  b.intVal(c.Consul.Coordinate.UpdateBatchSize),
   655  		ConsulCoordinateUpdateMaxBatches: b.intVal(c.Consul.Coordinate.UpdateMaxBatches),
   656  		ConsulCoordinateUpdatePeriod:     b.durationVal("consul.coordinate.update_period", c.Consul.Coordinate.UpdatePeriod),
   657  		ConsulRaftElectionTimeout:        consulRaftElectionTimeout,
   658  		ConsulRaftHeartbeatTimeout:       consulRaftHeartbeatTimeout,
   659  		ConsulRaftLeaderLeaseTimeout:     consulRaftLeaderLeaseTimeout,
   660  		ConsulServerHealthInterval:       b.durationVal("consul.server.health_interval", c.Consul.Server.HealthInterval),
   661  
   662  		// gossip configuration
   663  		GossipLANGossipInterval: b.durationVal("gossip_lan..gossip_interval", c.GossipLAN.GossipInterval),
   664  		GossipLANGossipNodes:    b.intVal(c.GossipLAN.GossipNodes),
   665  		GossipLANProbeInterval:  b.durationVal("gossip_lan..probe_interval", c.GossipLAN.ProbeInterval),
   666  		GossipLANProbeTimeout:   b.durationVal("gossip_lan..probe_timeout", c.GossipLAN.ProbeTimeout),
   667  		GossipLANSuspicionMult:  b.intVal(c.GossipLAN.SuspicionMult),
   668  		GossipLANRetransmitMult: b.intVal(c.GossipLAN.RetransmitMult),
   669  		GossipWANGossipInterval: b.durationVal("gossip_wan..gossip_interval", c.GossipWAN.GossipInterval),
   670  		GossipWANGossipNodes:    b.intVal(c.GossipWAN.GossipNodes),
   671  		GossipWANProbeInterval:  b.durationVal("gossip_wan..probe_interval", c.GossipWAN.ProbeInterval),
   672  		GossipWANProbeTimeout:   b.durationVal("gossip_wan..probe_timeout", c.GossipWAN.ProbeTimeout),
   673  		GossipWANSuspicionMult:  b.intVal(c.GossipWAN.SuspicionMult),
   674  		GossipWANRetransmitMult: b.intVal(c.GossipWAN.RetransmitMult),
   675  
   676  		// ACL
   677  		ACLEnforceVersion8:        b.boolValWithDefault(c.ACLEnforceVersion8, true),
   678  		ACLsEnabled:               aclsEnabled,
   679  		ACLAgentMasterToken:       b.stringValWithDefault(c.ACL.Tokens.AgentMaster, b.stringVal(c.ACLAgentMasterToken)),
   680  		ACLAgentToken:             b.stringValWithDefault(c.ACL.Tokens.Agent, b.stringVal(c.ACLAgentToken)),
   681  		ACLDatacenter:             aclDC,
   682  		ACLDefaultPolicy:          b.stringValWithDefault(c.ACL.DefaultPolicy, b.stringVal(c.ACLDefaultPolicy)),
   683  		ACLDownPolicy:             b.stringValWithDefault(c.ACL.DownPolicy, b.stringVal(c.ACLDownPolicy)),
   684  		ACLEnableKeyListPolicy:    b.boolValWithDefault(c.ACL.EnableKeyListPolicy, b.boolVal(c.ACLEnableKeyListPolicy)),
   685  		ACLMasterToken:            b.stringValWithDefault(c.ACL.Tokens.Master, b.stringVal(c.ACLMasterToken)),
   686  		ACLReplicationToken:       b.stringValWithDefault(c.ACL.Tokens.Replication, b.stringVal(c.ACLReplicationToken)),
   687  		ACLTokenTTL:               b.durationValWithDefault("acl.token_ttl", c.ACL.TokenTTL, b.durationVal("acl_ttl", c.ACLTTL)),
   688  		ACLPolicyTTL:              b.durationVal("acl.policy_ttl", c.ACL.PolicyTTL),
   689  		ACLToken:                  b.stringValWithDefault(c.ACL.Tokens.Default, b.stringVal(c.ACLToken)),
   690  		ACLTokenReplication:       b.boolValWithDefault(c.ACL.TokenReplication, b.boolValWithDefault(c.EnableACLReplication, enableTokenReplication)),
   691  		ACLEnableTokenPersistence: b.boolValWithDefault(c.ACL.EnableTokenPersistence, false),
   692  
   693  		// Autopilot
   694  		AutopilotCleanupDeadServers:      b.boolVal(c.Autopilot.CleanupDeadServers),
   695  		AutopilotDisableUpgradeMigration: b.boolVal(c.Autopilot.DisableUpgradeMigration),
   696  		AutopilotLastContactThreshold:    b.durationVal("autopilot.last_contact_threshold", c.Autopilot.LastContactThreshold),
   697  		AutopilotMaxTrailingLogs:         b.intVal(c.Autopilot.MaxTrailingLogs),
   698  		AutopilotRedundancyZoneTag:       b.stringVal(c.Autopilot.RedundancyZoneTag),
   699  		AutopilotServerStabilizationTime: b.durationVal("autopilot.server_stabilization_time", c.Autopilot.ServerStabilizationTime),
   700  		AutopilotUpgradeVersionTag:       b.stringVal(c.Autopilot.UpgradeVersionTag),
   701  
   702  		// DNS
   703  		DNSAddrs:              dnsAddrs,
   704  		DNSAllowStale:         b.boolVal(c.DNS.AllowStale),
   705  		DNSARecordLimit:       b.intVal(c.DNS.ARecordLimit),
   706  		DNSDisableCompression: b.boolVal(c.DNS.DisableCompression),
   707  		DNSDomain:             b.stringVal(c.DNSDomain),
   708  		DNSEnableTruncate:     b.boolVal(c.DNS.EnableTruncate),
   709  		DNSMaxStale:           b.durationVal("dns_config.max_stale", c.DNS.MaxStale),
   710  		DNSNodeTTL:            b.durationVal("dns_config.node_ttl", c.DNS.NodeTTL),
   711  		DNSOnlyPassing:        b.boolVal(c.DNS.OnlyPassing),
   712  		DNSPort:               dnsPort,
   713  		DNSRecursorTimeout:    b.durationVal("recursor_timeout", c.DNS.RecursorTimeout),
   714  		DNSRecursors:          dnsRecursors,
   715  		DNSServiceTTL:         dnsServiceTTL,
   716  		DNSSOA:                soa,
   717  		DNSUDPAnswerLimit:     b.intVal(c.DNS.UDPAnswerLimit),
   718  		DNSNodeMetaTXT:        b.boolValWithDefault(c.DNS.NodeMetaTXT, true),
   719  		DNSUseCache:           b.boolVal(c.DNS.UseCache),
   720  		DNSCacheMaxAge:        b.durationVal("dns_config.cache_max_age", c.DNS.CacheMaxAge),
   721  
   722  		// HTTP
   723  		HTTPPort:            httpPort,
   724  		HTTPSPort:           httpsPort,
   725  		HTTPAddrs:           httpAddrs,
   726  		HTTPSAddrs:          httpsAddrs,
   727  		HTTPBlockEndpoints:  c.HTTPConfig.BlockEndpoints,
   728  		HTTPResponseHeaders: c.HTTPConfig.ResponseHeaders,
   729  		AllowWriteHTTPFrom:  b.cidrsVal("allow_write_http_from", c.HTTPConfig.AllowWriteHTTPFrom),
   730  
   731  		// Telemetry
   732  		Telemetry: lib.TelemetryConfig{
   733  			CirconusAPIApp:                     b.stringVal(c.Telemetry.CirconusAPIApp),
   734  			CirconusAPIToken:                   b.stringVal(c.Telemetry.CirconusAPIToken),
   735  			CirconusAPIURL:                     b.stringVal(c.Telemetry.CirconusAPIURL),
   736  			CirconusBrokerID:                   b.stringVal(c.Telemetry.CirconusBrokerID),
   737  			CirconusBrokerSelectTag:            b.stringVal(c.Telemetry.CirconusBrokerSelectTag),
   738  			CirconusCheckDisplayName:           b.stringVal(c.Telemetry.CirconusCheckDisplayName),
   739  			CirconusCheckForceMetricActivation: b.stringVal(c.Telemetry.CirconusCheckForceMetricActivation),
   740  			CirconusCheckID:                    b.stringVal(c.Telemetry.CirconusCheckID),
   741  			CirconusCheckInstanceID:            b.stringVal(c.Telemetry.CirconusCheckInstanceID),
   742  			CirconusCheckSearchTag:             b.stringVal(c.Telemetry.CirconusCheckSearchTag),
   743  			CirconusCheckTags:                  b.stringVal(c.Telemetry.CirconusCheckTags),
   744  			CirconusSubmissionInterval:         b.stringVal(c.Telemetry.CirconusSubmissionInterval),
   745  			CirconusSubmissionURL:              b.stringVal(c.Telemetry.CirconusSubmissionURL),
   746  			DisableHostname:                    b.boolVal(c.Telemetry.DisableHostname),
   747  			DogstatsdAddr:                      b.stringVal(c.Telemetry.DogstatsdAddr),
   748  			DogstatsdTags:                      c.Telemetry.DogstatsdTags,
   749  			PrometheusRetentionTime:            b.durationVal("prometheus_retention_time", c.Telemetry.PrometheusRetentionTime),
   750  			FilterDefault:                      b.boolVal(c.Telemetry.FilterDefault),
   751  			AllowedPrefixes:                    telemetryAllowedPrefixes,
   752  			BlockedPrefixes:                    telemetryBlockedPrefixes,
   753  			MetricsPrefix:                      b.stringVal(c.Telemetry.MetricsPrefix),
   754  			StatsdAddr:                         b.stringVal(c.Telemetry.StatsdAddr),
   755  			StatsiteAddr:                       b.stringVal(c.Telemetry.StatsiteAddr),
   756  		},
   757  
   758  		// Agent
   759  		AdvertiseAddrLAN:                        advertiseAddrLAN,
   760  		AdvertiseAddrWAN:                        advertiseAddrWAN,
   761  		BindAddr:                                bindAddr,
   762  		Bootstrap:                               b.boolVal(c.Bootstrap),
   763  		BootstrapExpect:                         b.intVal(c.BootstrapExpect),
   764  		CAFile:                                  b.stringVal(c.CAFile),
   765  		CAPath:                                  b.stringVal(c.CAPath),
   766  		CertFile:                                b.stringVal(c.CertFile),
   767  		CheckUpdateInterval:                     b.durationVal("check_update_interval", c.CheckUpdateInterval),
   768  		Checks:                                  checks,
   769  		ClientAddrs:                             clientAddrs,
   770  		ConnectEnabled:                          connectEnabled,
   771  		ConnectCAProvider:                       connectCAProvider,
   772  		ConnectCAConfig:                         connectCAConfig,
   773  		ConnectProxyAllowManagedRoot:            b.boolVal(c.Connect.Proxy.AllowManagedRoot),
   774  		ConnectProxyAllowManagedAPIRegistration: b.boolVal(c.Connect.Proxy.AllowManagedAPIRegistration),
   775  		ConnectProxyBindMinPort:                 proxyMinPort,
   776  		ConnectProxyBindMaxPort:                 proxyMaxPort,
   777  		ConnectSidecarMinPort:                   sidecarMinPort,
   778  		ConnectSidecarMaxPort:                   sidecarMaxPort,
   779  		ConnectProxyDefaultExecMode:             proxyDefaultExecMode,
   780  		ConnectProxyDefaultDaemonCommand:        proxyDefaultDaemonCommand,
   781  		ConnectProxyDefaultScriptCommand:        proxyDefaultScriptCommand,
   782  		ConnectProxyDefaultConfig:               proxyDefaultConfig,
   783  		DataDir:                                 b.stringVal(c.DataDir),
   784  		Datacenter:                              datacenter,
   785  		DevMode:                                 b.boolVal(b.Flags.DevMode),
   786  		DisableAnonymousSignature:               b.boolVal(c.DisableAnonymousSignature),
   787  		DisableCoordinates:                      b.boolVal(c.DisableCoordinates),
   788  		DisableHostNodeID:                       b.boolVal(c.DisableHostNodeID),
   789  		DisableHTTPUnprintableCharFilter:        b.boolVal(c.DisableHTTPUnprintableCharFilter),
   790  		DisableKeyringFile:                      b.boolVal(c.DisableKeyringFile),
   791  		DisableRemoteExec:                       b.boolVal(c.DisableRemoteExec),
   792  		DisableUpdateCheck:                      b.boolVal(c.DisableUpdateCheck),
   793  		DiscardCheckOutput:                      b.boolVal(c.DiscardCheckOutput),
   794  		DiscoveryMaxStale:                       b.durationVal("discovery_max_stale", c.DiscoveryMaxStale),
   795  		EnableAgentTLSForChecks:                 b.boolVal(c.EnableAgentTLSForChecks),
   796  		EnableDebug:                             b.boolVal(c.EnableDebug),
   797  		EnableRemoteScriptChecks:                enableRemoteScriptChecks,
   798  		EnableLocalScriptChecks:                 enableLocalScriptChecks,
   799  		EnableSyslog:                            b.boolVal(c.EnableSyslog),
   800  		EnableUI:                                b.boolVal(c.UI),
   801  		EncryptKey:                              b.stringVal(c.EncryptKey),
   802  		EncryptVerifyIncoming:                   b.boolVal(c.EncryptVerifyIncoming),
   803  		EncryptVerifyOutgoing:                   b.boolVal(c.EncryptVerifyOutgoing),
   804  		GRPCPort:                                grpcPort,
   805  		GRPCAddrs:                               grpcAddrs,
   806  		KeyFile:                                 b.stringVal(c.KeyFile),
   807  		LeaveDrainTime:                          b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
   808  		LeaveOnTerm:                             leaveOnTerm,
   809  		LogLevel:                                b.stringVal(c.LogLevel),
   810  		LogFile:                                 b.stringVal(c.LogFile),
   811  		LogRotateBytes:                          b.intVal(c.LogRotateBytes),
   812  		LogRotateDuration:                       b.durationVal("log_rotate_duration", c.LogRotateDuration),
   813  		NodeID:                                  types.NodeID(b.stringVal(c.NodeID)),
   814  		NodeMeta:                                c.NodeMeta,
   815  		NodeName:                                b.nodeName(c.NodeName),
   816  		NonVotingServer:                         b.boolVal(c.NonVotingServer),
   817  		PidFile:                                 b.stringVal(c.PidFile),
   818  		PrimaryDatacenter:                       primaryDatacenter,
   819  		RPCAdvertiseAddr:                        rpcAdvertiseAddr,
   820  		RPCBindAddr:                             rpcBindAddr,
   821  		RPCHoldTimeout:                          b.durationVal("performance.rpc_hold_timeout", c.Performance.RPCHoldTimeout),
   822  		RPCMaxBurst:                             b.intVal(c.Limits.RPCMaxBurst),
   823  		RPCProtocol:                             b.intVal(c.RPCProtocol),
   824  		RPCRateLimit:                            rate.Limit(b.float64Val(c.Limits.RPCRate)),
   825  		RaftProtocol:                            b.intVal(c.RaftProtocol),
   826  		RaftSnapshotThreshold:                   b.intVal(c.RaftSnapshotThreshold),
   827  		RaftSnapshotInterval:                    b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval),
   828  		ReconnectTimeoutLAN:                     b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN),
   829  		ReconnectTimeoutWAN:                     b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN),
   830  		RejoinAfterLeave:                        b.boolVal(c.RejoinAfterLeave),
   831  		RetryJoinIntervalLAN:                    b.durationVal("retry_interval", c.RetryJoinIntervalLAN),
   832  		RetryJoinIntervalWAN:                    b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN),
   833  		RetryJoinLAN:                            b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN),
   834  		RetryJoinMaxAttemptsLAN:                 b.intVal(c.RetryJoinMaxAttemptsLAN),
   835  		RetryJoinMaxAttemptsWAN:                 b.intVal(c.RetryJoinMaxAttemptsWAN),
   836  		RetryJoinWAN:                            b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN),
   837  		SegmentName:                             b.stringVal(c.SegmentName),
   838  		Segments:                                segments,
   839  		SerfAdvertiseAddrLAN:                    serfAdvertiseAddrLAN,
   840  		SerfAdvertiseAddrWAN:                    serfAdvertiseAddrWAN,
   841  		SerfBindAddrLAN:                         serfBindAddrLAN,
   842  		SerfBindAddrWAN:                         serfBindAddrWAN,
   843  		SerfPortLAN:                             serfPortLAN,
   844  		SerfPortWAN:                             serfPortWAN,
   845  		ServerMode:                              b.boolVal(c.ServerMode),
   846  		ServerName:                              b.stringVal(c.ServerName),
   847  		ServerPort:                              serverPort,
   848  		Services:                                services,
   849  		SessionTTLMin:                           b.durationVal("session_ttl_min", c.SessionTTLMin),
   850  		SkipLeaveOnInt:                          skipLeaveOnInt,
   851  		StartJoinAddrsLAN:                       b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN),
   852  		StartJoinAddrsWAN:                       b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN),
   853  		SyslogFacility:                          b.stringVal(c.SyslogFacility),
   854  		TLSCipherSuites:                         b.tlsCipherSuites("tls_cipher_suites", c.TLSCipherSuites),
   855  		TLSMinVersion:                           b.stringVal(c.TLSMinVersion),
   856  		TLSPreferServerCipherSuites:             b.boolVal(c.TLSPreferServerCipherSuites),
   857  		TaggedAddresses:                         c.TaggedAddresses,
   858  		TranslateWANAddrs:                       b.boolVal(c.TranslateWANAddrs),
   859  		UIDir:                                   b.stringVal(c.UIDir),
   860  		UnixSocketGroup:                         b.stringVal(c.UnixSocket.Group),
   861  		UnixSocketMode:                          b.stringVal(c.UnixSocket.Mode),
   862  		UnixSocketUser:                          b.stringVal(c.UnixSocket.User),
   863  		VerifyIncoming:                          b.boolVal(c.VerifyIncoming),
   864  		VerifyIncomingHTTPS:                     b.boolVal(c.VerifyIncomingHTTPS),
   865  		VerifyIncomingRPC:                       b.boolVal(c.VerifyIncomingRPC),
   866  		VerifyOutgoing:                          verifyOutgoing,
   867  		VerifyServerHostname:                    verifyServerName,
   868  		Watches:                                 c.Watches,
   869  	}
   870  
   871  	if rt.BootstrapExpect == 1 {
   872  		rt.Bootstrap = true
   873  		rt.BootstrapExpect = 0
   874  		b.warn(`BootstrapExpect is set to 1; this is the same as Bootstrap mode.`)
   875  	}
   876  
   877  	return rt, nil
   878  }
   879  
   880  // Validate performs semantical validation of the runtime configuration.
   881  func (b *Builder) Validate(rt RuntimeConfig) error {
   882  	// reDatacenter defines a regexp for a valid datacenter name
   883  	var reDatacenter = regexp.MustCompile("^[a-z0-9_-]+$")
   884  
   885  	// ----------------------------------------------------------------
   886  	// check required params we cannot recover from first
   887  	//
   888  
   889  	if rt.Datacenter == "" {
   890  		return fmt.Errorf("datacenter cannot be empty")
   891  	}
   892  	if !reDatacenter.MatchString(rt.Datacenter) {
   893  		return fmt.Errorf("datacenter cannot be %q. Please use only [a-z0-9-_].", rt.Datacenter)
   894  	}
   895  	if rt.DataDir == "" && !rt.DevMode {
   896  		return fmt.Errorf("data_dir cannot be empty")
   897  	}
   898  	if !rt.DevMode {
   899  		fi, err := os.Stat(rt.DataDir)
   900  		switch {
   901  		case err != nil && !os.IsNotExist(err):
   902  			return fmt.Errorf("Error getting info on data_dir: %s", err)
   903  		case err == nil && !fi.IsDir():
   904  			return fmt.Errorf("data_dir %q is not a directory", rt.DataDir)
   905  		}
   906  	}
   907  	if rt.NodeName == "" {
   908  		return fmt.Errorf("node_name cannot be empty")
   909  	}
   910  	if ipaddr.IsAny(rt.AdvertiseAddrLAN.IP) {
   911  		return fmt.Errorf("Advertise address cannot be 0.0.0.0, :: or [::]")
   912  	}
   913  	if ipaddr.IsAny(rt.AdvertiseAddrWAN.IP) {
   914  		return fmt.Errorf("Advertise WAN address cannot be 0.0.0.0, :: or [::]")
   915  	}
   916  	if err := b.validateSegments(rt); err != nil {
   917  		return err
   918  	}
   919  	for _, a := range rt.DNSAddrs {
   920  		if _, ok := a.(*net.UnixAddr); ok {
   921  			return fmt.Errorf("DNS address cannot be a unix socket")
   922  		}
   923  	}
   924  	for _, a := range rt.DNSRecursors {
   925  		if ipaddr.IsAny(a) {
   926  			return fmt.Errorf("DNS recursor address cannot be 0.0.0.0, :: or [::]")
   927  		}
   928  	}
   929  	if rt.Bootstrap && !rt.ServerMode {
   930  		return fmt.Errorf("'bootstrap = true' requires 'server = true'")
   931  	}
   932  	if rt.BootstrapExpect < 0 {
   933  		return fmt.Errorf("bootstrap_expect cannot be %d. Must be greater than or equal to zero", rt.BootstrapExpect)
   934  	}
   935  	if rt.BootstrapExpect > 0 && !rt.ServerMode {
   936  		return fmt.Errorf("'bootstrap_expect > 0' requires 'server = true'")
   937  	}
   938  	if rt.BootstrapExpect > 0 && rt.DevMode {
   939  		return fmt.Errorf("'bootstrap_expect > 0' not allowed in dev mode")
   940  	}
   941  	if rt.BootstrapExpect > 0 && rt.Bootstrap {
   942  		return fmt.Errorf("'bootstrap_expect > 0' and 'bootstrap = true' are mutually exclusive")
   943  	}
   944  	if rt.AEInterval <= 0 {
   945  		return fmt.Errorf("ae_interval cannot be %s. Must be positive", rt.AEInterval)
   946  	}
   947  	if rt.AutopilotMaxTrailingLogs < 0 {
   948  		return fmt.Errorf("autopilot.max_trailing_logs cannot be %d. Must be greater than or equal to zero", rt.AutopilotMaxTrailingLogs)
   949  	}
   950  	if rt.ACLDatacenter != "" && !reDatacenter.MatchString(rt.ACLDatacenter) {
   951  		return fmt.Errorf("acl_datacenter cannot be %q. Please use only [a-z0-9-_].", rt.ACLDatacenter)
   952  	}
   953  	if rt.EnableUI && rt.UIDir != "" {
   954  		return fmt.Errorf(
   955  			"Both the ui and ui-dir flags were specified, please provide only one.\n" +
   956  				"If trying to use your own web UI resources, use the ui-dir flag.\n" +
   957  				"If using Consul version 0.7.0 or later, the web UI is included in the binary so use ui to enable it")
   958  	}
   959  	if rt.DNSUDPAnswerLimit < 0 {
   960  		return fmt.Errorf("dns_config.udp_answer_limit cannot be %d. Must be greater than or equal to zero", rt.DNSUDPAnswerLimit)
   961  	}
   962  	if rt.DNSARecordLimit < 0 {
   963  		return fmt.Errorf("dns_config.a_record_limit cannot be %d. Must be greater than or equal to zero", rt.DNSARecordLimit)
   964  	}
   965  	if err := structs.ValidateMetadata(rt.NodeMeta, false); err != nil {
   966  		return fmt.Errorf("node_meta invalid: %v", err)
   967  	}
   968  	if rt.EncryptKey != "" {
   969  		if _, err := decodeBytes(rt.EncryptKey); err != nil {
   970  			return fmt.Errorf("encrypt has invalid key: %s", err)
   971  		}
   972  		keyfileLAN := filepath.Join(rt.DataDir, SerfLANKeyring)
   973  		if _, err := os.Stat(keyfileLAN); err == nil {
   974  			b.warn("WARNING: LAN keyring exists but -encrypt given, using keyring")
   975  		}
   976  		if rt.ServerMode {
   977  			keyfileWAN := filepath.Join(rt.DataDir, SerfWANKeyring)
   978  			if _, err := os.Stat(keyfileWAN); err == nil {
   979  				b.warn("WARNING: WAN keyring exists but -encrypt given, using keyring")
   980  			}
   981  		}
   982  	}
   983  
   984  	// Check the data dir for signs of an un-migrated Consul 0.5.x or older
   985  	// server. Consul refuses to start if this is present to protect a server
   986  	// with existing data from starting on a fresh data set.
   987  	if rt.ServerMode {
   988  		mdbPath := filepath.Join(rt.DataDir, "mdb")
   989  		if _, err := os.Stat(mdbPath); !os.IsNotExist(err) {
   990  			if os.IsPermission(err) {
   991  				return fmt.Errorf(
   992  					"CRITICAL: Permission denied for data folder at %q!\n"+
   993  						"Consul will refuse to boot without access to this directory.\n"+
   994  						"Please correct permissions and try starting again.", mdbPath)
   995  			}
   996  			return fmt.Errorf("CRITICAL: Deprecated data folder found at %q!\n"+
   997  				"Consul will refuse to boot with this directory present.\n"+
   998  				"See https://www.consul.io/docs/upgrade-specific.html for more information.", mdbPath)
   999  		}
  1000  	}
  1001  
  1002  	inuse := map[string]string{}
  1003  	if err := addrsUnique(inuse, "DNS", rt.DNSAddrs); err != nil {
  1004  		// cannot happen since this is the first address
  1005  		// we leave this for consistency
  1006  		return err
  1007  	}
  1008  	if err := addrsUnique(inuse, "HTTP", rt.HTTPAddrs); err != nil {
  1009  		return err
  1010  	}
  1011  	if err := addrsUnique(inuse, "HTTPS", rt.HTTPSAddrs); err != nil {
  1012  		return err
  1013  	}
  1014  	if err := addrUnique(inuse, "RPC Advertise", rt.RPCAdvertiseAddr); err != nil {
  1015  		return err
  1016  	}
  1017  	if err := addrUnique(inuse, "Serf Advertise LAN", rt.SerfAdvertiseAddrLAN); err != nil {
  1018  		return err
  1019  	}
  1020  	// Validate serf WAN advertise address only when its set
  1021  	if rt.SerfAdvertiseAddrWAN != nil {
  1022  		if err := addrUnique(inuse, "Serf Advertise WAN", rt.SerfAdvertiseAddrWAN); err != nil {
  1023  			return err
  1024  		}
  1025  	}
  1026  	if b.err != nil {
  1027  		return b.err
  1028  	}
  1029  
  1030  	// Check for errors in the service definitions
  1031  	for _, s := range rt.Services {
  1032  		if err := s.Validate(); err != nil {
  1033  			return fmt.Errorf("service %q: %s", s.Name, err)
  1034  		}
  1035  	}
  1036  
  1037  	// Validate the given Connect CA provider config
  1038  	validCAProviders := map[string]bool{
  1039  		"":                       true,
  1040  		structs.ConsulCAProvider: true,
  1041  		structs.VaultCAProvider:  true,
  1042  	}
  1043  	if _, ok := validCAProviders[rt.ConnectCAProvider]; !ok {
  1044  		return fmt.Errorf("%s is not a valid CA provider", rt.ConnectCAProvider)
  1045  	} else {
  1046  		switch rt.ConnectCAProvider {
  1047  		case structs.ConsulCAProvider:
  1048  			if _, err := ca.ParseConsulCAConfig(rt.ConnectCAConfig); err != nil {
  1049  				return err
  1050  			}
  1051  		case structs.VaultCAProvider:
  1052  			if _, err := ca.ParseVaultCAConfig(rt.ConnectCAConfig); err != nil {
  1053  				return err
  1054  			}
  1055  		}
  1056  	}
  1057  
  1058  	// ----------------------------------------------------------------
  1059  	// warnings
  1060  	//
  1061  
  1062  	if rt.ServerMode && !rt.DevMode && !rt.Bootstrap && rt.BootstrapExpect == 2 {
  1063  		b.warn(`bootstrap_expect = 2: A cluster with 2 servers will provide no failure tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`)
  1064  	}
  1065  
  1066  	if rt.ServerMode && !rt.Bootstrap && rt.BootstrapExpect > 2 && rt.BootstrapExpect%2 == 0 {
  1067  		b.warn(`bootstrap_expect is even number: A cluster with an even number of servers does not achieve optimum fault tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`)
  1068  	}
  1069  
  1070  	if rt.ServerMode && rt.Bootstrap && rt.BootstrapExpect == 0 {
  1071  		b.warn(`bootstrap = true: do not enable unless necessary`)
  1072  	}
  1073  
  1074  	if rt.ServerMode && !rt.DevMode && !rt.Bootstrap && rt.BootstrapExpect > 1 {
  1075  		b.warn("bootstrap_expect > 0: expecting %d servers", rt.BootstrapExpect)
  1076  	}
  1077  
  1078  	return nil
  1079  }
  1080  
  1081  // addrUnique checks if the given address is already in use for another
  1082  // protocol.
  1083  func addrUnique(inuse map[string]string, name string, addr net.Addr) error {
  1084  	key := addr.Network() + ":" + addr.String()
  1085  	if other, ok := inuse[key]; ok {
  1086  		return fmt.Errorf("%s address %s already configured for %s", name, addr.String(), other)
  1087  	}
  1088  	inuse[key] = name
  1089  	return nil
  1090  }
  1091  
  1092  // addrsUnique checks if any of the give addresses is already in use for
  1093  // another protocol.
  1094  func addrsUnique(inuse map[string]string, name string, addrs []net.Addr) error {
  1095  	for _, a := range addrs {
  1096  		if err := addrUnique(inuse, name, a); err != nil {
  1097  			return err
  1098  		}
  1099  	}
  1100  	return nil
  1101  }
  1102  
  1103  // splitSlicesAndValues moves all slice values defined in c to 'slices'
  1104  // and all other values to 'values'.
  1105  func (b *Builder) splitSlicesAndValues(c Config) (slices, values Config) {
  1106  	v, t := reflect.ValueOf(c), reflect.TypeOf(c)
  1107  	rs, rv := reflect.New(t), reflect.New(t)
  1108  
  1109  	for i := 0; i < t.NumField(); i++ {
  1110  		f := t.Field(i)
  1111  		if f.Type.Kind() == reflect.Slice {
  1112  			rs.Elem().Field(i).Set(v.Field(i))
  1113  		} else {
  1114  			rv.Elem().Field(i).Set(v.Field(i))
  1115  		}
  1116  	}
  1117  	return rs.Elem().Interface().(Config), rv.Elem().Interface().(Config)
  1118  }
  1119  
  1120  func (b *Builder) warn(msg string, args ...interface{}) {
  1121  	b.Warnings = append(b.Warnings, fmt.Sprintf(msg, args...))
  1122  }
  1123  
  1124  func (b *Builder) checkVal(v *CheckDefinition) *structs.CheckDefinition {
  1125  	if v == nil {
  1126  		return nil
  1127  	}
  1128  
  1129  	id := types.CheckID(b.stringVal(v.ID))
  1130  
  1131  	return &structs.CheckDefinition{
  1132  		ID:                             id,
  1133  		Name:                           b.stringVal(v.Name),
  1134  		Notes:                          b.stringVal(v.Notes),
  1135  		ServiceID:                      b.stringVal(v.ServiceID),
  1136  		Token:                          b.stringVal(v.Token),
  1137  		Status:                         b.stringVal(v.Status),
  1138  		ScriptArgs:                     v.ScriptArgs,
  1139  		HTTP:                           b.stringVal(v.HTTP),
  1140  		Header:                         v.Header,
  1141  		Method:                         b.stringVal(v.Method),
  1142  		TCP:                            b.stringVal(v.TCP),
  1143  		Interval:                       b.durationVal(fmt.Sprintf("check[%s].interval", id), v.Interval),
  1144  		DockerContainerID:              b.stringVal(v.DockerContainerID),
  1145  		Shell:                          b.stringVal(v.Shell),
  1146  		GRPC:                           b.stringVal(v.GRPC),
  1147  		GRPCUseTLS:                     b.boolVal(v.GRPCUseTLS),
  1148  		TLSSkipVerify:                  b.boolVal(v.TLSSkipVerify),
  1149  		AliasNode:                      b.stringVal(v.AliasNode),
  1150  		AliasService:                   b.stringVal(v.AliasService),
  1151  		Timeout:                        b.durationVal(fmt.Sprintf("check[%s].timeout", id), v.Timeout),
  1152  		TTL:                            b.durationVal(fmt.Sprintf("check[%s].ttl", id), v.TTL),
  1153  		DeregisterCriticalServiceAfter: b.durationVal(fmt.Sprintf("check[%s].deregister_critical_service_after", id), v.DeregisterCriticalServiceAfter),
  1154  	}
  1155  }
  1156  
  1157  func (b *Builder) serviceVal(v *ServiceDefinition) *structs.ServiceDefinition {
  1158  	if v == nil {
  1159  		return nil
  1160  	}
  1161  
  1162  	var checks structs.CheckTypes
  1163  	for _, check := range v.Checks {
  1164  		checks = append(checks, b.checkVal(&check).CheckType())
  1165  	}
  1166  	if v.Check != nil {
  1167  		checks = append(checks, b.checkVal(v.Check).CheckType())
  1168  	}
  1169  
  1170  	meta := make(map[string]string)
  1171  	if err := structs.ValidateMetadata(v.Meta, false); err != nil {
  1172  		b.err = multierror.Append(fmt.Errorf("invalid meta for service %s: %v", b.stringVal(v.Name), err))
  1173  	} else {
  1174  		meta = v.Meta
  1175  	}
  1176  	serviceWeights := &structs.Weights{Passing: 1, Warning: 1}
  1177  	if v.Weights != nil {
  1178  		if v.Weights.Passing != nil {
  1179  			serviceWeights.Passing = *v.Weights.Passing
  1180  		}
  1181  		if v.Weights.Warning != nil {
  1182  			serviceWeights.Warning = *v.Weights.Warning
  1183  		}
  1184  	}
  1185  
  1186  	if err := structs.ValidateWeights(serviceWeights); err != nil {
  1187  		b.err = multierror.Append(fmt.Errorf("Invalid weight definition for service %s: %s", b.stringVal(v.Name), err))
  1188  	}
  1189  	return &structs.ServiceDefinition{
  1190  		Kind:              b.serviceKindVal(v.Kind),
  1191  		ID:                b.stringVal(v.ID),
  1192  		Name:              b.stringVal(v.Name),
  1193  		Tags:              v.Tags,
  1194  		Address:           b.stringVal(v.Address),
  1195  		Meta:              meta,
  1196  		Port:              b.intVal(v.Port),
  1197  		Token:             b.stringVal(v.Token),
  1198  		EnableTagOverride: b.boolVal(v.EnableTagOverride),
  1199  		Weights:           serviceWeights,
  1200  		Checks:            checks,
  1201  		// DEPRECATED (ProxyDestination) - don't populate deprecated field, just use
  1202  		// it as a default below on read. Remove that when removing ProxyDestination
  1203  		Proxy:   b.serviceProxyVal(v.Proxy, v.ProxyDestination),
  1204  		Connect: b.serviceConnectVal(v.Connect),
  1205  	}
  1206  }
  1207  
  1208  func (b *Builder) serviceKindVal(v *string) structs.ServiceKind {
  1209  	if v == nil {
  1210  		return structs.ServiceKindTypical
  1211  	}
  1212  	switch *v {
  1213  	case string(structs.ServiceKindConnectProxy):
  1214  		return structs.ServiceKindConnectProxy
  1215  	default:
  1216  		return structs.ServiceKindTypical
  1217  	}
  1218  }
  1219  
  1220  func (b *Builder) serviceProxyVal(v *ServiceProxy, deprecatedDest *string) *structs.ConnectProxyConfig {
  1221  	if v == nil {
  1222  		if deprecatedDest != nil {
  1223  			return &structs.ConnectProxyConfig{
  1224  				DestinationServiceName: b.stringVal(deprecatedDest),
  1225  			}
  1226  		}
  1227  		return nil
  1228  	}
  1229  
  1230  	return &structs.ConnectProxyConfig{
  1231  		DestinationServiceName: b.stringVal(v.DestinationServiceName),
  1232  		DestinationServiceID:   b.stringVal(v.DestinationServiceID),
  1233  		LocalServiceAddress:    b.stringVal(v.LocalServiceAddress),
  1234  		LocalServicePort:       b.intVal(v.LocalServicePort),
  1235  		Config:                 v.Config,
  1236  		Upstreams:              b.upstreamsVal(v.Upstreams),
  1237  	}
  1238  }
  1239  
  1240  func (b *Builder) upstreamsVal(v []Upstream) structs.Upstreams {
  1241  	ups := make(structs.Upstreams, len(v))
  1242  	for i, u := range v {
  1243  		ups[i] = structs.Upstream{
  1244  			DestinationType:      b.stringVal(u.DestinationType),
  1245  			DestinationNamespace: b.stringVal(u.DestinationNamespace),
  1246  			DestinationName:      b.stringVal(u.DestinationName),
  1247  			Datacenter:           b.stringVal(u.Datacenter),
  1248  			LocalBindAddress:     b.stringVal(u.LocalBindAddress),
  1249  			LocalBindPort:        b.intVal(u.LocalBindPort),
  1250  			Config:               u.Config,
  1251  		}
  1252  		if ups[i].DestinationType == "" {
  1253  			ups[i].DestinationType = structs.UpstreamDestTypeService
  1254  		}
  1255  	}
  1256  	return ups
  1257  }
  1258  
  1259  func (b *Builder) serviceConnectVal(v *ServiceConnect) *structs.ServiceConnect {
  1260  	if v == nil {
  1261  		return nil
  1262  	}
  1263  
  1264  	var proxy *structs.ServiceDefinitionConnectProxy
  1265  	if v.Proxy != nil {
  1266  		proxy = &structs.ServiceDefinitionConnectProxy{
  1267  			ExecMode:  b.stringVal(v.Proxy.ExecMode),
  1268  			Command:   v.Proxy.Command,
  1269  			Config:    v.Proxy.Config,
  1270  			Upstreams: b.upstreamsVal(v.Proxy.Upstreams),
  1271  		}
  1272  	}
  1273  
  1274  	sidecar := b.serviceVal(v.SidecarService)
  1275  	if sidecar != nil {
  1276  		// Sanity checks
  1277  		if sidecar.ID != "" {
  1278  			b.err = multierror.Append(b.err, fmt.Errorf("sidecar_service can't specify an ID"))
  1279  			sidecar.ID = ""
  1280  		}
  1281  		if sidecar.Connect != nil {
  1282  			if sidecar.Connect.SidecarService != nil {
  1283  				b.err = multierror.Append(b.err, fmt.Errorf("sidecar_service can't have a nested sidecar_service"))
  1284  				sidecar.Connect.SidecarService = nil
  1285  			}
  1286  			if sidecar.Connect.Proxy != nil {
  1287  				b.err = multierror.Append(b.err, fmt.Errorf("sidecar_service can't have a managed proxy"))
  1288  				sidecar.Connect.Proxy = nil
  1289  			}
  1290  		}
  1291  	}
  1292  
  1293  	return &structs.ServiceConnect{
  1294  		Native:         b.boolVal(v.Native),
  1295  		Proxy:          proxy,
  1296  		SidecarService: sidecar,
  1297  	}
  1298  }
  1299  
  1300  func (b *Builder) boolValWithDefault(v *bool, defaultVal bool) bool {
  1301  	if v == nil {
  1302  		return defaultVal
  1303  	}
  1304  
  1305  	return *v
  1306  }
  1307  
  1308  func (b *Builder) boolVal(v *bool) bool {
  1309  	return b.boolValWithDefault(v, false)
  1310  }
  1311  
  1312  func (b *Builder) durationValWithDefault(name string, v *string, defaultVal time.Duration) (d time.Duration) {
  1313  	if v == nil {
  1314  		return defaultVal
  1315  	}
  1316  	d, err := time.ParseDuration(*v)
  1317  	if err != nil {
  1318  		b.err = multierror.Append(fmt.Errorf("%s: invalid duration: %q: %s", name, *v, err))
  1319  	}
  1320  	return d
  1321  }
  1322  
  1323  func (b *Builder) durationVal(name string, v *string) (d time.Duration) {
  1324  	return b.durationValWithDefault(name, v, 0)
  1325  }
  1326  
  1327  func (b *Builder) intVal(v *int) int {
  1328  	if v == nil {
  1329  		return 0
  1330  	}
  1331  	return *v
  1332  }
  1333  
  1334  func (b *Builder) portVal(name string, v *int) int {
  1335  	if v == nil || *v <= 0 {
  1336  		return -1
  1337  	}
  1338  	if *v > 65535 {
  1339  		b.err = multierror.Append(b.err, fmt.Errorf("%s: invalid port: %d", name, *v))
  1340  	}
  1341  	return *v
  1342  }
  1343  
  1344  func (b *Builder) stringValWithDefault(v *string, defaultVal string) string {
  1345  	if v == nil {
  1346  		return defaultVal
  1347  	}
  1348  	return *v
  1349  }
  1350  
  1351  func (b *Builder) stringVal(v *string) string {
  1352  	return b.stringValWithDefault(v, "")
  1353  }
  1354  
  1355  func (b *Builder) float64Val(v *float64) float64 {
  1356  	if v == nil {
  1357  		return 0
  1358  	}
  1359  
  1360  	return *v
  1361  }
  1362  
  1363  func (b *Builder) cidrsVal(name string, v []string) (nets []*net.IPNet) {
  1364  	if v == nil {
  1365  		return
  1366  	}
  1367  
  1368  	for _, p := range v {
  1369  		_, net, err := net.ParseCIDR(strings.TrimSpace(p))
  1370  		if err != nil {
  1371  			b.err = multierror.Append(b.err, fmt.Errorf("%s: invalid cidr: %s", name, p))
  1372  		}
  1373  		nets = append(nets, net)
  1374  	}
  1375  
  1376  	return
  1377  }
  1378  
  1379  func (b *Builder) tlsCipherSuites(name string, v *string) []uint16 {
  1380  	if v == nil {
  1381  		return nil
  1382  	}
  1383  
  1384  	var a []uint16
  1385  	a, err := tlsutil.ParseCiphers(*v)
  1386  	if err != nil {
  1387  		b.err = multierror.Append(b.err, fmt.Errorf("%s: invalid tls cipher suites: %s", name, err))
  1388  	}
  1389  	return a
  1390  }
  1391  
  1392  func (b *Builder) nodeName(v *string) string {
  1393  	nodeName := b.stringVal(v)
  1394  	if nodeName == "" {
  1395  		fn := b.Hostname
  1396  		if fn == nil {
  1397  			fn = os.Hostname
  1398  		}
  1399  		name, err := fn()
  1400  		if err != nil {
  1401  			b.err = multierror.Append(b.err, fmt.Errorf("node_name: %s", err))
  1402  			return ""
  1403  		}
  1404  		nodeName = name
  1405  	}
  1406  	return strings.TrimSpace(nodeName)
  1407  }
  1408  
  1409  // expandAddrs expands the go-sockaddr template in s and returns the
  1410  // result as a list of *net.IPAddr and *net.UnixAddr.
  1411  func (b *Builder) expandAddrs(name string, s *string) []net.Addr {
  1412  	if s == nil || *s == "" {
  1413  		return nil
  1414  	}
  1415  
  1416  	x, err := template.Parse(*s)
  1417  	if err != nil {
  1418  		b.err = multierror.Append(b.err, fmt.Errorf("%s: error parsing %q: %s", name, *s, err))
  1419  		return nil
  1420  	}
  1421  
  1422  	var addrs []net.Addr
  1423  	for _, a := range strings.Fields(x) {
  1424  		switch {
  1425  		case strings.HasPrefix(a, "unix://"):
  1426  			addrs = append(addrs, &net.UnixAddr{Name: a[len("unix://"):], Net: "unix"})
  1427  		default:
  1428  			// net.ParseIP does not like '[::]'
  1429  			ip := net.ParseIP(a)
  1430  			if a == "[::]" {
  1431  				ip = net.ParseIP("::")
  1432  			}
  1433  			if ip == nil {
  1434  				b.err = multierror.Append(b.err, fmt.Errorf("%s: invalid ip address: %s", name, a))
  1435  				return nil
  1436  			}
  1437  			addrs = append(addrs, &net.IPAddr{IP: ip})
  1438  		}
  1439  	}
  1440  
  1441  	return addrs
  1442  }
  1443  
  1444  // expandOptionalAddrs expands the go-sockaddr template in s and returns the
  1445  // result as a list of strings. If s does not contain a go-sockaddr template,
  1446  // the result list will contain the input string as a single element with no
  1447  // error set. In contrast to expandAddrs, expandOptionalAddrs does not validate
  1448  // if the result contains valid addresses and returns a list of strings.
  1449  // However, if the expansion of the go-sockaddr template fails an error is set.
  1450  func (b *Builder) expandOptionalAddrs(name string, s *string) []string {
  1451  	if s == nil || *s == "" {
  1452  		return nil
  1453  	}
  1454  
  1455  	x, err := template.Parse(*s)
  1456  	if err != nil {
  1457  		b.err = multierror.Append(b.err, fmt.Errorf("%s: error parsing %q: %s", name, *s, err))
  1458  		return nil
  1459  	}
  1460  
  1461  	if x != *s {
  1462  		// A template has been expanded, split the results from go-sockaddr
  1463  		return strings.Fields(x)
  1464  	} else {
  1465  		// No template has been expanded, pass through the input
  1466  		return []string{*s}
  1467  	}
  1468  }
  1469  
  1470  func (b *Builder) expandAllOptionalAddrs(name string, addrs []string) []string {
  1471  	out := make([]string, 0, len(addrs))
  1472  	for _, a := range addrs {
  1473  		expanded := b.expandOptionalAddrs(name, &a)
  1474  		if expanded != nil {
  1475  			out = append(out, expanded...)
  1476  		}
  1477  	}
  1478  	return out
  1479  }
  1480  
  1481  // expandIPs expands the go-sockaddr template in s and returns a list of
  1482  // *net.IPAddr. If one of the expanded addresses is a unix socket
  1483  // address an error is set and nil is returned.
  1484  func (b *Builder) expandIPs(name string, s *string) []*net.IPAddr {
  1485  	if s == nil || *s == "" {
  1486  		return nil
  1487  	}
  1488  
  1489  	addrs := b.expandAddrs(name, s)
  1490  	var x []*net.IPAddr
  1491  	for _, addr := range addrs {
  1492  		switch a := addr.(type) {
  1493  		case *net.IPAddr:
  1494  			x = append(x, a)
  1495  		case *net.UnixAddr:
  1496  			b.err = multierror.Append(b.err, fmt.Errorf("%s cannot be a unix socket", name))
  1497  			return nil
  1498  		default:
  1499  			b.err = multierror.Append(b.err, fmt.Errorf("%s has invalid address type %T", name, a))
  1500  			return nil
  1501  		}
  1502  	}
  1503  	return x
  1504  }
  1505  
  1506  // expandFirstAddr expands the go-sockaddr template in s and returns the
  1507  // first address which is either a *net.IPAddr or a *net.UnixAddr. If
  1508  // the template expands to multiple addresses an error is set and nil
  1509  // is returned.
  1510  func (b *Builder) expandFirstAddr(name string, s *string) net.Addr {
  1511  	if s == nil || *s == "" {
  1512  		return nil
  1513  	}
  1514  
  1515  	addrs := b.expandAddrs(name, s)
  1516  	if len(addrs) == 0 {
  1517  		return nil
  1518  	}
  1519  	if len(addrs) > 1 {
  1520  		var x []string
  1521  		for _, a := range addrs {
  1522  			x = append(x, a.String())
  1523  		}
  1524  		b.err = multierror.Append(b.err, fmt.Errorf("%s: multiple addresses found: %s", name, strings.Join(x, " ")))
  1525  		return nil
  1526  	}
  1527  	return addrs[0]
  1528  }
  1529  
  1530  // expandFirstIP expands the go-sockaddr template in s and returns the
  1531  // first address if it is not a unix socket address. If the template
  1532  // expands to multiple addresses an error is set and nil is returned.
  1533  func (b *Builder) expandFirstIP(name string, s *string) *net.IPAddr {
  1534  	if s == nil || *s == "" {
  1535  		return nil
  1536  	}
  1537  
  1538  	addr := b.expandFirstAddr(name, s)
  1539  	if addr == nil {
  1540  		return nil
  1541  	}
  1542  	switch a := addr.(type) {
  1543  	case *net.IPAddr:
  1544  		return a
  1545  	case *net.UnixAddr:
  1546  		b.err = multierror.Append(b.err, fmt.Errorf("%s cannot be a unix socket", name))
  1547  		return nil
  1548  	default:
  1549  		b.err = multierror.Append(b.err, fmt.Errorf("%s has invalid address type %T", name, a))
  1550  		return nil
  1551  	}
  1552  }
  1553  
  1554  func (b *Builder) makeIPAddr(pri *net.IPAddr, sec *net.IPAddr) *net.IPAddr {
  1555  	if pri != nil {
  1556  		return pri
  1557  	}
  1558  	return sec
  1559  }
  1560  
  1561  func (b *Builder) makeTCPAddr(pri *net.IPAddr, sec net.Addr, port int) *net.TCPAddr {
  1562  	if pri == nil && reflect.ValueOf(sec).IsNil() || port <= 0 {
  1563  		return nil
  1564  	}
  1565  	addr := pri
  1566  	if addr == nil {
  1567  		switch a := sec.(type) {
  1568  		case *net.IPAddr:
  1569  			addr = a
  1570  		case *net.TCPAddr:
  1571  			addr = &net.IPAddr{IP: a.IP}
  1572  		default:
  1573  			panic(fmt.Sprintf("makeTCPAddr requires a net.IPAddr or a net.TCPAddr. Got %T", a))
  1574  		}
  1575  	}
  1576  	return &net.TCPAddr{IP: addr.IP, Port: port}
  1577  }
  1578  
  1579  // makeAddr creates an *net.TCPAddr or a *net.UnixAddr from either the
  1580  // primary or secondary address and the given port. If the port is <= 0
  1581  // then the address is considered to be disabled and nil is returned.
  1582  func (b *Builder) makeAddr(pri, sec net.Addr, port int) net.Addr {
  1583  	if reflect.ValueOf(pri).IsNil() && reflect.ValueOf(sec).IsNil() || port <= 0 {
  1584  		return nil
  1585  	}
  1586  	addr := pri
  1587  	if addr == nil {
  1588  		addr = sec
  1589  	}
  1590  	switch a := addr.(type) {
  1591  	case *net.IPAddr:
  1592  		return &net.TCPAddr{IP: a.IP, Port: port}
  1593  	case *net.UnixAddr:
  1594  		return a
  1595  	default:
  1596  		panic(fmt.Sprintf("invalid address type %T", a))
  1597  	}
  1598  }
  1599  
  1600  // makeAddrs creates a list of *net.TCPAddr or *net.UnixAddr entries
  1601  // from either the primary or secondary addresses and the given port.
  1602  // If the port is <= 0 then the address is considered to be disabled
  1603  // and nil is returned.
  1604  func (b *Builder) makeAddrs(pri []net.Addr, sec []*net.IPAddr, port int) []net.Addr {
  1605  	if len(pri) == 0 && len(sec) == 0 || port <= 0 {
  1606  		return nil
  1607  	}
  1608  	addrs := pri
  1609  	if len(addrs) == 0 {
  1610  		addrs = []net.Addr{}
  1611  		for _, a := range sec {
  1612  			addrs = append(addrs, a)
  1613  		}
  1614  	}
  1615  	var x []net.Addr
  1616  	for _, a := range addrs {
  1617  		x = append(x, b.makeAddr(a, nil, port))
  1618  	}
  1619  	return x
  1620  }
  1621  
  1622  // isUnixAddr returns true when the given address is a unix socket address type.
  1623  func (b *Builder) isUnixAddr(a net.Addr) bool {
  1624  	_, ok := a.(*net.UnixAddr)
  1625  	return a != nil && ok
  1626  }
  1627  
  1628  // decodeBytes returns the encryption key decoded.
  1629  func decodeBytes(key string) ([]byte, error) {
  1630  	return base64.StdEncoding.DecodeString(key)
  1631  }
  1632  
  1633  func isIPAddr(a net.Addr) bool {
  1634  	_, ok := a.(*net.IPAddr)
  1635  	return ok
  1636  }
  1637  
  1638  func isUnixAddr(a net.Addr) bool {
  1639  	_, ok := a.(*net.UnixAddr)
  1640  	return ok
  1641  }