vitess.io/vitess@v0.16.2/go/test/endtoend/encryption/encryptedreplication/encrypted_replication_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     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  package encryptedreplication
    18  
    19  import (
    20  	"flag"
    21  	"os"
    22  	"os/exec"
    23  	"path"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/require"
    27  
    28  	"vitess.io/vitess/go/test/endtoend/cluster"
    29  	"vitess.io/vitess/go/test/endtoend/encryption"
    30  	"vitess.io/vitess/go/vt/log"
    31  )
    32  
    33  var (
    34  	clusterInstance *cluster.LocalProcessCluster
    35  	keyspace        = "test_keyspace"
    36  	hostname        = "localhost"
    37  	shardName       = "0"
    38  	cell            = "zone1"
    39  	certDirectory   string
    40  )
    41  
    42  // This test makes sure that we can use SSL replication with Vitess
    43  func TestSecure(t *testing.T) {
    44  	defer cluster.PanicHandler(t)
    45  	testReplicationBase(t, true)
    46  	testReplicationBase(t, false)
    47  }
    48  
    49  // This test makes sure that we can use SSL replication with Vitess.
    50  func testReplicationBase(t *testing.T, isClientCertPassed bool) {
    51  	flag.Parse()
    52  
    53  	// initialize cluster
    54  	_, err := initializeCluster(t)
    55  	require.Nil(t, err, "setup failed")
    56  
    57  	defer teardownCluster()
    58  
    59  	primaryTablet := *clusterInstance.Keyspaces[0].Shards[0].Vttablets[0]
    60  	replicaTablet := *clusterInstance.Keyspaces[0].Shards[0].Vttablets[1]
    61  
    62  	if isClientCertPassed {
    63  		replicaTablet.VttabletProcess.ExtraArgs = append(replicaTablet.VttabletProcess.ExtraArgs, "--db_flags", "2048",
    64  			"--db_ssl_ca", path.Join(certDirectory, "ca-cert.pem"),
    65  			"--db_ssl_cert", path.Join(certDirectory, "client-cert.pem"),
    66  			"--db_ssl_key", path.Join(certDirectory, "client-key.pem"),
    67  		)
    68  	}
    69  
    70  	// start the tablets
    71  	for _, tablet := range []cluster.Vttablet{primaryTablet, replicaTablet} {
    72  		_ = tablet.VttabletProcess.Setup()
    73  	}
    74  
    75  	// Reparent using SSL (this will also check replication works)
    76  	err = clusterInstance.VtctlclientProcess.InitializeShard(keyspace, shardName, clusterInstance.Cell, primaryTablet.TabletUID)
    77  	if isClientCertPassed {
    78  		require.NoError(t, err)
    79  	} else {
    80  		require.Error(t, err)
    81  	}
    82  
    83  	err = clusterInstance.StartVTOrc(keyspace)
    84  	require.NoError(t, err)
    85  }
    86  
    87  func initializeCluster(t *testing.T) (int, error) {
    88  	var mysqlProcesses []*exec.Cmd
    89  	clusterInstance = cluster.NewCluster(cell, hostname)
    90  
    91  	// Start topo server
    92  	if err := clusterInstance.StartTopo(); err != nil {
    93  		return 1, err
    94  	}
    95  
    96  	// create certs directory
    97  	log.Info("Creating certificates")
    98  	certDirectory = path.Join(clusterInstance.TmpDirectory, "certs")
    99  	_ = encryption.CreateDirectory(certDirectory, 0700)
   100  
   101  	err := encryption.ExecuteVttlstestCommand("CreateCA", "--root", certDirectory)
   102  	require.NoError(t, err)
   103  
   104  	err = encryption.ExecuteVttlstestCommand("CreateSignedCert", "--root", certDirectory, "--common-name", "Mysql Server", "--serial", "01", "server")
   105  	require.NoError(t, err)
   106  
   107  	err = encryption.ExecuteVttlstestCommand("CreateSignedCert", "--root", certDirectory, "--common-name", "Mysql Client", "--serial", "02", "client")
   108  	require.NoError(t, err)
   109  
   110  	extraMyCnf := path.Join(certDirectory, "secure.cnf")
   111  	f, err := os.Create(extraMyCnf)
   112  	require.NoError(t, err)
   113  
   114  	_, err = f.WriteString("require_secure_transport=" + "true\n")
   115  	require.NoError(t, err)
   116  	_, err = f.WriteString("ssl-ca=" + certDirectory + "/ca-cert.pem\n")
   117  	require.NoError(t, err)
   118  	_, err = f.WriteString("ssl-cert=" + certDirectory + "/server-cert.pem\n")
   119  	require.NoError(t, err)
   120  	_, err = f.WriteString("ssl-key=" + certDirectory + "/server-key.pem\n")
   121  	require.NoError(t, err)
   122  
   123  	err = f.Close()
   124  	require.NoError(t, err)
   125  
   126  	err = os.Setenv("EXTRA_MY_CNF", extraMyCnf)
   127  
   128  	require.NoError(t, err)
   129  
   130  	for _, keyspaceStr := range []string{keyspace} {
   131  		KeyspacePtr := &cluster.Keyspace{Name: keyspaceStr}
   132  		keyspace := *KeyspacePtr
   133  		if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name); err != nil {
   134  			return 1, err
   135  		}
   136  		shard := &cluster.Shard{
   137  			Name: shardName,
   138  		}
   139  		for i := 0; i < 2; i++ {
   140  			// instantiate vttablet object with reserved ports
   141  			tabletUID := clusterInstance.GetAndReserveTabletUID()
   142  			tablet := clusterInstance.NewVttabletInstance("replica", tabletUID, cell)
   143  
   144  			// Start Mysqlctl process
   145  			tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory)
   146  			proc, err := tablet.MysqlctlProcess.StartProcess()
   147  			if err != nil {
   148  				return 1, err
   149  			}
   150  			mysqlProcesses = append(mysqlProcesses, proc)
   151  			// start vttablet process
   152  			tablet.VttabletProcess = cluster.VttabletProcessInstance(
   153  				tablet.HTTPPort,
   154  				tablet.GrpcPort,
   155  				tablet.TabletUID,
   156  				clusterInstance.Cell,
   157  				shardName,
   158  				keyspace.Name,
   159  				clusterInstance.VtctldProcess.Port,
   160  				tablet.Type,
   161  				clusterInstance.TopoProcess.Port,
   162  				clusterInstance.Hostname,
   163  				clusterInstance.TmpDirectory,
   164  				clusterInstance.VtTabletExtraArgs,
   165  				clusterInstance.DefaultCharset)
   166  			tablet.Alias = tablet.VttabletProcess.TabletPath
   167  			shard.Vttablets = append(shard.Vttablets, tablet)
   168  		}
   169  		keyspace.Shards = append(keyspace.Shards, *shard)
   170  		clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace)
   171  	}
   172  	for _, proc := range mysqlProcesses {
   173  		err := proc.Wait()
   174  		if err != nil {
   175  			return 1, err
   176  		}
   177  	}
   178  	return 0, nil
   179  }
   180  
   181  func teardownCluster() {
   182  	clusterInstance.Teardown()
   183  }