Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cluster: check, deploy support use ssh-agent instead of identity-file #1416

Merged
merged 7 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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("ssh password, identity file, SSH_AUTH_SOCK were not specified")
9547 marked this conversation as resolved.
Show resolved Hide resolved
}
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is sshAuthSock used in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSH_AUTH_SOCK will be used in https://github.com/appleboy/easyssh-proxy/blob/master/easyssh.go#L147-L149, our previous code just checks this socket file exists and valid.

}
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