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