Implementing Jump Hosts with SSHJ - shell

Somebody asked for this and there is a pull-request which contains code that somehow was rewritten before it got merged and somebody managed to code a solution based on the pull-request. However, there is no example for the final version in that library.
Therefore, that doesn't really help me with my limited understanding of ssh and all. Basically there are two scenarios I want to solve:
common SSH-session via some jump-hosts:
user1#jump1.com
user2#jump2.com
user3#jump3.com
admin#server.com
ending in an ssh-session where the connecting user is free to work around in that ssh-shell at server.com, i.e. what a normal ssh admin#server.com-command would do in the shell on jump3.com.
like the above but ending in a port forwarding to server.com:80
That is possible with ssh's ProxyCommand, but I want to code this with SSHJ. And that's where I fail to figure out how to do this.
What I have now is
SSHClient hop1 = new SSHClient();
try {
Path knownHosts = rootConfig.getKnownHosts();
if (knownHosts != null) {
hop1.loadKnownHosts(knownHosts.toFile());
} else {
hop1.loadKnownHosts();
}
Path authenticationFile = hop1Config.getAuthenticationFile();
if (authenticationFile != null) {
KeyProvider keyProvider = hop1.loadKeys(authenticationFile.toString(), (String) null);
hop1.authPublickey(hop1Config.getUser(), keyProvider);
} else {
hop1.authPassword(hop1Config.getUser(), hop1Config.getPassword());
}
// I found these methods:
hop1.getConnection();
hop1.getSocket();
// and now what?
} catch (IOException e) {
logger.error("Failed to open ssh-connection to {}", hop1Config, e);
}
I noticed class LocalPortForwarder.DirectTCPIPChannel, but I don't know with what values I should instantiate it or how to use it with the rest afterwards.

Related

E1740 lambda captured variable of type "..." cannot be copied to closure class field of type "..."

