Skip to content

Commit

Permalink
cluster: support init root password (#1700)
Browse files Browse the repository at this point in the history
  • Loading branch information
AstroProfundis authored Dec 29, 2021
1 parent 26e5521 commit 13b33c0
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 29 deletions.
7 changes: 3 additions & 4 deletions components/bench/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ tidy:
clean:
@# Target: run the build cleanup steps
@rm -rf bin
@rm -rf cover
@rm -rf tests/*/{bin/*.test,logs,cover/*.out}
@rm -rf tests/*/{bin/*.test,logs}

test: failpoint-enable run-tests failpoint-disable
@# Target: run tests with failpoint enabled
Expand All @@ -91,8 +90,8 @@ run-tests: unit-test
# Run tests
unit-test:
@# Target: run the code coverage test phase
mkdir -p cover
TIUP_HOME=$(shell pwd)/../../tests/tiup $(GOTEST) ./... -covermode=count -coverprofile ../../cover/cov.unit-test.out
mkdir -p ../../cover
TIUP_HOME=$(shell pwd)/../../tests/tiup $(GOTEST) ./... -covermode=count -coverprofile ../../cover/cov.unit-test.bench.out

race: failpoint-enable
@# Target: run race check with failpoint enabled
Expand Down
7 changes: 3 additions & 4 deletions components/client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ tidy:
clean:
@# Target: run the build cleanup steps
@rm -rf bin
@rm -rf cover
@rm -rf tests/*/{bin/*.test,logs,cover/*.out}
@rm -rf tests/*/{bin/*.test,logs}

test: failpoint-enable run-tests failpoint-disable
@# Target: run tests with failpoint enabled
Expand All @@ -91,8 +90,8 @@ run-tests: unit-test
# Run tests
unit-test:
@# Target: run the code coverage test phase
mkdir -p cover
TIUP_HOME=$(shell pwd)/../../tests/tiup $(GOTEST) ./... -covermode=count -coverprofile ../../cover/cov.unit-test.out
mkdir -p ../../cover
TIUP_HOME=$(shell pwd)/../../tests/tiup $(GOTEST) ./... -covermode=count -coverprofile ../../cover/cov.unit-test.client.out

race: failpoint-enable
@# Target: run race check with failpoint enabled
Expand Down
80 changes: 78 additions & 2 deletions components/cluster/command/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,23 @@
package command

import (
"database/sql"
"fmt"

"github.com/fatih/color"
"github.com/pingcap/tiup/pkg/cluster/spec"
"github.com/pingcap/tiup/pkg/cluster/task"
"github.com/pingcap/tiup/pkg/crypto/rand"
"github.com/pingcap/tiup/pkg/proxy"
"github.com/spf13/cobra"

// for sql/driver
_ "github.com/go-sql-driver/mysql"
)

func newStartCmd() *cobra.Command {
var initPasswd bool

cmd := &cobra.Command{
Use: "start <cluster-name>",
Short: "Start a TiDB cluster",
Expand All @@ -36,19 +47,84 @@ func newStartCmd() *cobra.Command {
clusterReport.ID = scrubClusterName(clusterName)
teleCommand = append(teleCommand, scrubClusterName(clusterName))

return cm.StartCluster(clusterName, gOpt, func(b *task.Builder, metadata spec.Metadata) {
if err := cm.StartCluster(clusterName, gOpt, func(b *task.Builder, metadata spec.Metadata) {
b.UpdateTopology(
clusterName,
tidbSpec.Path(clusterName),
metadata.(*spec.ClusterMeta),
nil, /* deleteNodeIds */
)
})
}); err != nil {
return err
}

// init password
if initPasswd {
pwd, err := initPassword(clusterName)
if err != nil {
log.Errorf("failed to set root password of TiDB database to '%s'", pwd)
return err
}
log.Warnf("The root password of TiDB database has been changed.")
fmt.Printf("The new password is: '%s'.", color.HiYellowString(pwd)) // use fmt to avoid printing to audit log
log.Warnf("Copy and record it to somewhere safe, %s, and will not be stored.", color.HiRedString("it is only displayed once"))
log.Warnf("The generated password %s.", color.HiRedString("could NOT be get and shown again"))
}
return nil
},
}

cmd.Flags().BoolVar(&initPasswd, "init", false, "Initialize a secure root password for the database")
cmd.Flags().StringSliceVarP(&gOpt.Roles, "role", "R", nil, "Only start specified roles")
cmd.Flags().StringSliceVarP(&gOpt.Nodes, "node", "N", nil, "Only start specified nodes")

return cmd
}

func initPassword(clusterName string) (string, error) {
metadata, err := spec.ClusterMetadata(clusterName)
if err != nil {
return "", err
}
tcpProxy := proxy.GetTCPProxy()

// generate password
pwd, err := rand.Password(18)
if err != nil {
return pwd, err
}

var lastErr error
for _, spec := range metadata.Topology.TiDBServers {
spec := spec
endpoint := fmt.Sprintf("%s:%d", spec.Host, spec.Port)
if tcpProxy != nil {
closeC := tcpProxy.Run([]string{endpoint})
defer tcpProxy.Close(closeC)
endpoint = tcpProxy.GetEndpoints()[0]
}
db, err := createDB(endpoint)
if err != nil {
lastErr = err
continue
}
defer db.Close()

sqlStr := fmt.Sprintf("SET PASSWORD FOR 'root'@'%%' = '%s'; FLUSH PRIVILEGES;", pwd)
_, err = db.Exec(sqlStr)
if err != nil {
lastErr = err
continue
}
return pwd, nil
}

return pwd, lastErr
}

