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