github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/utils/ssh/connect.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ssh 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "net" 21 "path/filepath" 22 "time" 23 24 "github.com/pkg/sftp" 25 26 "github.com/alibaba/sealer/utils" 27 "golang.org/x/crypto/ssh" 28 ) 29 30 const DefaultSSHPort = "22" 31 32 func (s *SSH) connect(host string) (*ssh.Client, error) { 33 if s.Encrypted { 34 passwd, err := utils.AesDecrypt([]byte(s.Password)) 35 if err != nil { 36 return nil, err 37 } 38 s.Password = passwd 39 s.Encrypted = false 40 } 41 auth := s.sshAuthMethod(s.Password, s.PkFile, s.PkPassword) 42 config := ssh.Config{ 43 Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"}, 44 } 45 DefaultTimeout := time.Duration(15) * time.Second 46 if s.Timeout == nil { 47 s.Timeout = &DefaultTimeout 48 } 49 clientConfig := &ssh.ClientConfig{ 50 User: s.User, 51 Auth: auth, 52 Timeout: *s.Timeout, 53 Config: config, 54 HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { 55 return nil 56 }, 57 } 58 if s.Port == "" { 59 s.Port = DefaultSSHPort 60 } 61 return ssh.Dial("tcp", fmt.Sprintf("%s:%s", host, s.Port), clientConfig) 62 } 63 64 func (s *SSH) Connect(host string) (*ssh.Client, *ssh.Session, error) { 65 client, err := s.connect(host) 66 if err != nil { 67 return nil, nil, err 68 } 69 70 session, err := client.NewSession() 71 if err != nil { 72 _ = client.Close() 73 return nil, nil, err 74 } 75 76 modes := ssh.TerminalModes{ 77 ssh.ECHO: 0, //disable echoing 78 ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud 79 ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud 80 } 81 82 if err := session.RequestPty("xterm", 80, 40, modes); err != nil { 83 _ = session.Close() 84 _ = client.Close() 85 return nil, nil, err 86 } 87 88 return client, session, nil 89 } 90 91 func (s *SSH) sshAuthMethod(password, pkFile, pkPasswd string) (auth []ssh.AuthMethod) { 92 if fileExist(pkFile) { 93 am, err := s.sshPrivateKeyMethod(pkFile, pkPasswd) 94 if err == nil { 95 auth = append(auth, am) 96 } 97 } 98 if password != "" { 99 auth = append(auth, s.sshPasswordMethod(password)) 100 } 101 return auth 102 } 103 104 //Authentication with a private key,private key has password and no password to verify in this 105 func (s *SSH) sshPrivateKeyMethod(pkFile, pkPassword string) (am ssh.AuthMethod, err error) { 106 pkData, err := ioutil.ReadFile(filepath.Clean(pkFile)) 107 if err != nil { 108 return nil, err 109 } 110 111 var pk ssh.Signer 112 if pkPassword == "" { 113 pk, err = ssh.ParsePrivateKey(pkData) 114 if err != nil { 115 return nil, err 116 } 117 } else { 118 bufPwd := []byte(pkPassword) 119 pk, err = ssh.ParsePrivateKeyWithPassphrase(pkData, bufPwd) 120 if err != nil { 121 return nil, err 122 } 123 } 124 return ssh.PublicKeys(pk), nil 125 } 126 127 func (s *SSH) sshPasswordMethod(password string) ssh.AuthMethod { 128 return ssh.Password(password) 129 } 130 131 func (s *SSH) sftpConnect(host string) (*ssh.Client, *sftp.Client, error) { 132 sshClient, err := s.connect(host) 133 if err != nil { 134 return nil, nil, err 135 } 136 137 // create sftp client 138 sftpClient, err := sftp.NewClient(sshClient) 139 return sshClient, sftpClient, err 140 }