2017-04-18 283 views
0

我正在尝试自动化一些操作,其中一项操作是切换到远程Linux机器上的技术用户。该过程如下所示:使用“普通”用户登录,然后使用Jsch和sudo命令

sudo /bin/rootsh -i -u techUser

切换到技术用户。

这里是我的,我的工作Groovy的代码示例:

import com.jcraft.jsch.JSch 
import com.jcraft.jsch.Session 
import com.jcraft.jsch.Channel 
import com.jcraft.jsch.ChannelExec 
import com.jcraft.jsch.JSchException 

class Main { 
    static void main(String[] args) { 
     int responseCode = 0 
     String responseText = "" 
     def targetHost = "targetHost" 
     def targetUser = "targetUser" 
     def technicalUser= "technicalUser" 
     def targetPass = "targetPass" 
     def targetPort = 22 
     Properties configConnection = new Properties() 
     configConnection.put("StrictHostKeyChecking", "no") 
     configConnection.put("PreferredAuthentications", "publickey,keyboard-interactive,password") 
     JSch jsch = new JSch() 
     try { 
      Session targetSession = jsch.getSession(targetUser, targetHost, targetPort) 
      targetSession.setPassword(targetPass) 
      targetSession.setConfig(configConnection) 
      targetSession.connect() 
      Channel channel = targetSession.openChannel("exec") 
      ((ChannelExec) channel).setCommand("echo 'targetPass' | sudo -S -p /bin/rootsh -i -u technicalUser") 
      ((ChannelExec) channel).setPty(true) 
      final ByteArrayOutputStream baos = new ByteArrayOutputStream() 
      ((ChannelExec) channel).setErrStream(baos) 
      channel.setInputStream(null) 
      InputStream is = channel.getInputStream() 
      channel.connect() 
      byte[] tmp = new byte[1024] 
      while (true) { 
       while (is.available() > 0) { 
        int i = is.read(tmp, 0, 1024) 
        if (i < 0) 
         break 
        responseText = new String(tmp, 0, i) 
       } 
       if (channel.isClosed()) { 
        responseText = new String(baos.toByteArray()) 
        responseCode = channel.getExitStatus() 
        break 
       } 
       try { 
        Thread.sleep(1000); 
       } catch (Exception ee) { 
        println("[ERROR] " + ee.getMessage()) 
       } 
      } 
      channel.disconnect() 
      targetSession.disconnect() 
      println("RESULT: code: " + responseCode + ", text: \"" + responseText + "\"") 
     } catch (JSchException e) { 
      println("[ERROR] Exception, problem with connection: " + e.getMessage()) 
     } 
    } 
} 

结果是:

RESULT: code: 1, text: "" 

当我设置为

((ChannelExec) channel).setPty(false) 

结果是:

RESULT: code: 1, text: "/bin/rootshSorry, user targetUser is not allowed to execute '/bin/bash' as technicalUser on targetHost." 

当我从以下行删除密码:

((ChannelExec) channel).setCommand("echo '' | sudo -S -p /bin/rootsh -i -u technichalUser") 

结果是:

RESULT: code: 1, text: "/bin/rootsh/bin/rootsh 
Sorry, try again. 
/bin/rootsh 
/bin/rootsh 
sudo: pam_authenticate: Authentication information cannot be recovered" 

当我设置以下命令:

((ChannelExec) channel).setCommand("sudo -S -p /bin/rootsh -i -u technichalUser") 

没有响应毕竟随着进程一直在运行(进程正在等待密码)

如果有人已经解决了这个问题或类似的问题,我会真正appriciate任何帮助。

回答

0

您无法通过输入重定向将密码传递给sudo,至少不会使用默认配置。

因此,这不能工作:

echo 'targetPass' | sudo -S -p /bin/rootsh -i -u technicalUser` 

你甚至尝试它在交互式终端?我认为它也不会在那里工作。


您必须将密码写入通道输入流(在JSch中称为“输出流”)。

查看官方JSch Sudo example

您可能需要启用TTY/PTY。请参阅Use JSch sudo example and Channel.setPty for running sudo command on remote host