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