vitess.io/vitess@v0.16.2/go/vt/vtgr/db/tls.go (about) 1 /* 2 Copyright 2014 Outbrain Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 /* 18 This file has been copied over from VTOrc package 19 */ 20 21 package db 22 23 import ( 24 "crypto/tls" 25 "fmt" 26 "strings" 27 "time" 28 29 "vitess.io/vitess/go/vt/external/golib/sqlutils" 30 "vitess.io/vitess/go/vt/log" 31 32 "github.com/go-sql-driver/mysql" 33 "github.com/patrickmn/go-cache" 34 "github.com/rcrowley/go-metrics" 35 36 "vitess.io/vitess/go/vt/vtgr/config" 37 "vitess.io/vitess/go/vt/vtgr/ssl" 38 ) 39 40 const Error3159 = "Error 3159:" 41 const Error1045 = "Access denied for user" 42 43 // Track if a TLS has already been configured for topology 44 var topologyTLSConfigured = false 45 46 // Track if a TLS has already been configured for Orchestrator 47 var orchestratorTLSConfigured = false 48 49 var requireTLSCache *cache.Cache = cache.New(time.Duration(config.Config.TLSCacheTTLFactor*config.Config.InstancePollSeconds)*time.Second, time.Second) 50 51 var readInstanceTLSCounter = metrics.NewCounter() 52 var writeInstanceTLSCounter = metrics.NewCounter() 53 var readInstanceTLSCacheCounter = metrics.NewCounter() 54 var writeInstanceTLSCacheCounter = metrics.NewCounter() 55 56 func init() { 57 metrics.Register("instance_tls.read", readInstanceTLSCounter) 58 metrics.Register("instance_tls.write", writeInstanceTLSCounter) 59 metrics.Register("instance_tls.read_cache", readInstanceTLSCacheCounter) 60 metrics.Register("instance_tls.write_cache", writeInstanceTLSCacheCounter) 61 } 62 63 func requiresTLS(host string, port int, uri string) bool { 64 cacheKey := fmt.Sprintf("%s:%d", host, port) 65 66 if value, found := requireTLSCache.Get(cacheKey); found { 67 readInstanceTLSCacheCounter.Inc(1) 68 return value.(bool) 69 } 70 71 required := false 72 db, _, _ := sqlutils.GetDB(uri) 73 if err := db.Ping(); err != nil && (strings.Contains(err.Error(), Error3159) || strings.Contains(err.Error(), Error1045)) { 74 required = true 75 } 76 77 query := ` 78 insert into 79 database_instance_tls ( 80 hostname, port, required 81 ) values ( 82 ?, ?, ? 83 ) 84 on duplicate key update 85 required=values(required) 86 ` 87 if _, err := ExecOrchestrator(query, host, port, required); err != nil { 88 log.Error(err) 89 } 90 writeInstanceTLSCounter.Inc(1) 91 92 requireTLSCache.Set(cacheKey, required, cache.DefaultExpiration) 93 writeInstanceTLSCacheCounter.Inc(1) 94 95 return required 96 } 97 98 // Create a TLS configuration from the config supplied CA, Certificate, and Private key. 99 // Register the TLS config with the mysql drivers as the "topology" config 100 // Modify the supplied URI to call the TLS config 101 func SetupMySQLTopologyTLS(uri string) (string, error) { 102 if !topologyTLSConfigured { 103 tlsConfig, err := ssl.NewTLSConfig(config.Config.MySQLTopologySSLCAFile, !config.Config.MySQLTopologySSLSkipVerify) 104 // Drop to TLS 1.0 for talking to MySQL 105 tlsConfig.MinVersion = tls.VersionTLS10 106 if err != nil { 107 log.Errorf("Can't create TLS configuration for Topology connection %s: %s", uri, err) 108 return "", err 109 } 110 tlsConfig.InsecureSkipVerify = config.Config.MySQLTopologySSLSkipVerify 111 112 if (config.Config.MySQLTopologyUseMutualTLS && !config.Config.MySQLTopologySSLSkipVerify) && 113 config.Config.MySQLTopologySSLCertFile != "" && 114 config.Config.MySQLTopologySSLPrivateKeyFile != "" { 115 if err = ssl.AppendKeyPair(tlsConfig, config.Config.MySQLTopologySSLCertFile, config.Config.MySQLTopologySSLPrivateKeyFile); err != nil { 116 log.Errorf("Can't setup TLS key pairs for %s: %s", uri, err) 117 return "", err 118 } 119 } 120 if err = mysql.RegisterTLSConfig("topology", tlsConfig); err != nil { 121 log.Errorf("Can't register mysql TLS config for topology: %s", err) 122 return "", err 123 } 124 topologyTLSConfigured = true 125 } 126 return fmt.Sprintf("%s&tls=topology", uri), nil 127 } 128 129 // Create a TLS configuration from the config supplied CA, Certificate, and Private key. 130 // Register the TLS config with the mysql drivers as the "orchestrator" config 131 // Modify the supplied URI to call the TLS config 132 func SetupMySQLOrchestratorTLS(uri string) (string, error) { 133 if !orchestratorTLSConfigured { 134 tlsConfig, err := ssl.NewTLSConfig(config.Config.MySQLOrchestratorSSLCAFile, !config.Config.MySQLOrchestratorSSLSkipVerify) 135 // Drop to TLS 1.0 for talking to MySQL 136 tlsConfig.MinVersion = tls.VersionTLS10 137 if err != nil { 138 log.Fatalf("Can't create TLS configuration for Orchestrator connection %s: %s", uri, err) 139 return "", err 140 } 141 tlsConfig.InsecureSkipVerify = config.Config.MySQLOrchestratorSSLSkipVerify 142 if (!config.Config.MySQLOrchestratorSSLSkipVerify) && 143 config.Config.MySQLOrchestratorSSLCertFile != "" && 144 config.Config.MySQLOrchestratorSSLPrivateKeyFile != "" { 145 if err = ssl.AppendKeyPair(tlsConfig, config.Config.MySQLOrchestratorSSLCertFile, config.Config.MySQLOrchestratorSSLPrivateKeyFile); err != nil { 146 log.Fatalf("Can't setup TLS key pairs for %s: %s", uri, err) 147 return "", err 148 } 149 } 150 if err = mysql.RegisterTLSConfig("orchestrator", tlsConfig); err != nil { 151 log.Fatalf("Can't register mysql TLS config for orchestrator: %s", err) 152 return "", err 153 } 154 orchestratorTLSConfigured = true 155 } 156 return fmt.Sprintf("%s&tls=orchestrator", uri), nil 157 }