I have recently installed VS 2019 and opened up my project I created in VS 2017. The software works fine but there is a bug in VS with lambda captured variables. MS apparently is aware of said issue, but I was wondering if anyone else had come across this recently and if you have, have you managed to solve it?
Example bit of code from my project, the intellisense has flagged up every line where "[this]" appears. The error / bug reads
lambda captured variable of type "MainPage^*" cannot be copied to closure class field of type "MainPage^"
if (_serialPort1 != nullptr)
{
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
Ok, I managed to stumble upon a somewhat ugly hack to fix this.
Rather than pass [this] into the lambda, I added the line auto _this = this; prior to creating any tasks. This did however mean that any variables which were accessed using this->SomeVariable became _this->SomeVariable.
So my example above now looks like this.
if (_serialPort1 != nullptr)
{
auto _this = this;
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
Hope this is of use.
If so then why copying outside the task? You could do
if (_serialPort1 != nullptr)
{ concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this = this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
But based on your problem this is not the proper solution. You better find what's wrong with your project migration to VS 2019.

How to use integrationFlows for new files?

I was following a tutorial on how to listen to a folder with spring integration and SseEmitter. I have this code now:
#Bean
IntegrationFlow inboundFlow ( #Value("${input-dir:file:C:\\Users\\kader\\Desktop\\Scaned\\}") File in){
return IntegrationFlows.from(Files.inboundAdapter(in).autoCreateDirectory(true),
poller -> poller.poller(spec -> spec.fixedRate(1000L)))
.transform(File.class, File::getAbsolutePath)
.handle(String.class, (path, map) -> {
sses.forEach((sse) -> {
try {
String p = path;
sse.send(SseEmitter.event().name("spring").data(p));
}
catch (IOException e) {
throw new RuntimeException(e);
}
});
return null ;
})
.get();
}
and it works but it sends all the files in the specified directory including the files that already exist, is there any way to make it ignore them and send the new files only???
Well, actually since you don't configure any filters on the Files.inboundAdapter(), there is a logic like this:
// no filters are provided
else if (Boolean.FALSE.equals(this.preventDuplicates)) {
filtersNeeded.add(new AcceptAllFileListFilter<File>());
}
else { // preventDuplicates is either TRUE or NULL
filtersNeeded.add(new AcceptOnceFileListFilter<File>());
}
Therefore an AcceptOnceFileListFilter is applied and no any already polled files are not going to be picked up on the subsequent poll tasks.
However you really may talk about something like "after application restart", so yes, in this case all the files are going to be pulled.
I believe you need to study what is the FileListFilter and use an appropriate for your use-case: https://docs.spring.io/spring-integration/docs/current/reference/html/files.html#file-reading

apache VFS2 uriStyle - root absolute path ends with double slash

while working on an ftp server with the vfs2 library I noticed, that I had to enable VFS.setUriStyle(true) so the library would change the working directory to parent directory of the target file I am operating on (cwd directoryName).
But if UriStyle is enabled, everything is being resolved relativly to the root. Which would not be a Problem if the root was not "//".
The class GenericFileName sets the absolutePath of the root to "/", which makes the Method getPath() return "/"+getUriTrailer() which in the case of the root always returns "//". Everything that is resolved relativly to // has two dots proceeding to their path.
Which means if I execute the following code:
public class RemoteFileTest {
public static void main(String[] args) {
// Options for a RemoteFileObject connection
VFS.setUriStyle(true);
FileSystemOptions options = new FileSystemOptions();
// we doing an ftp connection, hence we use the ftpConfigBuilder
// we want to work in passive mode
FtpFileSystemConfigBuilder.getInstance().setPassiveMode(options, true);
FtpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(options, false);
// DefaultFileSystemConfigBuilder.getInstance().setRootURI(options, "/newRoot/");
// System.out.println(DefaultFileSystemConfigBuilder.getInstance().getRootURI(options));
// ftp://localhost:21/
StaticUserAuthenticator auth = new StaticUserAuthenticator("", "user", "pass");
try {
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(options, auth);
} catch (FileSystemException e) {
e.printStackTrace();
return;
}
// A FileSystemManager creates an abstract FileObject linked to are desired RemoteFile.
// That link is just simulated and not yet real.
FileSystemManager manager;
try {
manager = VFS.getManager();
} catch (FileSystemException e) {
e.printStackTrace();
return;
}
try (FileObject remoteFile = manager.resolveFile("ftp://localhost:21/sub_folder/test.txt", options)) {
System.out.println("Is Folder " + remoteFile.isFolder());
System.out.println("Is File " + remoteFile.isFile());
} catch (FileSystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
}}
I receive this interaction with the ftp server:
USER user
PASS ****
TYPE I
CWD //
SYST
PASV
LIST ..sub_folder/
PWD
CWD ..sub_folder/
I want the interaction to be just like this, but without the two dots infront of the directory.
Kind regards
Barry
Fixed it as described below:
Disabled uriStyle again.
Wrote my own VFS class which creates my custom written Manager.
That Manager overwrites the FtpFileProvider with my custom one, which simply sets the root to a custom selected one, which causes the desired behaviour.
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs2.provider.ftp.FtpFileProvider;
public class AdvancedFtpFileProvider extends FtpFileProvider {
public AdvancedFtpFileProvider() {
super();
// setFileNameParser(AdvancedFtpFileNameParser.getInstance());
}
#Override
protected FileObject findFile(FileName name, FileSystemOptions fileSystemOptions) throws FileSystemException {
// Check in the cache for the file system
//getContext().getFileSystemManager().resolveName... resolves the configured RootUri relative to the selected root (name.getRoot()). This calls cwd to the selectedRoot and operates from there with relatives urls towards the new root!
final FileName rootName = getContext().getFileSystemManager().resolveName(name.getRoot(), DefaultFileSystemConfigBuilder.getInstance().getRootURI(fileSystemOptions));
final FileSystem fs = getFileSystem(rootName, fileSystemOptions);
// Locate the file
// return fs.resolveFile(name.getPath());
return fs.resolveFile(name);
}
}
Came across this question because I was having the same issue with the following
ftp://user:pass#host//home/user/file.txt
becoming... (note the single slash after 'home')
ftp://user:pass#host/home/user/file.txt
I did this to solve the issue...
// Setup some options, add as many as you need
FileSystemOptions opts = new FileSystemOptions( );
// This line tells VFS to treat the URI as the absolute path and not relative
FtpsFileSystemConfigBuilder.getInstance( ).setUserDirIsRoot( opts, false );
// Retrieve the file from the remote FTP server
FileObject realFileObject = fileSystemManager.resolveFile( fileSystemUri, opts );
I hope this can help someone, if not then provide a reference for the next time this stumps me.

File being used by another process in a Windows Service with a StreamReader

I have searched numerous articles and tried several different ways of solving this issue.
Note that this process works fine in a Console app or a Windows app with the exact same code. So, there's nothing wrong with the logic. It's the way the Windows Service is processing these files that is somehow not letting subsequent files get through.
I tried reading a simple article to actually debug the service, but I don't have the "Attach To Process" selection under my Debug menu using Visual Studio 2010.
http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.100).aspx
I really need some help here, because my options have really run out.
Here is the simple scenario:
I have a FileSystemWatcher in the OnStart method that kicks off another method to process a file on my local machine. These are just simple txt files. When the first file is processed, everything is normal and I get the following in my Event log:
Data successfully inserted for file 20121212_AZM_Journey_MIS.txt
When I try and process subsequent files (exact same format, but a different name --- with the date), I get the following in my Event log:
The process cannot access the file 'C:\Projects\Data\VendingStats\20121213_AZM_Journey_MIS.txt' because it is being used by another process.
Note that the files are watched for in this same directory when created.
Here is my code in my Windows Service. Can someone please let me know how I can solve this issue? Note that e.FullPath evaluates to "C:\Projects\Data\VendingStats" on my local machine.
public partial class VendingStatsService : ServiceBase
{
public VendingStatsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
FileSystemWatcher Watcher = new FileSystemWatcher(#"C:\Projects\Data\VendingStats");
Watcher.EnableRaisingEvents = true;
Watcher.Created += new FileSystemEventHandler(**Watcher_Created**);
Watcher.Filter = "*.txt";
Watcher.IncludeSubdirectories = false;
}
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
try
{
using (TextReader tr = new StreamReader(e.FullPath))
{
// code here to insert data from file into a DB
}
Dispose();
}
catch (Exception ex)
{
EventLog.WriteEntry("VendorStats", "Error in the Main:" + "\r\n\r\n" + ex.Message + "\r\n\r\n" + ex.InnerException);
return;
}
}
public void Dispose()
{
GC.Collect();
}

JGit - Get all commits (PlotCommitList) that affected a file/path

Hy i am trying to get all the commits that include a specific directory or file of my repository.
I tried the folowing code :
public PlotCommitList getPlotCommits(String path){
System.out.println(path);
PlotCommitList<PlotLane> plotCommitList = new PlotCommitList<PlotLane>();
PlotWalk revWalk = new PlotWalk(repository);
try {
ObjectId rootId = repository.resolve("HEAD");
if (rootId != null) {
RevCommit root = revWalk.parseCommit(rootId);
revWalk.markStart(root);
revWalk.setTreeFilter(PathFilter.create(path));
plotCommitList.source(revWalk);
plotCommitList.fillTo(Integer.MAX_VALUE);
return plotCommitList;
}
} catch (AmbiguousObjectException ex) {
Logger.getLogger(GitRepository.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GitRepository.class.getName()).log(Level.SEVERE, null, ex);
}
return plotCommitList;
}
I don't get just the commits that affected that file. I get some "subLists" of the entire list but not just those commits that affected that file.
Maybe TreeFilter doesn't work how i think? I should use other way to get those commits?
I saw the log command has a path filter but i didn't tried it yet because it returns a RevCommit list and for my PlotCommitList i need a revwalk to use as a source. And also i think i cannot cast RevCommit to PlotCommit.
A guy had the same problem here (1st Answer with fileA and fileB issue) : Link - Click Here
You need to combine the PathFilter with an ANY_DIFF filter:
revWalk.setTreeFilter(
AndTreeFilter.create(PathFilter.create(path), TreeFilter.ANY_DIFF));
With only PathFilter I think what happens is that all commits are selected where the specified tree exists (e.g. all commits starting from the initial commit of that file).
Also see the API docs of setTreeFilter or how the LogCommand does it.

Resources