Skip to content

Commit

Permalink
cluster: check, deploy support use ssh-agent instead of identity-file (
Browse files Browse the repository at this point in the history
  • Loading branch information
jsvisa authored Jun 11, 2021
1 parent befddd5 commit ffa74b5
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 69 deletions.
5 changes: 0 additions & 5 deletions components/cluster/command/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package command
import (
"path"

"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/cluster/manager"
operator "github.com/pingcap/tiup/pkg/cluster/operation"
"github.com/pingcap/tiup/pkg/utils"
Expand Down Expand Up @@ -44,10 +43,6 @@ conflict checks with other clusters`,
if opt.ExistCluster {
clusterReport.ID = scrubClusterName(args[0])
}
// natvie ssh has it's own logic to find the default identity_file
if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
opt.IdentityFile = ""
}
return cm.CheckCluster(args[0], opt, gOpt)
},
}
Expand Down
6 changes: 0 additions & 6 deletions components/cluster/command/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"path"

"github.com/pingcap/tiup/pkg/cliutil"
"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/cluster/manager"
operator "github.com/pingcap/tiup/pkg/cluster/operation"
"github.com/pingcap/tiup/pkg/cluster/spec"
Expand Down Expand Up @@ -53,11 +52,6 @@ func newDeploy() *cobra.Command {
return nil
}

// natvie ssh has it's own logic to find the default identity_file
if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
opt.IdentityFile = ""
}

clusterName := args[0]
version, err := utils.FmtVer(args[1])
if err != nil {
Expand Down
6 changes: 0 additions & 6 deletions components/cluster/command/scale_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"os"
"path/filepath"

"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/cluster/manager"
"github.com/pingcap/tiup/pkg/cluster/spec"
"github.com/pingcap/tiup/pkg/cluster/task"
Expand All @@ -38,11 +37,6 @@ func newScaleOutCmd() *cobra.Command {
return cmd.Help()
}

// natvie ssh has it's own logic to find the default identity_file
if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
opt.IdentityFile = ""
}

clusterName := args[0]
clusterReport.ID = scrubClusterName(clusterName)
teleCommand = append(teleCommand, scrubClusterName(clusterName))
Expand Down
6 changes: 0 additions & 6 deletions components/dm/command/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/pingcap/errors"
"github.com/pingcap/tiup/pkg/cliutil"
"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/cluster/manager"
operator "github.com/pingcap/tiup/pkg/cluster/operation"
"github.com/pingcap/tiup/pkg/cluster/spec"
Expand Down Expand Up @@ -47,11 +46,6 @@ func newDeployCmd() *cobra.Command {
return nil
}

// natvie ssh has it's own logic to find the default identity_file
if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
opt.IdentityFile = ""
}

clusterName := args[0]
version, err := utils.FmtVer(args[1])
if err != nil {
Expand Down
6 changes: 0 additions & 6 deletions components/dm/command/scale_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package command
import (
"path/filepath"

"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/cluster/manager"
"github.com/pingcap/tiup/pkg/cluster/spec"
"github.com/pingcap/tiup/pkg/cluster/task"
Expand All @@ -37,11 +36,6 @@ func newScaleOutCmd() *cobra.Command {
return cmd.Help()
}

// natvie ssh has it's own logic to find the default identity_file
if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
opt.IdentityFile = ""
}

clusterName := args[0]
topoFile := args[1]

Expand Down
86 changes: 51 additions & 35 deletions pkg/cliutil/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import (

"github.com/ScaleFT/sshkeys"
"github.com/pingcap/tiup/pkg/errutil"
"github.com/pingcap/tiup/pkg/utils"
"golang.org/x/crypto/ssh"
)

var (
// ErrIdentityFileReadFiled is ErrIdentityFileReadFiled
ErrIdentityFileReadFiled = errNS.NewType("id_read_failed", errutil.ErrTraitPreCheck)
// ErrIdentityFileReadFailed is ErrIdentityFileReadFailed
ErrIdentityFileReadFailed = errNS.NewType("id_read_failed", errutil.ErrTraitPreCheck)
)

// SSHConnectionProps is SSHConnectionProps
Expand All @@ -41,50 +42,65 @@ func ReadIdentityFileOrPassword(identityFilePath string, usePass bool) (*SSHConn
return &SSHConnectionProps{
Password: password,
}, nil
} else if identityFilePath == "" {
return &SSHConnectionProps{}, nil
}

// Identity file is specified, check identity file
buf, err := os.ReadFile(identityFilePath)
if err != nil {
return nil, ErrIdentityFileReadFiled.
Wrap(err, "Failed to read SSH identity file '%s'", identityFilePath).
WithProperty(SuggestionFromTemplate(`
if len(identityFilePath) > 0 && utils.IsExist(identityFilePath) {
buf, err := os.ReadFile(identityFilePath)
if err != nil {
return nil, ErrIdentityFileReadFailed.
Wrap(err, "Failed to read SSH identity file '%s'", identityFilePath).
WithProperty(SuggestionFromTemplate(`
Please check whether your SSH identity file {{ColorKeyword}}{{.File}}{{ColorReset}} exists and have access permission.
`, map[string]string{
"File": identityFilePath,
}))
}
"File": identityFilePath,
}))
}

