mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-17 02:20:26 +08:00
SSH认证支持sudo
This commit is contained in:
@@ -13,6 +13,9 @@ import (
|
||||
type SSHClient struct {
|
||||
raw *ssh.Client
|
||||
sftp *sftp.Client
|
||||
|
||||
sudo bool
|
||||
sudoPassword string
|
||||
}
|
||||
|
||||
func NewSSHClient(raw *ssh.Client) (*SSHClient, error) {
|
||||
@@ -30,8 +33,18 @@ func NewSSHClient(raw *ssh.Client) (*SSHClient, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Sudo 设置使用Sudo
|
||||
func (this *SSHClient) Sudo(password string) {
|
||||
this.sudo = true
|
||||
this.sudoPassword = password
|
||||
}
|
||||
|
||||
// Exec 执行shell命令
|
||||
func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error) {
|
||||
if this.raw.User() != "root" && this.sudo {
|
||||
return this.execSudo(cmd, this.sudoPassword)
|
||||
}
|
||||
|
||||
session, err := this.raw.NewSession()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@@ -40,8 +53,8 @@ func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error
|
||||
_ = session.Close()
|
||||
}()
|
||||
|
||||
stdoutBuf := bytes.NewBuffer([]byte{})
|
||||
stderrBuf := bytes.NewBuffer([]byte{})
|
||||
var stdoutBuf = &bytes.Buffer{}
|
||||
var stderrBuf = &bytes.Buffer{}
|
||||
session.Stdout = stdoutBuf
|
||||
session.Stderr = stderrBuf
|
||||
err = session.Run(cmd)
|
||||
@@ -51,6 +64,79 @@ func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error
|
||||
return strings.TrimRight(stdoutBuf.String(), "\n"), stderrBuf.String(), nil
|
||||
}
|
||||
|
||||
// execSudo 使用sudo执行shell命令
|
||||
func (this *SSHClient) execSudo(cmd string, password string) (stdout string, stderr string, err error) {
|
||||
session, err := this.raw.NewSession()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer func() {
|
||||
_ = session.Close()
|
||||
}()
|
||||
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // disable echo
|
||||
ssh.TTY_OP_ISPEED: 14400,
|
||||
ssh.TTY_OP_OSPEED: 14400,
|
||||
}
|
||||
|
||||
err = session.RequestPty("xterm", 80, 40, modes)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
var stderrBuf = &bytes.Buffer{}
|
||||
session.Stderr = stderrBuf
|
||||
|
||||
pipeIn, err := session.StdinPipe()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pipeOut, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
var resultErr error
|
||||
var stdoutBuf = bytes.NewBuffer([]byte{})
|
||||
|
||||
go func() {
|
||||
var buf = make([]byte, 512)
|
||||
for {
|
||||
n, err := pipeOut.Read(buf)
|
||||
if n > 0 {
|
||||
if strings.Contains(string(buf[:n]), "[sudo] password for") {
|
||||
_, err = pipeIn.Write([]byte(password + "\n"))
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
stdoutBuf.Write(buf[:n])
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.Run("sudo " + cmd)
|
||||
|
||||
stdout = strings.TrimSpace(stdoutBuf.String())
|
||||
stderr = strings.TrimSpace(stderrBuf.String())
|
||||
|
||||
if err != nil {
|
||||
return stdout, stderr, err
|
||||
}
|
||||
|
||||
if resultErr != nil {
|
||||
return stdout, stderr, resultErr
|
||||
}
|
||||
return stdout, stderr, nil
|
||||
}
|
||||
|
||||
func (this *SSHClient) Listen(network string, addr string) (net.Listener, error) {
|
||||
return this.raw.Listen(network, addr)
|
||||
}
|
||||
@@ -152,3 +238,31 @@ func (this *SSHClient) WriteFile(path string, data []byte) (n int, err error) {
|
||||
func (this *SSHClient) Remove(path string) error {
|
||||
return this.sftp.Remove(path)
|
||||
}
|
||||
|
||||
// User 用户名
|
||||
func (this *SSHClient) User() string {
|
||||
return this.raw.User()
|
||||
}
|
||||
|
||||
// UserHome 用户地址
|
||||
func (this *SSHClient) UserHome() string {
|
||||
homeStdout, _, err := this.Exec("echo $HOME")
|
||||
if err != nil {
|
||||
return this.defaultUserHome()
|
||||
}
|
||||
|
||||
var home = strings.TrimSpace(homeStdout)
|
||||
if len(home) > 0 {
|
||||
return home
|
||||
}
|
||||
|
||||
return this.defaultUserHome()
|
||||
}
|
||||
|
||||
func (this *SSHClient) defaultUserHome() string {
|
||||
var user = this.raw.User()
|
||||
if user == "root" {
|
||||
return "/root"
|
||||
}
|
||||
return "/home/" + user
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user