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