func createDB(endpoint string) (db *sql.DB, err error) {
dsn := fmt.Sprintf("root:@tcp(%s)/?charset=utf8mb4,utf8&multiStatements=true", endpoint)
db, err = sql.Open("mysql", dsn)

return
}
8 changes: 0 additions & 8 deletions components/cluster/command/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package command

import (
"context"
"database/sql"
"errors"
"fmt"

Expand Down Expand Up @@ -72,13 +71,6 @@ func newTestCmd() *cobra.Command {
return cmd
}

func createDB(endpoint string) (db *sql.DB, err error) {
dsn := fmt.Sprintf("root:@tcp(%s)/?charset=utf8mb4,utf8&multiStatements=true", endpoint)
db, err = sql.Open("mysql", dsn)

return
}

// To check if test.ti_cluster has data
func data(topo *spec.Specification, tcpProxy *proxy.TCPProxy) error {
errg, _ := errgroup.WithContext(context.Background())
Expand Down
3 changes: 3 additions & 0 deletions embed/templates/scripts/run_tidb.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ exec env GODEBUG=madvdontneed=1 bin/tidb-server \
--host="{{.ListenHost}}" \
--advertise-address="{{.AdvertiseAddr}}" \
--store="tikv" \
{{- if .SupportSecboot}}
--initialize-insecure \
{{- end}}
--path="{{template "PDList" .Endpoints}}" \
--log-slow-query="{{.LogDir}}/tidb_slow_query.log" \
--config=conf/tidb.toml \
Expand Down
2 changes: 1 addition & 1 deletion examples
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/r3labs/diff/v2 v2.14.0
github.com/relex/aini v1.5.0
github.com/sergi/go-diff v1.2.0
github.com/sethvargo/go-password v0.2.0
github.com/shirou/gopsutil v3.21.8+incompatible
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/spf13/cobra v1.2.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI=
github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE=
github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU=
github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
Expand Down
4 changes: 3 additions & 1 deletion pkg/cluster/spec/tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/pingcap/tiup/pkg/cluster/ctxt"
"github.com/pingcap/tiup/pkg/cluster/template/scripts"
"github.com/pingcap/tiup/pkg/meta"
"golang.org/x/mod/semver"
)

// TiDBSpec represents the TiDB topology specification in topology.yaml
Expand Down Expand Up @@ -144,7 +145,8 @@ func (i *TiDBInstance) InitConfig(
WithStatusPort(spec.StatusPort).
AppendEndpoints(topo.Endpoints(deployUser)...).
WithListenHost(i.GetListenHost()).
WithAdvertiseAddr(spec.Host)
WithAdvertiseAddr(spec.Host).
SupportSecureBootstrap(semver.Compare(clusterVersion, "v5.3.0") >= 0)
fp := filepath.Join(paths.Cache, fmt.Sprintf("run_tidb_%s_%d.sh", i.GetHost(), i.GetPort()))
if err := cfg.ConfigToFile(fp); err != nil {
return err
Expand Down
25 changes: 16 additions & 9 deletions pkg/cluster/template/scripts/tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ import (

// TiDBScript represent the data to generate TiDB config
type TiDBScript struct {
IP string
ListenHost string
AdvertiseAddr string
Port int
StatusPort int
DeployDir string
LogDir string
NumaNode string
Endpoints []*PDScript
IP string
ListenHost string
AdvertiseAddr string
Port int
StatusPort int
DeployDir string
LogDir string
NumaNode string
SupportSecboot bool
Endpoints []*PDScript
}

// NewTiDBScript returns a TiDBScript with given arguments
Expand Down Expand Up @@ -79,6 +80,12 @@ func (c *TiDBScript) WithNumaNode(numa string) *TiDBScript {
return c
}

// SupportSecureBootstrap set SupportSecboot field of TiDBScript
func (c *TiDBScript) SupportSecureBootstrap(s bool) *TiDBScript {
c.SupportSecboot = s
return c
}

// AppendEndpoints add new PDScript to Endpoints field
func (c *TiDBScript) AppendEndpoints(ends ...*PDScript) *TiDBScript {
c.Endpoints = append(c.Endpoints, ends...)
Expand Down
53 changes: 53 additions & 0 deletions pkg/crypto/rand/passwd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2021 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package rand

import (
"github.com/sethvargo/go-password/password"
)

// charsets with some in similar shapes removed (e.g., O, o, I, l, etc.)
const (
lowerLetters = "abcdefghijkmnpqrstuvwxyz"
upperLetters = "ABCDEFGHJKLMNPQRSTUVWXYZ"
digits = "0123456789"
symbols = "!@#$%^&*+-=_"
)

// Password generates a random password
func Password(length int) (string, error) {
if length < 8 {
panic("password length muster be at least 8.")
}

gi := &password.GeneratorInput{
LowerLetters: lowerLetters,
UpperLetters: upperLetters,
Digits: digits,
Symbols: symbols,
Reader: Reader,
}
g, err := password.NewGenerator(gi)
if err != nil {
return "", err
}

// 1/3 of the password are digits and 1/4 of it are symbols
numDigits := length / 3
numSymbols := length / 4
// allow repeat if the length is longer than the shortest charset
allowRepeat := (numDigits > len(digits) || numSymbols > len(symbols))

return g.Generate(length, numDigits, numSymbols, false, allowRepeat)
}
36 changes: 36 additions & 0 deletions pkg/crypto/rand/passwd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2021 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package rand

import (
"testing"
)

func TestPasswd(t *testing.T) {
for i := 0; i < 100; i++ {
l := Intn(64)
if l < 8 { // make sure it's greater than 8
l += 8
}
t.Logf("generating random password of length %d", l)
p, e := Password(l)
if e != nil {
t.Error(e)
}
t.Log(p)
if len(p) != l {
t.Fail()
}
}
}

0 comments on commit 13b33c0

Please sign in to comment.