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 manualCAPems []string 162 connectCAPems []string 163 cert *tls.Certificate 164 verifyServerHostname bool 165} 166 167func (a *autoTLS) caPems() []string { 168 return append(a.manualCAPems, a.connectCAPems...) 169} 170 171type manual struct { 172 caPems []string 173 cert *tls.Certificate 174} 175 176// Configurator holds a Config and is responsible for generating all the 177// *tls.Config necessary for Consul. Except the one in the api package. 178type Configurator struct { 179 sync.RWMutex 180 base *Config 181 autoTLS *autoTLS 182 manual *manual 183 peerDatacenterUseTLS map[string]bool 184 185 caPool *x509.CertPool 186 logger hclog.Logger 187 version int 188} 189 190// NewConfigurator creates a new Configurator and sets the provided 191// configuration. 192func NewConfigurator(config Config, logger hclog.Logger) (*Configurator, error) { 193 if logger == nil { 194 logger = hclog.New(&hclog.LoggerOptions{ 195 Level: hclog.Debug, 196 }) 197 } 198 199 c := &Configurator{ 200 logger: logger.Named(logging.TLSUtil), 201 manual: &manual{}, 202 autoTLS: &autoTLS{}, 203 peerDatacenterUseTLS: map[string]bool{}, 204 } 205 err := c.Update(config) 206 if err != nil { 207 return nil, err 208 } 209 return c, nil 210} 211 212// CAPems returns the currently loaded CAs in PEM format. 213func (c *Configurator) CAPems() []string { 214 c.RLock() 215 defer c.RUnlock() 216 return append(c.manual.caPems, c.autoTLS.caPems()...) 217} 218 219// ManualCAPems returns the currently loaded CAs in PEM format. 220func (c *Configurator) ManualCAPems() []string { 221 c.RLock() 222 defer c.RUnlock() 223 return c.manual.caPems 224} 225 226// Update updates the internal configuration which is used to generate 227// *tls.Config. 228// This function acquires a write lock because it writes the new config. 229func (c *Configurator) Update(config Config) error { 230 c.Lock() 231 // order of defers matters because log acquires a RLock() 232 defer c.log("Update") 233 defer c.Unlock() 234 235 cert, err := loadKeyPair(config.CertFile, config.KeyFile) 236 if err != nil { 237 return err 238 } 239 pems, err := LoadCAs(config.CAFile, config.CAPath) 240 if err != nil { 241 return err 242 } 243 pool, err := pool(append(pems, c.autoTLS.caPems()...)) 244 if err != nil { 245 return err 246 } 247 if err = c.check(config, pool, cert); err != nil { 248 return err 249 } 250 c.base = &config 251 c.manual.cert = cert 252 c.manual.caPems = pems 253 c.caPool = pool 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 := pool(append(c.manual.caPems, append(c.autoTLS.manualCAPems, 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 := pool(append(c.manual.caPems, append(manualCAPems, connectCAPems...)...)) 314 if err != nil { 315 return err 316 } 317 c.autoTLS.manualCAPems = 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 348func pool(pems []string) (*x509.CertPool, error) { 349 pool := x509.NewCertPool() 350 for _, pem := range pems { 351 if !pool.AppendCertsFromPEM([]byte(pem)) { 352 return nil, fmt.Errorf("Couldn't parse PEM %s", pem) 353 } 354 } 355 if len(pool.Subjects()) == 0 { 356 return nil, nil 357 } 358 return pool, nil 359} 360 361func (c *Configurator) check(config Config, pool *x509.CertPool, cert *tls.Certificate) error { 362 // Check if a minimum TLS version was set 363 if config.TLSMinVersion != "" { 364 if _, ok := TLSLookup[config.TLSMinVersion]; !ok { 365 return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", config.TLSMinVersion, TLSVersions) 366 } 367 } 368 369 // Ensure we have a CA if VerifyOutgoing is set 370 if config.VerifyOutgoing && pool == nil { 371 return fmt.Errorf("VerifyOutgoing set, and no CA certificate provided!") 372 } 373 374 // Ensure we have a CA and cert if VerifyIncoming is set 375 if config.anyVerifyIncoming() { 376 if pool == nil { 377 // both auto-config and auto-encrypt require verifying the connection from the client to the server for secure 378 // operation. In order to be able to verify the servers certificate we must have some CA certs already provided. 379 // Therefore, even though both of those features can push down extra CA certificates which could be used to 380 // verify incoming connections, we still must consider it an error if none are provided in the initial configuration 381 // as those features cannot be successfully enabled without providing CA certificates to use those features. 382 return fmt.Errorf("VerifyIncoming set but no CA certificates were provided") 383 } 384 385 // We will use the auto_encrypt/auto_config cert for TLS in the incoming APIs when available. Therefore the check 386 // here will ensure that either we enabled one of those two features or a certificate and key were provided manually 387 if cert == nil && !config.AutoTLS { 388 return fmt.Errorf("VerifyIncoming requires either a Cert and Key pair in the configuration file, or auto_encrypt/auto_config be enabled") 389 } 390 } 391 return nil 392} 393 394func (c Config) anyVerifyIncoming() bool { 395 return c.baseVerifyIncoming() || c.VerifyIncomingRPC || c.VerifyIncomingHTTPS 396} 397 398func (c Config) verifyIncomingRPC() bool { 399 return c.baseVerifyIncoming() || c.VerifyIncomingRPC 400} 401 402func (c Config) verifyIncomingHTTPS() bool { 403 return c.baseVerifyIncoming() || c.VerifyIncomingHTTPS 404} 405 406func (c *Config) baseVerifyIncoming() bool { 407 return c.VerifyIncoming 408} 409 410func loadKeyPair(certFile, keyFile string) (*tls.Certificate, error) { 411 if certFile == "" || keyFile == "" { 412 return nil, nil 413 } 414 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 415 if err != nil { 416 return nil, fmt.Errorf("Failed to load cert/key pair: %v", err) 417 } 418 return &cert, nil 419} 420 421func LoadCAs(caFile, caPath string) ([]string, error) { 422 if caFile == "" && caPath == "" { 423 return nil, nil 424 } 425 426 pems := []string{} 427 428 readFn := func(path string) error { 429 pem, err := ioutil.ReadFile(path) 430 if err != nil { 431 return fmt.Errorf("Error loading from %s: %s", path, err) 432 } 433 pems = append(pems, string(pem)) 434 return nil 435 } 436 437 walkFn := func(path string, info os.FileInfo, err error) error { 438 if err != nil { 439 return err 440 } 441 442 if !info.IsDir() { 443 if err := readFn(path); err != nil { 444 return err 445 } 446 } 447 return nil 448 } 449 450 if caFile != "" { 451 err := readFn(caFile) 452 if err != nil { 453 return pems, err 454 } 455 } else if caPath != "" { 456 err := filepath.Walk(caPath, walkFn) 457 if err != nil { 458 return pems, err 459 } 460 if len(pems) == 0 { 461 return pems, fmt.Errorf("Error loading from CAPath: no CAs found") 462 } 463 } 464 return pems, nil 465} 466 467// commonTLSConfig generates a *tls.Config from the base configuration the 468// Configurator has. It accepts an additional flag in case a config is needed 469// for incoming TLS connections. 470// This function acquires a read lock because it reads from the config. 471func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config { 472 // this needs to be outside of RLock because it acquires an RLock itself 473 verifyServerHostname := c.VerifyServerHostname() 474 475 c.RLock() 476 defer c.RUnlock() 477 tlsConfig := &tls.Config{ 478 InsecureSkipVerify: !verifyServerHostname, 479 } 480 481 // Set the cipher suites 482 if len(c.base.CipherSuites) != 0 { 483 tlsConfig.CipherSuites = c.base.CipherSuites 484 } 485 486 tlsConfig.PreferServerCipherSuites = c.base.PreferServerCipherSuites 487 488 // GetCertificate is used when acting as a server and responding to 489 // client requests. Default to the manually configured cert, but allow 490 // autoEncrypt cert too so that a client can encrypt incoming 491 // connections without having a manual cert configured. 492 tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 493 return c.Cert(), nil 494 } 495 496 // GetClientCertificate is used when acting as a client and responding 497 // to a server requesting a certificate. Return the autoEncrypt certificate 498 // if possible, otherwise default to the manually provisioned one. 499 tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { 500 cert := c.autoTLS.cert 501 if cert == nil { 502 cert = c.manual.cert 503 } 504 505 if cert == nil { 506 // the return value MUST not be nil but an empty certificate will be 507 // treated the same as having no client certificate 508 cert = &tls.Certificate{} 509 } 510 511 return cert, nil 512 } 513 514 tlsConfig.ClientCAs = c.caPool 515 tlsConfig.RootCAs = c.caPool 516 517 // This is possible because TLSLookup also contains "" with golang's 518 // default (tls10). And because the initial check makes sure the 519 // version correctly matches. 520 tlsConfig.MinVersion = TLSLookup[c.base.TLSMinVersion] 521 522 // Set ClientAuth if necessary 523 if verifyIncoming { 524 tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert 525 } 526 527 return tlsConfig 528} 529 530// This function acquires a read lock because it reads from the config. 531func (c *Configurator) Cert() *tls.Certificate { 532 c.RLock() 533 defer c.RUnlock() 534 cert := c.manual.cert 535 if cert == nil { 536 cert = c.autoTLS.cert 537 } 538 return cert 539} 540 541// This function acquires a read lock because it reads from the config. 542func (c *Configurator) VerifyIncomingRPC() bool { 543 c.RLock() 544 defer c.RUnlock() 545 return c.base.verifyIncomingRPC() 546} 547 548// This function acquires a read lock because it reads from the config. 549func (c *Configurator) outgoingRPCTLSDisabled() bool { 550 c.RLock() 551 defer c.RUnlock() 552 553 // if AutoEncrypt enabled, always use TLS 554 if c.base.AutoTLS { 555 return false 556 } 557 558 // if CAs are provided or VerifyOutgoing is set, use TLS 559 if c.base.VerifyOutgoing { 560 return false 561 } 562 563 return true 564} 565 566func (c *Configurator) MutualTLSCapable() bool { 567 return c.mutualTLSCapable() 568} 569 570// This function acquires a read lock because it reads from the config. 571func (c *Configurator) mutualTLSCapable() bool { 572 c.RLock() 573 defer c.RUnlock() 574 return c.caPool != nil && (c.autoTLS.cert != nil || c.manual.cert != nil) 575} 576 577// This function acquires a read lock because it reads from the config. 578func (c *Configurator) verifyOutgoing() bool { 579 c.RLock() 580 defer c.RUnlock() 581 582 // If AutoEncryptTLS is enabled and there is a CA, then verify 583 // outgoing. 584 if c.base.AutoTLS && c.caPool != nil { 585 return true 586 } 587 588 return c.base.VerifyOutgoing 589} 590 591func (c *Configurator) ServerSNI(dc, nodeName string) string { 592 // Strip the trailing '.' from the domain if any 593 domain := strings.TrimSuffix(c.domain(), ".") 594 595 if nodeName == "" || nodeName == "*" { 596 return "server." + dc + "." + domain 597 } 598 599 return nodeName + ".server." + dc + "." + domain 600} 601 602// This function acquires a read lock because it reads from the config. 603func (c *Configurator) domain() string { 604 c.RLock() 605 defer c.RUnlock() 606 return c.base.Domain 607} 608 609// This function acquires a read lock because it reads from the config. 610func (c *Configurator) verifyIncomingRPC() bool { 611 c.RLock() 612 defer c.RUnlock() 613 return c.base.verifyIncomingRPC() 614} 615 616// This function acquires a read lock because it reads from the config. 617func (c *Configurator) verifyIncomingHTTPS() bool { 618 c.RLock() 619 defer c.RUnlock() 620 return c.base.verifyIncomingHTTPS() 621} 622 623// This function acquires a read lock because it reads from the config. 624func (c *Configurator) enableAgentTLSForChecks() bool { 625 c.RLock() 626 defer c.RUnlock() 627 return c.base.EnableAgentTLSForChecks 628} 629 630// This function acquires a read lock because it reads from the config. 631func (c *Configurator) serverNameOrNodeName() string { 632 c.RLock() 633 defer c.RUnlock() 634 if c.base.ServerName != "" { 635 return c.base.ServerName 636 } 637 return c.base.NodeName 638} 639 640// This function acquires a read lock because it reads from the config. 641func (c *Configurator) VerifyServerHostname() bool { 642 c.RLock() 643 defer c.RUnlock() 644 return c.base.VerifyServerHostname || c.autoTLS.verifyServerHostname 645} 646 647// IncomingGRPCConfig generates a *tls.Config for incoming GRPC connections. 648func (c *Configurator) IncomingGRPCConfig() *tls.Config { 649 c.log("IncomingGRPCConfig") 650 651 // false has the effect that this config doesn't require a client cert 652 // verification. This is because there is no verify_incoming_grpc 653 // configuration option. And using verify_incoming would be backwards 654 // incompatible, because even if it was set before, it didn't have an 655 // effect on the grpc server. 656 config := c.commonTLSConfig(false) 657 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 658 return c.IncomingGRPCConfig(), nil 659 } 660 return config 661} 662 663// IncomingRPCConfig generates a *tls.Config for incoming RPC connections. 664func (c *Configurator) IncomingRPCConfig() *tls.Config { 665 c.log("IncomingRPCConfig") 666 config := c.commonTLSConfig(c.verifyIncomingRPC()) 667 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 668 return c.IncomingRPCConfig(), nil 669 } 670 return config 671} 672 673// IncomingALPNRPCConfig generates a *tls.Config for incoming RPC connections 674// directly using TLS with ALPN instead of the older byte-prefixed protocol. 675func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config { 676 c.log("IncomingALPNRPCConfig") 677 // Since the ALPN-RPC variation is indirectly exposed to the internet via 678 // mesh gateways we force mTLS and full server name verification. 679 config := c.commonTLSConfig(true) 680 config.InsecureSkipVerify = false 681 682 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 683 return c.IncomingALPNRPCConfig(alpnProtos), nil 684 } 685 config.NextProtos = alpnProtos 686 return config 687} 688 689// IncomingInsecureRPCConfig means that it doesn't verify incoming even thought 690// it might have been configured. This is only supposed to be used by the 691// servers for the insecure RPC server. At the time of writing only the 692// AutoEncrypt.Sign call is supported on that server. And it might be the only 693// usecase ever. 694func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config { 695 c.log("IncomingInsecureRPCConfig") 696 config := c.commonTLSConfig(false) 697 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 698 return c.IncomingInsecureRPCConfig(), nil 699 } 700 return config 701} 702 703// IncomingHTTPSConfig generates a *tls.Config for incoming HTTPS connections. 704func (c *Configurator) IncomingHTTPSConfig() *tls.Config { 705 c.log("IncomingHTTPSConfig") 706 config := c.commonTLSConfig(c.verifyIncomingHTTPS()) 707 config.NextProtos = []string{"h2", "http/1.1"} 708 config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { 709 return c.IncomingHTTPSConfig(), nil 710 } 711 return config 712} 713 714// OutgoingTLSConfigForCheck generates a *tls.Config for outgoing TLS connections 715// for checks. This function is separated because there is an extra flag to 716// consider for checks. EnableAgentTLSForChecks and InsecureSkipVerify has to 717// be checked for checks. 718func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName string) *tls.Config { 719 c.log("OutgoingTLSConfigForCheck") 720 721 if !c.enableAgentTLSForChecks() { 722 return &tls.Config{ 723 InsecureSkipVerify: skipVerify, 724 ServerName: serverName, 725 } 726 } 727 728 if serverName == "" { 729 serverName = c.serverNameOrNodeName() 730 } 731 config := c.commonTLSConfig(false) 732 config.InsecureSkipVerify = skipVerify 733 config.ServerName = serverName 734 735 return config 736} 737 738// OutgoingRPCConfig generates a *tls.Config for outgoing RPC connections. If 739// there is a CA or VerifyOutgoing is set, a *tls.Config will be provided, 740// otherwise we assume that no TLS should be used. 741func (c *Configurator) OutgoingRPCConfig() *tls.Config { 742 c.log("OutgoingRPCConfig") 743 if c.outgoingRPCTLSDisabled() { 744 return nil 745 } 746 return c.commonTLSConfig(false) 747} 748 749// OutgoingALPNRPCConfig generates a *tls.Config for outgoing RPC connections 750// directly using TLS with ALPN instead of the older byte-prefixed protocol. 751// If there is a CA or VerifyOutgoing is set, a *tls.Config will be provided, 752// otherwise we assume that no TLS should be used which completely disables the 753// ALPN variation. 754func (c *Configurator) OutgoingALPNRPCConfig() *tls.Config { 755 c.log("OutgoingALPNRPCConfig") 756 if !c.mutualTLSCapable() { 757 return nil // ultimately this will hard-fail as TLS is required 758 } 759 760 // Since the ALPN-RPC variation is indirectly exposed to the internet via 761 // mesh gateways we force mTLS and full server name verification. 762 config := c.commonTLSConfig(true) 763 config.InsecureSkipVerify = false 764 return config 765} 766 767// OutgoingRPCWrapper wraps the result of OutgoingRPCConfig in a DCWrapper. It 768// decides if verify server hostname should be used. 769func (c *Configurator) OutgoingRPCWrapper() DCWrapper { 770 c.log("OutgoingRPCWrapper") 771 772 // Generate the wrapper based on dc 773 return func(dc string, conn net.Conn) (net.Conn, error) { 774 if c.UseTLS(dc) { 775 return c.wrapTLSClient(dc, conn) 776 } 777 return conn, nil 778 } 779} 780 781func (c *Configurator) UseTLS(dc string) bool { 782 return !c.outgoingRPCTLSDisabled() && c.getAreaForPeerDatacenterUseTLS(dc) 783} 784 785// OutgoingALPNRPCWrapper wraps the result of OutgoingALPNRPCConfig in an 786// ALPNWrapper. It configures all of the negotiation plumbing. 787func (c *Configurator) OutgoingALPNRPCWrapper() ALPNWrapper { 788 c.log("OutgoingALPNRPCWrapper") 789 if !c.mutualTLSCapable() { 790 return nil 791 } 792 793 return func(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) { 794 return c.wrapALPNTLSClient(dc, nodeName, alpnProto, conn) 795 } 796} 797 798// AutoEncryptCertNotAfter returns NotAfter from the auto_encrypt cert. In case 799// there is no cert, it will return a time in the past. 800func (c *Configurator) AutoEncryptCertNotAfter() time.Time { 801 c.RLock() 802 defer c.RUnlock() 803 tlsCert := c.autoTLS.cert 804 if tlsCert == nil || tlsCert.Certificate == nil { 805 return time.Now().AddDate(0, 0, -1) 806 } 807 cert, err := x509.ParseCertificate(tlsCert.Certificate[0]) 808 if err != nil { 809 return time.Now().AddDate(0, 0, -1) 810 } 811 return cert.NotAfter 812} 813 814// AutoEncryptCertExpired returns if the auto_encrypt cert is expired. 815func (c *Configurator) AutoEncryptCertExpired() bool { 816 return c.AutoEncryptCertNotAfter().Before(time.Now()) 817} 818 819// This function acquires a read lock because it reads from the config. 820func (c *Configurator) log(name string) { 821 if c.logger != nil { 822 c.RLock() 823 defer c.RUnlock() 824 c.logger.Trace(name, "version", c.version) 825 } 826} 827 828// Wrap a net.Conn into a client tls connection, performing any 829// additional verification as needed. 830// 831// As of go 1.3, crypto/tls only supports either doing no certificate 832// verification, or doing full verification including of the peer's 833// DNS name. For consul, we want to validate that the certificate is 834// signed by a known CA, but because consul doesn't use DNS names for 835// node names, we don't verify the certificate DNS names. Since go 1.3 836// no longer supports this mode of operation, we have to do it 837// manually. 838func (c *Configurator) wrapTLSClient(dc string, conn net.Conn) (net.Conn, error) { 839 config := c.OutgoingRPCConfig() 840 verifyServerHostname := c.VerifyServerHostname() 841 verifyOutgoing := c.verifyOutgoing() 842 domain := c.domain() 843 844 if verifyServerHostname { 845 // Strip the trailing '.' from the domain if any 846 domain = strings.TrimSuffix(domain, ".") 847 config.ServerName = "server." + dc + "." + domain 848 } 849 tlsConn := tls.Client(conn, config) 850 851 // If crypto/tls is doing verification, there's no need to do 852 // our own. 853 if !config.InsecureSkipVerify { 854 return tlsConn, nil 855 } 856 857 // If verification is not turned on, don't do it. 858 if !verifyOutgoing { 859 return tlsConn, nil 860 } 861 862 err := tlsConn.Handshake() 863 if err != nil { 864 tlsConn.Close() 865 return nil, err 866 } 867 868 // The following is lightly-modified from the doFullHandshake 869 // method in crypto/tls's handshake_client.go. 870 opts := x509.VerifyOptions{ 871 Roots: config.RootCAs, 872 CurrentTime: time.Now(), 873 DNSName: "", 874 Intermediates: x509.NewCertPool(), 875 } 876 877 certs := tlsConn.ConnectionState().PeerCertificates 878 for i, cert := range certs { 879 if i == 0 { 880 continue 881 } 882 opts.Intermediates.AddCert(cert) 883 } 884 885 _, err = certs[0].Verify(opts) 886 if err != nil { 887 tlsConn.Close() 888 return nil, err 889 } 890 891 return tlsConn, err 892} 893 894// Wrap a net.Conn into a client tls connection suitable for secure ALPN-RPC, 895// performing any additional verification as needed. 896func (c *Configurator) wrapALPNTLSClient(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) { 897 if dc == "" { 898 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target datacenter") 899 } else if nodeName == "" { 900 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target node") 901 } else if alpnProto == "" { 902 return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target alpn protocol") 903 } 904 905 config := c.OutgoingALPNRPCConfig() 906 if config == nil { 907 return nil, fmt.Errorf("cannot dial via a mesh gateway when outgoing TLS is disabled") 908 } 909 910 // Since the ALPN-RPC variation is indirectly exposed to the internet via 911 // mesh gateways we force mTLS and full hostname validation (forcing 912 // verify_server_hostname and verify_outgoing to be effectively true). 913 914 config.ServerName = c.ServerSNI(dc, nodeName) 915 config.NextProtos = []string{alpnProto} 916 917 tlsConn := tls.Client(conn, config) 918 919 // NOTE: For this handshake to succeed the server must have key material 920 // for either "<nodename>.server.<datacenter>.<domain>" or 921 // "*.server.<datacenter>.<domain>" in addition to the 922 // "server.<datacenter>.<domain>" required for standard TLS'd RPC. 923 if err := tlsConn.Handshake(); err != nil { 924 tlsConn.Close() 925 return nil, err 926 } 927 928 return tlsConn, nil 929} 930 931// ParseCiphers parse ciphersuites from the comma-separated string into 932// recognized slice 933func ParseCiphers(cipherStr string) ([]uint16, error) { 934 suites := []uint16{} 935 936 cipherStr = strings.TrimSpace(cipherStr) 937 if cipherStr == "" { 938 return []uint16{}, nil 939 } 940 ciphers := strings.Split(cipherStr, ",") 941 942 // Note: this needs to be kept up to date with the cipherMap in CipherString 943 cipherMap := map[string]uint16{ 944 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 945 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 946 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 947 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 948 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 949 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 950 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 951 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 952 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 953 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 954 } 955 for _, cipher := range ciphers { 956 if v, ok := cipherMap[cipher]; ok { 957 suites = append(suites, v) 958 } else { 959 return suites, fmt.Errorf("unsupported cipher %q", cipher) 960 } 961 } 962 963 return suites, nil 964} 965 966// CipherString performs the inverse operation of ParseCiphers 967func CipherString(ciphers []uint16) (string, error) { 968 // Note: this needs to be kept up to date with the cipherMap in ParseCiphers 969 cipherMap := map[uint16]string{ 970 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 971 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 972 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 973 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 974 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 975 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 976 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 977 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 978 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 979 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 980 } 981 982 cipherStrings := make([]string, len(ciphers)) 983 for i, cipher := range ciphers { 984 if v, ok := cipherMap[cipher]; ok { 985 cipherStrings[i] = v 986 } else { 987 return "", fmt.Errorf("unsupported cipher %d", cipher) 988 } 989 } 990 991 return strings.Join(cipherStrings, ","), nil 992} 993