// Try to decode as not encrypted
_, err = ssh.ParsePrivateKey(buf)
if err == nil {
return &SSHConnectionProps{
IdentityFile: identityFilePath,
}, nil
}
// Try to decode as not encrypted
_, err = ssh.ParsePrivateKey(buf)
if err == nil {
return &SSHConnectionProps{
IdentityFile: identityFilePath,
}, nil
}

// Other kind of error.. e.g. not a valid SSH key
if _, ok := err.(*ssh.PassphraseMissingError); !ok {
return nil, ErrIdentityFileReadFiled.
Wrap(err, "Failed to read SSH identity file '%s'", identityFilePath).
WithProperty(SuggestionFromTemplate(`
// Other kind of error.. e.g. not a valid SSH key
if _, ok := err.(*ssh.PassphraseMissingError); !ok {
return nil, ErrIdentityFileReadFailed.
Wrap(err, "Failed to read SSH identity file '%s'", identityFilePath).
WithProperty(SuggestionFromTemplate(`
Looks like your SSH private key {{ColorKeyword}}{{.File}}{{ColorReset}} is invalid.
`, map[string]string{
"File": identityFilePath,
}))
"File": identityFilePath,
}))
}

// SSH key is passphrase protected
passphrase := PromptForPassword("The SSH identity key is encrypted. Input its passphrase: ")
if _, err := sshkeys.ParseEncryptedPrivateKey(buf, []byte(passphrase)); err != nil {
return nil, ErrIdentityFileReadFailed.
Wrap(err, "Failed to decrypt SSH identity file '%s'", identityFilePath)
}

return &SSHConnectionProps{
IdentityFile: identityFilePath,
IdentityFilePassphrase: passphrase,
}, nil
}

// SSH key is passphrase protected
passphrase := PromptForPassword("The SSH identity key is encrypted. Input its passphrase: ")
if _, err := sshkeys.ParseEncryptedPrivateKey(buf, []byte(passphrase)); err != nil {
return nil, ErrIdentityFileReadFiled.
Wrap(err, "Failed to decrypt SSH identity file '%s'", identityFilePath)
// No password, nor identity file were specified, check ssh-agent via the env SSH_AUTH_SOCK
sshAuthSock := os.Getenv("SSH_AUTH_SOCK")
if len(sshAuthSock) == 0 {
return nil, ErrIdentityFileReadFailed.New("none of ssh password, identity file, SSH_AUTH_SOCK specified")
}
stat, err := os.Stat(sshAuthSock)
if err != nil {
return nil, ErrIdentityFileReadFailed.Wrap(err, "Failed to stat SSH_AUTH_SOCK file: '%s'", sshAuthSock)
}
if stat.Mode()&os.ModeSocket == 0 {
return nil, ErrIdentityFileReadFailed.New("The SSH_AUTH_SOCK file: '%s' is not a valid unix socket file", sshAuthSock)
}

return &SSHConnectionProps{
IdentityFile: identityFilePath,
IdentityFilePassphrase: passphrase,
}, nil
return &SSHConnectionProps{}, nil
}
5 changes: 0 additions & 5 deletions pkg/cluster/manager/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,6 @@ func (m *Manager) CheckCluster(clusterOrTopoName string, opt CheckOptions, gOpt
}
}

// natvie ssh has it's own logic to find the default identity_file
// if gOpt.SSHType == executor.SSHTypeSystem && !utils.IsFlagSetByUser(cmd.Flags(), "identity_file") {
// opt.identityFile = ""
// }

var sshConnProps *cliutil.SSHConnectionProps = &cliutil.SSHConnectionProps{}
if gOpt.SSHType != executor.SSHTypeNone {
var err error
Expand Down
6 changes: 6 additions & 0 deletions tests/tiup-cluster/script/cmd_subtest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ function cmd_subtest() {
client="--ssh=system"
fi

# identify SSH via ssh-agent
eval $(ssh-agent) &> /dev/null
ssh-add /root/.ssh/id_rsa &> /dev/null

mv /root/.ssh/id_rsa{,.bak}
tiup-cluster $client check $topo -i ~/.ssh/id_rsa --enable-mem --enable-cpu --apply
mv /root/.ssh/id_rsa{.bak,}

check_result=`tiup-cluster $client --yes check $topo -i ~/.ssh/id_rsa`

Expand Down

0 comments on commit ffa74b5

Please sign in to comment.