I'm connecting to an EC2 instance from a remote machine via Java and Jsch. Once connected, I want to start a jboss server that sits in a directory owned and created by root. (I can't change that).
Usually from my putty shell, I would start jboss by issuing the following commands:
myUser#myIP:~# sudo su -
root#myIP:~:# cd jbossDirectory
root#myIp:~/jbossDirectory# ./startJbossScript.sh
The problems start when I try to do the same via Java/Jscp. This is my code:
import java.io.InputStream;
import java.io.OutputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
public class SSHExecutor {
static String SSHprivateKey = privateKeyFileLocation;
static String username = myUser;
static String hostnamePublicIP = EC2InstanceIP;
static String startJbossCommand = "sudo -i /root/jbossDirectory/startJbossScript.sh";
static String sudo_pass = "";
public static void main(String[] arg) {
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
try {
JSch jsch = new JSch();
jsch.addIdentity(SSHprivateKey);
Session session = jsch.getSession(username, hostnamePublicIP, 22);
// username and passphrase will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(startJbossCommnand);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
channel.connect();
out.write((sudo_pass + "\n").getBytes());
out.flush();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
System.out.println("exit-status: "
+ channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
channel.disconnect();
session.disconnect();
} catch (Exception e) {
System.out.println(e);
}
}
}
This program will correctly starts Jboss. However, when Jboss receives a request for a dynamic page, it throws the following error:
06:48:13,137 INFO [STDOUT] >>>>>>>>/root/.
06:8:13,138 INFO [STDOUT] Exception while initializing hibernate: java.io.FileNotFoundException: WEBAPP_CONF/hibernate.properties (No such file or directory)
06:48:13,141 INFO [[/rubis]] Marking servlet BrowseRegions as unavailable
06:48:13,141 ERROR [[BrowseRegions]] Allocate exception for servlet BrowseRegions
javax.servlet.UnavailableException: Couldn't find file mysql.properties: java.io.FileNotFoundException: WEBAPP_CONF/mysql.properties (No such file or directory)<br>
at edu.rice.rubis.servlets.RubisHttpServlet.init(Unknown Source)
at edu.rice.rubis.servlets.HibernateRubisHttpServlet.init(Unknown Source)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:724)
So it appears that it can't find the mysql configuration file. The file is there and this issue does not happen when I launch jboss from the console (as showed above). My guess is that the process does start with the sudo -i command, but then, it can't access the files that are within the jbossDirectory folder, hence it throws the error file not found. The WEBAPP_CONF/ is a subdirectory of jbossDirectory.
Any idea on how to fix this?
Thank you.
You are running the shell script from a different directory, and there is something in your code that expects the start-up script to start specifically in /root/jbossDirectory.
A simple workaround would be to edit startJbossScript.sh and add
cd /root/jbossDirectory
as the first line.
Before the channel.connect() line in your code add the below line which will allow you to excecute sudo commands
((ChannelExec) channel).setPty(true);
Related
This question already has an answer here:
Can we use JSch for SSH key-based communication?
(1 answer)
Closed 4 years ago.
I have two servers A and B.
I want to SFTP a file from server A to B.
Public key of server A (~/.ssh/id_rsa.pub) has been added to the ~/.ssh/authorized_keys of server B.
From command line, I can SFTP from server A to B without entering password.
However, from a Java client using library Jsch I am unable to make SFTP connection to server B and I am getting authentication error:
Error occurred during SFTP. Auth fail
com.jcraft.jsch.JSchException: Auth fail
at com.jcraft.jsch.Session.connect(Session.java:519)
at com.jcraft.jsch.Session.connect(Session.java:183)
at Main.main(Main.java:15)
Is there a way I can connect to server B for SFTP purposes using Java client without specifying password?
Below is my Java code for reference:
import com.jcraft.jsch.*;
public class Main {
public static void main(String[] args) {
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession("processor", "remoteserver.myorg.com", 22);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Trying to connect...");
session.connect();
System.out.println("Connected successfully.");
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
System.out.println("Doing SFTP...");
sftpChannel.put("/tmp/test.txt", "/some/remote/folder");
System.out.println("Success");
sftpChannel.exit();
session.disconnect();
} catch (JSchException | SftpException e) {
System.err.println("Error occurred during SFTP. " + e.getMessage());
e.printStackTrace();
}
}
}
Use addIdentity() api in jsync and point to your private key file location.
Ref:
Can we use JSch for SSH key-based communication?
String privateKey = "~/.ssh/id_rsa";
jsch.addIdentity(privateKey);
System.out.println("identity added ");
Session session = jsch.getSession(user, host, port);
System.out.println("session created.");
I am using JSch for sftp communication, now i want to use facilitate the key-based authentication, key is loaded on client and server machine once by my network team and all later communication would be only user based for which we have loaded the key.
sftp -oPort=10022 jmark#192.18.0.246
as tjill#192.18.0.135
like this command work fine and connect to the sftp, how i can achieve this functionality programmatically.
if it is not possible using JSch, please suggest some other library. I came across Apache SSHD.
It is possible. Have a look at JSch.addIdentity(...)
This allows you to use key either as byte array or to read it from file.
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class UserAuthPubKey {
public static void main(String[] arg) {
try {
JSch jsch = new JSch();
String user = "tjill";
String host = "192.18.0.246";
int port = 10022;
String privateKey = ".ssh/id_rsa";
jsch.addIdentity(privateKey);
System.out.println("identity added ");
Session session = jsch.getSession(user, host, port);
System.out.println("session created.");
// disabling StrictHostKeyChecking may help to make connection but makes it insecure
// see http://stackoverflow.com/questions/30178936/jsch-sftp-security-with-session-setconfigstricthostkeychecking-no
//
// java.util.Properties config = new java.util.Properties();
// config.put("StrictHostKeyChecking", "no");
// session.setConfig(config);
session.connect();
System.out.println("session connected.....");
Channel channel = session.openChannel("sftp");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
System.out.println("shell channel connected....");
ChannelSftp c = (ChannelSftp) channel;
String fileName = "test.txt";
c.put(fileName, "./in/");
c.exit();
System.out.println("done");
} catch (Exception e) {
System.err.println(e);
}
}
}
I am using JAVA 8. I am trying to connect a Socket Server using client certificates and certificate tree.
I have followings provided by client:
Client CERT (PEM)
Private Key (PEM)
CA Tree (PEM) - with 4 Certificates
I have created keystore.jks using following steps:
Combining client cert and CA tree in a single pem file using cat
Crested PKCS12 file from combined file encrypted using private key(OpenSSL Command)
Generated JKS keystore file using keytool
I have created trustore.jks using following steps:
Split CA Tree (4 certificates) into 4 different files
Generated trustore file using keytool by importing each file one by one
My Sample code is as following :
package com.tutorial.exception.customize;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.util.Scanner;
/**
* Created by SomnathG on 12/1/2016.
*/
public class Client {
public Client() {
System.setProperty("javax.net.ssl.keyStore", {keystore Location});
System.setProperty("javax.net.ssl.keyStorePassword", {password});
System.setProperty("javax.net.ssl.trustStore", {trustore location});
System.setProperty("javax.net.ssl.trustStorePassword", {password});
System.setProperty("javax.net.debug", "all");
System.setProperty( "sun.security.ssl.allowUnsafeRenegotiation", "true" );
}
public void connectHost(){
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = null;
try {
sslSocket = (SSLSocket) sslSocketFactory.createSocket(host, port);
sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
sslSocket.startHandshake();
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
System.out.println("Sending request to Socket Server");
outputStream.write("Hello".getBytes());
outputStream.write("exit".getBytes());
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
int bytesRead = 0;
String messageString = "";
DataInputStream in = new DataInputStream(sslSocket.getInputStream());
while(!end)
{
bytesRead = in.read(messageByte);
messageString += new String(messageByte, 0, bytesRead);
if (messageString.length() == 100)
{
end = true;
}
}
System.out.println("MESSAGE: " + messageString);
// byte[] read = (byte[]) ois.readObject();
//String s2 = new String(read);
//System.out.println("" + s2);
//System.out.println("Message: " + message);
//close resources
//System.out.println(receive(inputStream));
}catch (IOException e) {
e.printStackTrace();
System.out.println("=====");
System.out.println(e.getMessage());
System.out.println("=====");
CertPathValidatorException ce = new CertPathValidatorException(e);
System.out.println("******");
System.out.println(ce.getIndex());
System.out.println(ce.getReason());
System.out.println("******");
//e.printStackTrace();
}
}
public static void main(String[] args){
new Client().connectHost();
}
}
I am getting following exception after executing the code:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: this is not a CA certificate
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at com.tutorial.exception.customize.Client.connectHost(Client.java:33)
at com.tutorial.exception.customize.Client.main(Client.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
After analyzing the log I have found "clientHello" and "serverHello" messages but after that application is throwing above mentioned exception.
What am I doing wrong? Please advice.
Thanks,
Somnath Guha
I have figured out the issue after analyzing the debug lo.
"BasicConstraints" was missing from the server V3 certificates and thus java was failing to recognize the certificate as a valid certificate. Once that constraint has been added then the client was able to handshake with the server and able to communicate with server.
BasicConstraints:[
CA:true
PathLen:2147483647
]
I'm trying to use JSch in Java to connect to one of my EC2 instances, but keep getting an "UnknownHostKey" exception message. Here's is (part of) my code:
import com.jcraft.jsch.*;
import java.io.*;
public class JSchTest {
private String serverIp;
public void testSshConnection() {
try {
JSch jsch = new JSch();
jsch.addIdentity("C:\\Users\\Administrator\\.ssh\\id_rsa");
Session session = jsch.getSession("ec2-user", serverIp, 22);
session.connect(30000); // <-- this is where the exception is thrown
ChannelExec channel = (ChannelExec)session.openChannel("shell");
// more code here...
channel.disconnect();
session.disconnect();
} catch (JSchException|IOException ex) {
ex.printStackTrace();
}
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
}
I've already added my public key to the authorized_keys file on the EC2 instance that I'm connecting to, and I know it works because I can connect to it using PuTTY. However as soon as I hit the line with the session.connect() in it, I get an exception like this:
com.jcraft.jsch.JSchException: UnknownHostKey: 10.114.2.115. RSA key fingerprint is 63:04:cf:60:4a:1d:47:35:12:0e:56:4f:5b:0a:c9:d4
What am I missing? How can I get this to connect?
Try this:
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
As per this link.
I wants to write a program to copy/create one file from linux machine to another linux/windows machine in java.
I tried below code,which will create one file in another windows machine..
import java.io.File;
import java.io.IOException;
public class Example2 {
public static void main(String[] args) {
String path = "\\\\10.15.0.166"+File.separator+"test";
String fname= path+File.separator+"Sample.pdf";
File file = new File(fname);
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Exists"+file.exists());
file.getParentFile().mkdirs();
}
}
It worked in WIndows to windows.
But when I tried from linux machine .it is creating folder in the linux machine itself.
Could any one help me to solve this?
To work the above application ,We have to add one more line in the above code,
session.put("StrictHostKeyChecking", "no"); just before session.connect();
Complete program is
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import java.io.File;
public class test {
public static void main(String args[]) throws JSchException {
JSch jsch = new JSch();
Session session = jsch.getSession("user", "10.15.0.243", 22); //port is usually 22
session.setPassword("password1.");
session.put("StrictHostKeyChecking", "no");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp cFTP = (ChannelSftp) channel;
jsch.setConfig("StrictHostKeyChecking", "no");
String sourceFile = "/home/divya/hi.txt", targetFile = "/home/user/test";
try {
cFTP.put(sourceFile , targetFile );
} catch (SftpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cFTP.disconnect();
session.disconnect();
}
}
Regards
Divya
You should use something like FTP to move files between unix machines.
JSCH is a good API for that.
You will need some user authentication tho.
Here is an example:
JSch jsch = new JSCH();
Session session = jsch.getSession(config.getUsername(), config.getHostname(), config.getPort()); //port is usually 22
session.setPassword(config.getPassword());
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp cFTP = (ChannelSftp) channel;
String sourceFile = "---", targetFile = "---";
cFTP.put(sourceFile , targetFile );
cFTP.disconnect();
session.disconnect();
You can't create a file on another machine this way under Linux... You are using Windows share folders, which is not the way files are shared in Linux world. You have two choices :
either by connecting the two filesystems, with NFS for example (a
kind of Unix file sharing), in such a way that the second filesystem
is mounted on the first one so that a path will lead you to the
second machine in a way similar to Windows file sharing paths.
either by using some protocol to transfer your file (FTP, RSYNC,
etc).
You can use this code snippet to copy files to another linux machine.
JSch jsch = new JSch();
Session session = null;
session = jsch.getSession("username","hostname",22);
session.setPassword("password");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelSftp channel = null;
channel = (ChannelSftp)session.openChannel("sftp");
channel.connect();
File localFile = new File("localfilepath");
//If you want you can change the directory using the following line.
channel.cd(RemoteDirectoryPath)
channel.put(new FileInputStream(localFile),localFile.getName());
channel.disconnect();
session.disconnect();
For more details reach out THIS similar post