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  }