I am trying to automate some operations and one of such an operation is switching to a technical user on a remote Linux machine. The procedure looks like this: log in with a "normal" user and then switch with
sudo /bin/rootsh -i -u techUser
to the technical user.
Here's my Groovy code example that I am working on:
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())
}
}
}
The result is:
RESULT: code: 1, text: ""
When I set to
((ChannelExec) channel).setPty(false)
the result is:
RESULT: code: 1, text: "/bin/rootshSorry, user targetUser is not allowed to execute '/bin/bash' as technicalUser on targetHost."
When I remove the password from the following line:
((ChannelExec) channel).setCommand("echo '' | sudo -S -p /bin/rootsh -i -u technichalUser")
The result is:
RESULT: code: 1, text: "/bin/rootsh/bin/rootsh
Sorry, try again.
/bin/rootsh
/bin/rootsh
sudo: pam_authenticate: Authentication information cannot be recovered"
And when I set the following command:
((ChannelExec) channel).setCommand("sudo -S -p /bin/rootsh -i -u technichalUser")
There is no response at all as the process is running all the time (the process is waiting for password maybe)
If someone has already solved such an issue or a similar one, I would really appriciate any help.
You cannot pass a password to sudo
with input redirection, at least not with the default configuration.
Hence, this cannot work:
echo 'targetPass' | sudo -S -p /bin/rootsh -i -u technicalUser`
Did you even try it in the interactive terminal? I assume it would not work there either.
You have to write the password to the channel input stream (called "output stream" in JSch).
See the official JSch Sudo example.
You may need to enable TTY/PTY. See Use JSch sudo example and Channel.setPty for running sudo command on remote host.
来源:https://stackoverflow.com/questions/43467747/jsch-and-sudo-command