1package tlsutil 2 3import ( 4 "crypto/tls" 5 "crypto/x509" 6 "fmt" 7 "io/ioutil" 8 "net" 9 "os" 10 "path/filepath" 11 "sort" 12 "strings" 13 "sync" 14 "time" 15 16 "github.com/hashicorp/go-hclog" 17 18 "github.com/hashicorp/consul/logging" 19) 20 21// ALPNWrapper is a function that is used to wrap a non-TLS connection and 22// returns an appropriate TLS connection or error. This taks a datacenter and 23// node name as argument to configure the desired SNI value and the desired 24// next proto for configuring ALPN. 25type ALPNWrapper func(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) 26 27// DCWrapper is a function that is used to wrap a non-TLS connection 28// and returns an appropriate TLS connection or error. This takes 29// a datacenter as an argument. 30type DCWrapper func(dc string, conn net.Conn) (net.Conn, error) 31 32// Wrapper is a variant of DCWrapper, where the DC is provided as 33// a constant value. This is usually done by currying DCWrapper. 34type Wrapper func(conn net.Conn) (net.Conn, error) 35 36// TLSLookup maps the tls_min_version configuration to the internal value 37var TLSLookup = map[string]uint16{ 38 "": tls.VersionTLS10, // default in golang 39 "tls10": tls.VersionTLS10, 40 "tls11": tls.VersionTLS11, 41 "tls12": tls.VersionTLS12, 42 "tls13": tls.VersionTLS13, 43} 44 45// TLSVersions has all the keys from the map above. 46var TLSVersions = strings.Join(tlsVersions(), ", ") 47 48// Config used to create tls.Config 49type Config struct { 50 // VerifyIncoming is used to verify the authenticity of incoming 51 // connections. This means that TCP requests are forbidden, only 52 // allowing for TLS. TLS connections must match a provided certificate 53 // authority. This can be used to force client auth. 54 VerifyIncoming bool 55 56 // VerifyIncomingRPC is used to verify the authenticity of incoming RPC 57 // connections. This means that TCP requests are forbidden, only 58 // allowing for TLS. TLS connections must match a provided certificate 59 // authority. This can be used to force client auth. 60 VerifyIncomingRPC bool 61 62 // VerifyIncomingHTTPS is used to verify the authenticity of incoming 63 // HTTPS connections. This means that TCP requests are forbidden, only 64 // allowing for TLS. TLS connections must match a provided certificate 65 // authority. This can be used to force client auth. 66 VerifyIncomingHTTPS bool 67 68 // VerifyOutgoing is used to verify the authenticity of outgoing 69 // connections. This means that TLS requests are used, and TCP 70 // requests are not made. TLS connections must match a provided 71 // certificate authority. This is used to verify authenticity of server 72 // nodes. 73 VerifyOutgoing bool 74 75 // VerifyServerHostname is used to enable hostname verification of 76 // servers. This ensures that the certificate presented is valid for 77 // server.<datacenter>.<domain>. This prevents a compromised client 78 // from being restarted as a server, and then intercepting request 79 // traffic as well as being added as a raft peer. This should be 80 // enabled by default with VerifyOutgoing, but for legacy reasons we 81 // cannot break existing clients. 82 VerifyServerHostname bool 83 84 // CAFile is a path to a certificate authority file. This is used with 85 // VerifyIncoming or VerifyOutgoing to verify the TLS connection. 86 CAFile string 87 88 // CAPath is a path to a directory containing certificate authority 89 // files. This is used with VerifyIncoming or VerifyOutgoing to verify 90 // the TLS connection. 91 CAPath string 92 93 // CertFile is used to provide a TLS certificate that is used for 94 // serving TLS connections. Must be provided to serve TLS connections. 95 CertFile string 96 97 // KeyFile is used to provide a TLS key that is used for serving TLS 98 // connections. Must be provided to serve TLS connections. 99 KeyFile string 100 101 // Node name is the name we use to advertise. Defaults to hostname. 102 NodeName string 103 104 // ServerName is used with the TLS certificate to ensure the name we 105 // provide matches the certificate 106 ServerName string 107 108 // Domain is the Consul TLD being used. Defaults to "consul." 109 Domain string 110 111 // TLSMinVersion is the minimum accepted TLS version that can be used. 112 TLSMinVersion string 113 114 // CipherSuites is the list of TLS cipher suites to use. 115 CipherSuites []uint16 116 117 // PreferServerCipherSuites specifies whether to prefer the server's 118 // ciphersuite over the client ciphersuites. 119 PreferServerCipherSuites bool 120 121 // EnableAgentTLSForChecks is used to apply the agent's TLS settings in 122 // order to configure the HTTP client used for health checks. Enabling 123 // this allows HTTP checks to present a client certificate and verify 124 // the server using the same TLS configuration as the agent (CA, cert, 125 // and key). 126 EnableAgentTLSForChecks bool 127 128 // AutoTLS opts the agent into provisioning agent 129 // TLS certificates. 130 AutoTLS bool 131} 132 133func tlsVersions() []string { 134 versions := []string{} 135 for v := range TLSLookup { 136 if v != "" { 137 versions = append(versions, v) 138 } 139 } 140 sort.Strings(versions) 141 return versions 142} 143 144// KeyPair is used to open and parse a certificate and key file 145func (c *Config) KeyPair() (*tls.Certificate, error) { 146 return loadKeyPair(c.CertFile, c.KeyFile) 147} 148 149// SpecificDC is used to invoke a static datacenter 150// and turns a DCWrapper into a Wrapper type. 151func SpecificDC(dc string, tlsWrap DCWrapper) Wrapper { 152 if tlsWrap == nil { 153 return nil 154 } 155 return func(conn net.Conn) (net.Conn, error) { 156 return tlsWrap(dc, conn) 157 } 158} 159 160type autoTLS struct { 161 extraCAPems []string 162 connectCAPems []string 163 cert *tls.Certificate 164 verifyServerHostname bool 165} 166 167// manual stores the TLS CA and cert received from Configurator.Update which 168// generally comes from the agent configuration. 169type manual struct { 170 caPems []string 171 cert *tls.Certificate 172 // caPool containing only the caPems. This CertPool should be used instead of 173 // the Configurator.caPool when only the Agent TLS CA is allowed. 174 caPool *x509.CertPool 175} 176 177// Configurator holds a Config and is responsible for generating all the 178// *tls.Config necessary for Consul. Except the one in the api package. 179type Configurator struct { 180 sync.RWMutex 181 base *Config 182 autoTLS *autoTLS 183 manual *manual 184 peerDatacenterUseTLS map[string]bool 185 186 caPool *x509.CertPool 187 logger hclog.Logger 188 version int 189} 190 191// NewConfigurator creates a new Configurator and sets the provided 192// configuration. 193func NewConfigurator(config Config, logger hclog.Logger) (*Configurator, error) { 194 if logger == nil { 195 logger = hclog.New(&hclog.LoggerOptions{ 196 Level: hclog.Debug, 197 }) 198 } 199 200 c := &Configurator{ 201 logger: logger.Named(logging.TLSUtil), 202 manual: &manual{}, 203 autoTLS: &autoTLS{}, 204 peerDatacenterUseTLS: map[string]bool{}, 205 } 206 err := c.Update(config) 207 if err != nil { 208 return nil, err 209 } 210 return c, nil 211} 212 213// ManualCAPems returns the currently loaded CAs in PEM format. 214func (c *Configurator) ManualCAPems() []string { 215 c.RLock() 216 defer c.RUnlock() 217 return c.manual.caPems 218} 219 220// Update updates the internal configuration which is used to generate 221// *tls.Config. 222// This function acquires a write lock because it writes the new config. 223func (c *Configurator) Update(config Config) error { 224 c.Lock() 225 // order of defers matters because log acquires a RLock() 226 defer c.log("Update") 227 defer c.Unlock() 228 229 cert, err := loadKeyPair(config.CertFile, config.KeyFile) 230 if err != nil { 231 return err 232 } 233 pems, err := LoadCAs(config.CAFile, config.CAPath) 234 if err != nil { 235 return err 236 } 237 caPool, err := newX509CertPool(pems, c.autoTLS.extraCAPems, c.autoTLS.connectCAPems) 238 if err != nil { 239 return err 240 } 241 if err = c.check(config, caPool, cert); err != nil { 242 return err 243 } 244 manualCAPool, err := newX509CertPool(pems) 245 if err != nil { 246 return err 247 } 248 249 c.base = &config 250 c.manual.cert = cert 251 c.manual.caPool = manualCAPool 252 c.manual.caPems = pems 253 c.caPool = caPool 254 c.version++ 255 return nil 256} 257 258// UpdateAutoTLSCA updates the autoEncrypt.caPems. This is supposed to be called 259// from the server in order to be able to accept TLS connections with TLS 260// certificates. 261// Or it is being called on the client side when CA changes are detected. 262func (c *Configurator) UpdateAutoTLSCA(connectCAPems []string) error { 263 c.Lock() 264 // order of defers matters because log acquires a RLock() 265 defer c.log("UpdateAutoEncryptCA") 266 defer c.Unlock() 267 268 pool, err := newX509CertPool(c.manual.caPems, c.autoTLS.extraCAPems, connectCAPems) 269 if err != nil { 270 c.RUnlock() 271 return err 272 } 273 if err = c.check(*c.base, pool, c.manual.cert); err != nil { 274 c.RUnlock() 275 return err 276 } 277 c.autoTLS.connectCAPems = connectCAPems 278 c.caPool = pool 279 c.version++ 280 return nil 281} 282 283// UpdateAutoTLSCert 284func (c *Configurator) UpdateAutoTLSCert(pub, priv string) error { 285 // order of defers matters because log acquires a RLock() 286 defer c.log("UpdateAutoEncryptCert") 287 cert, err := tls.X509KeyPair([]byte(pub), []byte(priv)) 288 if err != nil { 289 return fmt.Errorf("Failed to load cert/key pair: %v", err) 290 } 291 292 c.Lock() 293 defer c.Unlock() 294 295 c.autoTLS.cert = &cert 296 c.version++ 297 return nil 298} 299 300// UpdateAutoTLS sets everything under autoEncrypt. This is being called on the 301// client when it received its cert from AutoEncrypt/AutoConfig endpoints. 302func (c *Configurator) UpdateAutoTLS(manualCAPems, connectCAPems []string, pub, priv string, verifyServerHostname bool) error { 303 // order of defers matters because log acquires a RLock() 304 defer c.log("UpdateAutoEncrypt") 305 cert, err := tls.X509KeyPair([]byte(pub), []byte(priv)) 306 if err != nil { 307 return fmt.Errorf("Failed to load cert/key pair: %v", err) 308 } 309 310 c.Lock() 311 defer c.Unlock() 312 313 pool, err := newX509CertPool(c.manual.caPems, manualCAPems, connectCAPems) 314 if err != nil { 315 return err 316 } 317 c.autoTLS.extraCAPems = manualCAPems 318 c.autoTLS.connectCAPems = connectCAPems 319 c.autoTLS.cert = &cert 320 c.caPool = pool 321 c.autoTLS.verifyServerHostname = verifyServerHostname 322 c.version++ 323 return nil 324} 325 326func (c *Configurator) UpdateAreaPeerDatacenterUseTLS(peerDatacenter string, useTLS bool) { 327 c.Lock() 328 defer c.Unlock() 329 c.version++ 330 c.peerDatacenterUseTLS[peerDatacenter] = useTLS 331} 332 333func (c *Configurator) getAreaForPeerDatacenterUseTLS(peerDatacenter string) bool { 334 c.RLock() 335 defer c.RUnlock() 336 if v, ok := c.peerDatacenterUseTLS[peerDatacenter]; ok { 337 return v 338 } 339 return true 340} 341 342func (c *Configurator) Base() Config { 343 c.RLock() 344 defer c.RUnlock() 345 return *c.base 346} 347 348// newX509CertPool loads all the groups of PEM encoded certificates into a 349// single x509.CertPool. 350// 351// The groups argument is a varargs of slices so that callers do not need to 352// append slices together. In some cases append can modify the backing array 353// of the first slice passed to append, which will often result in hard to 354// find bugs. By accepting a varargs of slices we remove the need for the 355// caller to append the groups, which should prevent any such bugs. 356func newX509CertPool(groups ...[]string) (*x509.CertPool, error) { 357 pool := x509.NewCertPool() 358 for _, group := range groups { 359 for _, pem := range group { 360 if !pool.AppendCertsFromPEM([]byte(pem)) { 361 return nil, fmt.Errorf("failed to parse PEM %s", pem) 362 } 363 } 364 } 365 if len(pool.Subjects()) == 0 { 366 return nil, nil 367 } 368 return pool, nil 369} 370 371func (c *Configurator) check(config Config, pool *x509.CertPool, cert *tls.Certificate) error { 372 // Check if a minimum TLS version was set 373 if config.TLSMinVersion != "" { 374 if _, ok := TLSLookup[config.TLSMinVersion]; !ok { 375 return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", config.TLSMinVersion, TLSVersions) 376 } 377 } 378 379 // Ensure we have a CA if VerifyOutgoing is set 380 if config.VerifyOutgoing && pool == nil { 381 return fmt.Errorf("VerifyOutgoing set, and no CA certificate provided!") 382 } 383 384 // Ensure we have a CA and cert if VerifyIncoming is set 385 if config.anyVerifyIncoming() { 386 if pool == nil { 387 // both auto-config and auto-encrypt require verifying the connection from the client to the server for secure 388 // operation. In order to be able to verify the servers certificate we must have some CA certs already provided. 389 // Therefore, even though both of those features can push down extra CA certificates which could be used to 390 // verify incoming connections, we still must consider it an error if none are provided in the initial configuration 391 // as those features cannot be successfully enabled without providing CA certificates to use those features. 392 return fmt.Errorf("VerifyIncoming set but no CA certificates were provided") 393 } 394 395 // We will use the auto_encrypt/auto_config cert for TLS in the incoming APIs when available. Therefore the check 396 // here will ensure that either we enabled one of those two features or a certificate and key were provided manually 397 if cert == nil && !config.AutoTLS { 398 return fmt.Errorf("VerifyIncoming requires either a Cert and Key pair in the configuration file, or auto_encrypt/auto_config be enabled") 399 } 400 } 401 return nil 402} 403 404func (c Config) anyVerifyIncoming() bool { 405 return c.baseVerifyIncoming() || c.VerifyIncomingRPC || c.VerifyIncomingHTTPS 406} 407 408func (c Config) verifyIncomingRPC() bool { 409 return c.baseVerifyIncoming() || c.VerifyIncomingRPC 410} 411 412func (c Config) verifyIncomingHTTPS() bool { 413 return c.baseVerifyIncoming() || c.VerifyIncomingHTTPS 414} 415 416func (c *Config) baseVerifyIncoming() bool { 417 return c.VerifyIncoming 418} 419 420func loadKeyPair(certFile, keyFile string) (*tls.Certificate, error) { 421 if certFile == "" || keyFile == "" { 422 return nil, nil 423 } 424 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 425 if err != nil { 426 return nil, fmt.Errorf("Failed to load cert/key pair: %v", err) 427 } 428 return &cert, nil 429} 430 431func LoadCAs(caFile, caPath string) ([]string, error) { 432 if caFile == "" && caPath == "" { 433 return nil, nil 434 } 435 436 pems := []string{} 437 438 readFn := func(path string) error { 439 pem, err := ioutil.ReadFile(path) 440 if err != nil { 441 return fmt.Errorf("Error loading from %s: %s", path, err) 442 } 443 pems = append(pems, string(pem)) 444 return nil 445 } 446 447 walkFn := func(path string, info os.FileInfo, err error) error { 448 if err != nil { 449 return err 450 } 451 452 if !info.IsDir() { 453 if err := readFn(path); err != nil { 454 return err 455 } 456 } 457 return nil 458 } 459 460 if caFile != "" { 461 err := readFn(caFile) 462 if err != nil { 463 return pems, err 464 } 465 } else if caPath != "" { 466 err := filepath.Walk(caPath, walkFn) 467 if err != nil { 468 return pems, err 469 } 470 if len(pems) == 0 { 471 return pems, fmt.Errorf("Error loading from CAPath: no CAs found") 472 } 473 } 474 return pems, nil 475} 476 477// commonTLSConfig generates a *tls.Config from the base configuration the 478// Configurator has. It accepts an additional flag in case a config is needed 479// for incoming TLS connections. 480// This function acquires a read lock because it reads from the config. 481func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config { 482 // this needs to be outside of RLock because it acquires an RLock itself 483 verifyServerHostname := c.VerifyServerHostname() 484 485 c.RLock() 486 defer c.RUnlock() 487 tlsConfig := &tls.Config{ 488 InsecureSkipVerify: !verifyServerHostname, 489 } 490 491 // Set the cipher suites 492 if len(c.base.CipherSuites) != 0 { 493 tlsConfig.CipherSuites = c.base.CipherSuites 494 } 495 496 tlsConfig.PreferServerCipherSuites = c.base.PreferServerCipherSuites 497 498 // GetCertificate is used when acting as a server and responding to 499 // client requests. Default to the manually configured cert, but allow 500 // autoEncrypt cert too so that a client can encrypt incoming 501 // connections without having a manual cert configured. 502 tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 503 return c.Cert(), nil 504 } 505 506 // GetClientCertificate is used when acting as a client and responding 507 // to a server requesting a certificate. Return the autoEncrypt certificate 508 // if possible, otherwise default to the manually provisioned one. 509 tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { 510 cert := c.autoTLS.cert 511 if cert == nil { 512 cert = c.manual.cert 513 } 514 515 if cert == nil { 516 // the return value MUST not be nil but an empty certificate will be 517 // treated the same as having no client certificate 518 cert = &tls.Certificate{} 519 } 520 521 return cert, nil 522 } 523 524 tlsConfig.ClientCAs = c.caPool 525 tlsConfig.RootCAs = c.caPool 526 527 // This is possible because TLSLookup also contains "" with golang's 528 // default (tls10). And because the initial check makes sure the 529 // version correctly matches. 530 tlsConfig.MinVersion = TLSLookup[c.base.TLSMinVersion] 531 532 // Set ClientAuth if necessary 533 if verifyIncoming { 534 tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert 535 } 536 537 return tlsConfig 538} 539 540// This function acquires a read lock because it reads from the config. 541func (c *Configurator) Cert() *tls.Certificate { 542 c.RLock() 543 defer c.RUnlock() 544 cert := c.manual.cert 545 if cert == nil { 546 cert = c.autoTLS.cert 547 } 548 return cert 549} 550 551// This function acquires a read lock because it reads from the config. 552func (c *Configurator) VerifyIncomingRPC() bool { 553 c.RLock() 554 defer c.RUnlock() 555 return c.base.verifyIncomingRPC() 556} 557 558// This function acquires a read lock because it reads from the config. 559func (c *Configurator) outgoingRPCTLSDisabled() bool { 560 c.RLock() 561 defer c.RUnlock() 562 563 // if AutoEncrypt enabled, always use TLS 564 if c.base.AutoTLS { 565 return false 566 } 567 568 // if CAs are provided or VerifyOutgoing is set, use TLS 569 if c.base.VerifyOutgoing { 570 return false 571 } 572 573 return true 574} 575 576func (c *Configurator) MutualTLSCapable() bool { 577 return c.mutualTLSCapable() 578} 579 580// This function acquires a read lock because it reads from the config. 581func (c *Configurator) mutualTLSCapable() bool { 582 c.RLock() 583 defer c.RUnlock() 584 return c.caPool != nil && (c.autoTLS.cert != nil || c.manual.cert != nil) 585} 586 587// This function acquires a read lock because it reads from the config. 588func (c *Configurator) verifyOutgoing() bool { 589 c.RLock() 590 defer c.RUnlock() 591 592 // If AutoEncryptTLS is enabled and there is a CA, then verify 593 // outgoing. 594 if c.base.AutoTLS && c.caPool != nil { 595 return true 596 } 597 598 return c.base.VerifyOutgoing 599} 600 601func (c *Configurator) ServerSNI(dc, nodeName string) string { 602 // Strip the trailing '.' from the domain if any 603 domain := strings.TrimSuffix(c.domain(), ".") 604 605 if nodeName == "" || nodeName == "*" { 606 return "server." + dc + "." + domain 607 } 608 609 return nodeName + ".server." + dc + "." + domain 610} 611 612// This function acquires a read lock because it reads from the config. 613func (c *Configurator) domain() string { 614 c.RLock() 615 defer c.RUnlock() 616 return c.base.Domain 617} 618 619// This function acquires a read lock because it reads from the config. 620func (c *Configurator) verifyIncomingRPC() bool { 621 c.RLock() 622 defer c.RUnlock() 623 return c.base.verifyIncomingRPC() 624} 625 626// This function acquires a read lock because it reads from the config. 627func (c *Configurator) verifyIncomingHTTPS() bool { 628 c.RLock() 629 defer c.RUnlock() 630 return c.base.verifyIncomingHTTPS() 631} 632 633// This function acquires a read lock because it reads from the config. 634func (c *Configurator) enableAgentTLSForChecks() bool { 635 c.RLock() 636 defer c.RUnlock() 637 return c.base.EnableAgentTLSForChecks 638} 639 640// This function acquires a read lock because it reads from the config. 641func (c *Configurator) serverNameOrNodeName() string { 642 c.RLock() 643 defer c.RUnlock() 644 if c.base.ServerName != "" { 645 return c.base.ServerName 646 } 647 return c.base.NodeName 648} 649 650// This function acquires a read lock because it reads from the config. 651func (c *Configurator) VerifyServerHostname() bool { 652 c.RLock() 653 defer c.RUnlock() 654 return c.base.VerifyServerHostname || c.autoTLS.verifyServerHostname 655} 656 657// IncomingGRPCConfig generates a *tls.Config for incoming GRPC connections. 658func (c *Configurator) IncomingGRPCConfig() *tls.Config { 659 c.log("IncomingGRPCConfig") 660 661 // false has the effect that this config doesn't require a client cert 662 // verification. This is because there is no verify_incoming_grpc 663 // configuration option. And using verify_incoming would be backwards 664 // incompatible, because even if it was set before, it didn't have an 665 // effect on the grpc server. 666 config := c.commonTLSConfig(false) 667 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 668 return c.IncomingGRPCConfig(), nil 669 } 670 return config 671} 672 673// IncomingRPCConfig generates a *tls.Config for incoming RPC connections. 674func (c *Configurator) IncomingRPCConfig() *tls.Config { 675 c.log("IncomingRPCConfig") 676 config := c.commonTLSConfig(c.verifyIncomingRPC()) 677 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 678 return c.IncomingRPCConfig(), nil 679 } 680 return config 681} 682 683// IncomingALPNRPCConfig generates a *tls.Config for incoming RPC connections 684// directly using TLS with ALPN instead of the older byte-prefixed protocol. 685func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config { 686 c.log("IncomingALPNRPCConfig") 687 // Since the ALPN-RPC variation is indirectly exposed to the internet via 688 // mesh gateways we force mTLS and full server name verification. 689 config := c.commonTLSConfig(true) 690 config.InsecureSkipVerify = false 691 692 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 693 return c.IncomingALPNRPCConfig(alpnProtos), nil 694 } 695 config.NextProtos = alpnProtos 696 return config 697} 698 699// IncomingInsecureRPCConfig means that it doesn't verify incoming even thought 700// it might have been configured. This is only supposed to be used by the 701// servers for the insecure RPC server. At the time of writing only the 702// AutoEncrypt.Sign call is supported on that server. And it might be the only 703// usecase ever. 704func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config { 705 c.log("IncomingInsecureRPCConfig") 706 config := c.commonTLSConfig(false) 707 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 708 return c.IncomingInsecureRPCConfig(), nil 709 } 710 return config 711} 712 713// IncomingHTTPSConfig generates a *tls.Config for incoming HTTPS connections. 714func (c *Configurator) IncomingHTTPSConfig() *tls.Config { 715 c.log("IncomingHTTPSConfig") 716 config := c.commonTLSConfig(c.verifyIncomingHTTPS()) 717 config.NextProtos = []string{"h2", "http/1.1"} 718 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 719 return c.IncomingHTTPSConfig(), nil 720 } 721 return config 722} 723 724// OutgoingTLSConfigForCheck generates a *tls.Config for outgoing TLS connections 725// for checks. This function is separated because there is an extra flag to 726// consider for checks. EnableAgentTLSForChecks and InsecureSkipVerify has to 727// be checked for checks. 728func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName string) *tls.Config { 729 c.log("OutgoingTLSConfigForCheck") 730 731 if !c.enableAgentTLSForChecks() { 732 return &tls.Config{ 733 InsecureSkipVerify: skipVerify, 734 ServerName: serverName, 735 } 736 } 737 738 if serverName == "" { 739 serverName = c.serverNameOrNodeName() 740 } 741 config := c.commonTLSConfig(false) 742 config.InsecureSkipVerify = skipVerify 743 config.ServerName = serverName 744 745 return config 746} 747 748// OutgoingRPCConfig generates a *tls.Config for outgoing RPC connections. If 749// there is a CA or VerifyOutgoing is set, a *tls.Config will be provided, 750// otherwise we assume that no TLS should be used. 751func (c *Configurator) OutgoingRPCConfig() *tls.Config { 752 c.log("OutgoingRPCConfig") 753 if c.outgoingRPCTLSDisabled() { 754 return nil 755 } 756 return c.commonTLSConfig(false) 757} 758 759// OutgoingALPNRPCConfig generates a *tls.Config for outgoing RPC connections 760// directly using TLS with ALPN instead of the older byte-prefixed protocol. 761// If there is a CA or VerifyOutgoing is set, a *tls.Config will be provided, 762// otherwise we assume that no TLS should be used which completely disables the 763// ALPN variation. 764func (c *Configurator) OutgoingALPNRPCConfig() *tls.Config { 765 c.log("OutgoingALPNRPCConfig") 766 if !c.mutualTLSCapable() { 767 return nil // ultimately this will hard-fail as TLS is required 768 } 769 770 // Since the ALPN-RPC variation is indirectly exposed to the internet via 771 // mesh gateways we force mTLS and full server name verification. 772 config := c.commonTLSConfig(true) 773 config.InsecureSkipVerify = false 774 return config 775} 776 777// OutgoingRPCWrapper wraps the result of OutgoingRPCConfig in a DCWrapper. It 778// decides if verify server hostname should be used. 779func (c *Configurator) OutgoingRPCWrapper() DCWrapper { 780 c.log("OutgoingRPCWrapper") 781 782 // Generate the wrapper based on dc 783 return func(dc string, conn net.Conn) (net.Conn, error) { 784 if c.UseTLS(dc) { 785 return c.wrapTLSClient(dc, conn) 786 } 787 return conn, nil 788 } 789} 790 791func (c *Configurator) UseTLS(dc string) bool { 792 return !c.outgoingRPCTLSDisabled() && c.getAreaForPeerDatacenterUseTLS(dc) 793} 794 795// OutgoingALPNRPCWrapper wraps the result of OutgoingALPNRPCConfig in an 796// ALPNWrapper. It configures all of the negotiation plumbing. 797func (c *Configurator) OutgoingALPNRPCWrapper() ALPNWrapper { 798 c.log("OutgoingALPNRPCWrapper") 799 if !c.mutualTLSCapable() { 800 return nil 801 } 802 803 return func(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) { 804 return c.wrapALPNTLSClient(dc, nodeName, alpnProto, conn) 805 } 806} 807 808// AutoEncryptCertNotAfter returns NotAfter from the auto_encrypt cert. In case 809// there is no cert, it will return a time in the past. 810func (c *Configurator) AutoEncryptCertNotAfter() time.Time { 811 c.RLock() 812 defer c.RUnlock() 813 tlsCert := c.autoTLS.cert 814 if tlsCert == nil || tlsCert.Certificate == nil { 815 return time.Now().AddDate(0, 0, -1) 816 } 817 cert, err := x509.ParseCertificate(tlsCert.Certificate[0]) 818 if err != nil { 819 return time.Now().AddDate(0, 0, -1) 820 } 821 return cert.NotAfter 822} 823 824// AutoEncryptCertExpired returns if the auto_encrypt cert is expired. 825func (c *Configurator) AutoEncryptCertExpired() bool { 826 return c.AutoEncryptCertNotAfter().Before(time.Now()) 827} 828 829// This function acquires a read lock because it reads from the config. 830func (c *Configurator) log(name string) { 831 if c.logger != nil { 832 c.RLock() 833 defer c.RUnlock() 834 c.logger.Trace(name, "version", c.version) 835 } 836} 837 838// Wrap a net.Conn into a client tls connection, performing any 839// additional verification as needed. 840// 841// As of go 1.3, crypto/tls only supports either doing no certificate 842// verification, or doing full verification including of the peer's 843// DNS name. For consul, we want to validate that the certificate is 844// signed by a known CA, but because consul doesn't use DNS names for 845// node names, we don't verify the certificate DNS names. Since go 1.3 846// no longer supports this mode of operation, we have to do it 847// manually. 848func (c *Configurator) wrapTLSClient(dc string, conn net.Conn) (net.Conn, error) { 849 config := c.OutgoingRPCConfig() 850 verifyServerHostname := c.VerifyServerHostname() 851 verifyOutgoing := c.verifyOutgoing() 852 domain := c.domain() 853 854 if verifyServerHostname { 855 // Strip the trailing '.' from the domain if any 856 domain = strings.TrimSuffix(domain, ".") 857 config.ServerName = "server." + dc + "." + domain 858 } 859 tlsConn := tls.Client(conn, config) 860 861 // If crypto/tls is doing verification, there's no need to do 862 // our own. 863 if !config.InsecureSkipVerify { 864 return tlsConn, nil 865 } 866 867 // If verification is not turned on, don't do it. 868 if !verifyOutgoing { 869 return tlsConn, nil 870 } 871 872 err := tlsConn.Handshake() 873 if err != nil { 874 tlsConn.Close() 875 return nil, err 876 } 877 878 // The following is lightly-modified from the doFullHandshake 879 // method in crypto/tls's handshake_client.go. 880 opts := x509.VerifyOptions{ 881 Roots: config.RootCAs, 882 CurrentTime: time.Now(), 883 DNSName: "", 884 Intermediates: x509.NewCertPool(), 885 } 886 887 certs := tlsConn.ConnectionState().PeerCertificates 888 for i, cert := range certs { 889 if i == 0 { 890 continue 891 } 892 opts.Intermediates.AddCert(cert) 893 } 894 895 _, err = certs[0].Verify(opts) 896 if err != nil { 897 tlsConn.Close() 898 return nil, err 899 } 900 901 return tlsConn, err 902} 903 904// Wrap a net.Conn into a client tls connection suitable for secure ALPN-RPC, 905// performing any additional verification as needed. 906func (c *Configurator) wrapALPNTLSClient(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) { 907 if dc == "" { 908 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target datacenter") 909 } else if nodeName == "" { 910 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target node") 911 } else if alpnProto == "" { 912 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target alpn protocol") 913 } 914 915 config := c.OutgoingALPNRPCConfig() 916 if config == nil { 917 return nil, fmt.Errorf("cannot dial via a mesh gateway when outgoing TLS is disabled") 918 } 919 920 // Since the ALPN-RPC variation is indirectly exposed to the internet via 921 // mesh gateways we force mTLS and full hostname validation (forcing 922 // verify_server_hostname and verify_outgoing to be effectively true). 923 924 config.ServerName = c.ServerSNI(dc, nodeName) 925 config.NextProtos = []string{alpnProto} 926 927 tlsConn := tls.Client(conn, config) 928 929 // NOTE: For this handshake to succeed the server must have key material 930 // for either "<nodename>.server.<datacenter>.<domain>" or 931 // "*.server.<datacenter>.<domain>" in addition to the 932 // "server.<datacenter>.<domain>" required for standard TLS'd RPC. 933 if err := tlsConn.Handshake(); err != nil { 934 tlsConn.Close() 935 return nil, err 936 } 937 938 return tlsConn, nil 939} 940 941// AuthorizeServerConn is used to validate that the connection is being established 942// by a Consul server in the same datacenter. 943// 944// The identity of the connection is checked by verifying that the certificate 945// presented is signed by the Agent TLS CA, and has a DNSName that matches the 946// local ServerSNI name. 947// 948// Note this check is only performed if VerifyServerHostname is enabled, otherwise 949// it does no authorization. 950func (c *Configurator) AuthorizeServerConn(dc string, conn *tls.Conn) error { 951 if !c.VerifyServerHostname() { 952 return nil 953 } 954 955 c.RLock() 956 caPool := c.manual.caPool 957 c.RUnlock() 958 959 expected := c.ServerSNI(dc, "") 960 for _, chain := range conn.ConnectionState().VerifiedChains { 961 if len(chain) == 0 { 962 continue 963 } 964 clientCert := chain[0] 965 _, err := clientCert.Verify(x509.VerifyOptions{ 966 DNSName: expected, 967 Roots: caPool, 968 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 969 }) 970 if err == nil { 971 return nil 972 } 973 c.logger.Debug("AuthorizeServerConn failed certificate validation", "error", err) 974 } 975 return fmt.Errorf("a TLS certificate with a CommonName of %v is required for this operation", expected) 976} 977 978// ParseCiphers parse ciphersuites from the comma-separated string into 979// recognized slice 980func ParseCiphers(cipherStr string) ([]uint16, error) { 981 suites := []uint16{} 982 983 cipherStr = strings.TrimSpace(cipherStr) 984 if cipherStr == "" { 985 return []uint16{}, nil 986 } 987 ciphers := strings.Split(cipherStr, ",") 988 989 // Note: this needs to be kept up to date with the cipherMap in CipherString 990 cipherMap := map[string]uint16{ 991 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 992 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 993 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 994 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 995 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 996 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 997 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 998 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 999 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 1000 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 1001 } 1002 for _, cipher := range ciphers { 1003 if v, ok := cipherMap[cipher]; ok { 1004 suites = append(suites, v) 1005 } else { 1006 return suites, fmt.Errorf("unsupported cipher %q", cipher) 1007 } 1008 } 1009 1010 return suites, nil 1011} 1012 1013// CipherString performs the inverse operation of ParseCiphers 1014func CipherString(ciphers []uint16) (string, error) { 1015 // Note: this needs to be kept up to date with the cipherMap in ParseCiphers 1016 cipherMap := map[uint16]string{ 1017 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 1018 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 1019 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 1020 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 1021 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 1022 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 1023 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 1024 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 1025 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 1026 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 1027 } 1028 1029 cipherStrings := make([]string, len(ciphers)) 1030 for i, cipher := range ciphers { 1031 if v, ok := cipherMap[cipher]; ok { 1032 cipherStrings[i] = v 1033 } else { 1034 return "", fmt.Errorf("unsupported cipher %d", cipher) 1035 } 1036 } 1037 1038 return strings.Join(cipherStrings, ","), nil 1039} 1040