Skip to content

Commit

Permalink
ctl: clone tls config to avoid reusing connection (#7740) (#7741)
Browse files Browse the repository at this point in the history
close #7739

Signed-off-by: husharp <[email protected]>

Co-authored-by: husharp <[email protected]>
  • Loading branch information
ti-chi-bot and HuSharp authored Jan 22, 2024
1 parent 9271ad9 commit 6dfc9dd
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tools/pd-ctl/pdctl/command/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func InitHTTPSClient(pdAddrs, caPath, certPath, keyPath string) error {
&http.Transport{TLSClientConfig: tlsConfig}, pdControlCallerID),
}

SetNewPDClient(strings.Split(pdAddrs, ","), pd.WithTLSConfig(tlsConfig))
SetNewPDClient(strings.Split(pdAddrs, ","), pd.WithTLSConfig(tlsConfig.Clone()))

return nil
}
Expand Down
55 changes: 55 additions & 0 deletions tools/pd-ctl/tests/cert_opt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash
cert_dir="$2"

function generate_certs() {
if [[ ! -z "$cert_dir" ]]; then
cd "$cert_dir" || exit 255 # Change to the specified directory
fi

if ! [[ "$0" =~ "cert_opt.sh" ]]; then
echo "must be run from 'cert'"
exit 255
fi

if ! which openssl; then
echo "openssl is not installed"
exit 255
fi

# Generate CA private key and self-signed certificate
openssl genpkey -algorithm RSA -out ca-key.pem
openssl req -new -x509 -key ca-key.pem -out ca.pem -days 1 -subj "/CN=ca"
# pd-server
openssl genpkey -algorithm RSA -out pd-server-key.pem
openssl req -new -key pd-server-key.pem -out pd-server.csr -subj "/CN=pd-server"

# Add IP address as a SAN
echo "subjectAltName = IP:127.0.0.1" > extfile.cnf
openssl x509 -req -in pd-server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out pd-server.pem -days 1 -extfile extfile.cnf

# Clean up the temporary extension file
rm extfile.cnf

# client
openssl genpkey -algorithm RSA -out client-key.pem
openssl req -new -key client-key.pem -out client.csr -subj "/CN=client"
openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client.pem -days 1
}

function cleanup_certs() {
if [[ ! -z "$cert_dir" ]]; then
cd "$cert_dir" || exit 255 # Change to the specified directory
fi

rm -f ca.pem ca-key.pem ca.srl
rm -f pd-server.pem pd-server-key.pem pd-server.csr
rm -f client.pem client-key.pem client.csr
}

if [[ "$1" == "generate" ]]; then
generate_certs
elif [[ "$1" == "cleanup" ]]; then
cleanup_certs
else
echo "Usage: $0 [generate|cleanup] <cert_directory>"
fi
99 changes: 99 additions & 0 deletions tools/pd-ctl/tests/store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ package store_test
import (
"context"
"encoding/json"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"time"

Expand All @@ -25,10 +29,13 @@ import (
"github.com/tikv/pd/pkg/core"
"github.com/tikv/pd/pkg/core/storelimit"
"github.com/tikv/pd/pkg/statistics/utils"
"github.com/tikv/pd/pkg/utils/grpcutil"
"github.com/tikv/pd/server/api"
"github.com/tikv/pd/server/config"
pdTests "github.com/tikv/pd/tests"
ctl "github.com/tikv/pd/tools/pd-ctl/pdctl"
"github.com/tikv/pd/tools/pd-ctl/tests"
"go.etcd.io/etcd/pkg/transport"
)

func TestStore(t *testing.T) {
Expand Down Expand Up @@ -544,3 +551,95 @@ func TestTombstoneStore(t *testing.T) {
re.Contains(message, "2")
re.Contains(message, "3")
}

func TestStoreTLS(t *testing.T) {
re := require.New(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
certPath := "../cert"
certScript := "../cert_opt.sh"
// generate certs
if err := os.Mkdir(certPath, 0755); err != nil {
t.Fatal(err)
}
if err := exec.Command(certScript, "generate", certPath).Run(); err != nil {
t.Fatal(err)
}
defer func() {
if err := exec.Command(certScript, "cleanup", certPath).Run(); err != nil {
t.Fatal(err)
}
if err := os.RemoveAll(certPath); err != nil {
t.Fatal(err)
}
}()

tlsInfo := transport.TLSInfo{
KeyFile: filepath.Join(certPath, "pd-server-key.pem"),
CertFile: filepath.Join(certPath, "pd-server.pem"),
TrustedCAFile: filepath.Join(certPath, "ca.pem"),
}
cluster, err := pdTests.NewTestCluster(ctx, 1, func(conf *config.Config, serverName string) {
conf.Security.TLSConfig = grpcutil.TLSConfig{
KeyPath: tlsInfo.KeyFile,
CertPath: tlsInfo.CertFile,
CAPath: tlsInfo.TrustedCAFile,
}
conf.AdvertiseClientUrls = strings.ReplaceAll(conf.AdvertiseClientUrls, "http", "https")
conf.ClientUrls = strings.ReplaceAll(conf.ClientUrls, "http", "https")
conf.AdvertisePeerUrls = strings.ReplaceAll(conf.AdvertisePeerUrls, "http", "https")
conf.PeerUrls = strings.ReplaceAll(conf.PeerUrls, "http", "https")
conf.InitialCluster = strings.ReplaceAll(conf.InitialCluster, "http", "https")
})
re.NoError(err)
err = cluster.RunInitialServers()
re.NoError(err)
cluster.WaitLeader()
cmd := ctl.GetRootCmd()

stores := []*api.StoreInfo{
{
Store: &api.MetaStore{
Store: &metapb.Store{
Id: 1,
State: metapb.StoreState_Up,
NodeState: metapb.NodeState_Serving,
LastHeartbeat: time.Now().UnixNano(),
},
StateName: metapb.StoreState_Up.String(),
},
},
{
Store: &api.MetaStore{
Store: &metapb.Store{
Id: 2,
State: metapb.StoreState_Up,
NodeState: metapb.NodeState_Serving,
LastHeartbeat: time.Now().UnixNano(),
},
StateName: metapb.StoreState_Up.String(),
},
},
}

leaderServer := cluster.GetLeaderServer()
re.NoError(leaderServer.BootstrapCluster())

for _, store := range stores {
pdTests.MustPutStore(re, cluster, store.Store.Store)
}
defer cluster.Destroy()

pdAddr := cluster.GetConfig().GetClientURL()
pdAddr = strings.ReplaceAll(pdAddr, "http", "https")
// store command
args := []string{"-u", pdAddr, "store",
"--cacert=../cert/ca.pem",
"--cert=../cert/client.pem",
"--key=../cert/client-key.pem"}
output, err := tests.ExecuteCommand(cmd, args...)
re.NoError(err)
storesInfo := new(api.StoresInfo)
re.NoError(json.Unmarshal(output, &storesInfo))
tests.CheckStoresInfo(re, storesInfo.Stores, stores)
}

0 comments on commit 6dfc9dd

Please sign in to comment.