SSH support in Q2

92 views
Skip to first unread message

Alejandro Revilla

unread,
Sep 21, 2016, 1:56:29 PM9/21/16
to jPOS Users

As part of the upgrade from jline1 to jline3 I took the opportunity to migrate jPOS-EE’s SSH module (contributed by Victor) to jPOS, so that we have it handy in all installs.

Try q2 --help to see the new options.

Running q2 --ssh will start Q2 and an SSH server in the default port 2222.

You need to place your authorized_keys in a cfg directory and then you can:

ssh -p 2222 admin@localhost

to get a q2> prompt.

The server checks that the cfg/authorized_keys has read-only permissions and while this works alright in Unix, I wonder if it works in Windows (I’d appreciate some feedback - can you give it a try) ?


Luiz Felipph

unread,
Sep 22, 2016, 10:09:13 AM9/22/16
to jpos-...@googlegroups.com

Hello,

I downloaded a new jpos-master from github and ran gradlew installApp successfully

Inside build/install/jpos/cfg, I created the authorized_keys file and put my public key (ssh-rsa AAA(….) ), then ran bin/q2 —ssh and got this exception:

<log realm="sshd" at="2016-09-22T10:28:19.904">
  <warn>
    start
    <exception name="null">
    java.lang.NullPointerException
        at org.jpos.q2.ssh.SshService.checkAuthorizedKeys(SshService.java:100)
        at org.jpos.q2.ssh.SshService.startService(SshService.java:53)
        at org.jpos.q2.QBeanSupport.start(QBeanSupport.java:118)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at sun.reflect.misc.Trampoline.invoke(Unknown Source)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
        at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(Unknown Source)
        at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(Unknown Source)
        at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(Unknown Source)
        at com.sun.jmx.mbeanserver.PerInterface.invoke(Unknown Source)
        at com.sun.jmx.mbeanserver.MBeanSupport.invoke(Unknown Source)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(Unknown Source)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(Unknown Source)
        at org.jpos.q2.QFactory.startQBean(QFactory.java:187)
        at org.jpos.q2.Q2.start(Q2.java:569)
        at org.jpos.q2.Q2.deploy(Q2.java:353)
        at org.jpos.q2.Q2.run(Q2.java:220)
        at java.lang.Thread.run(Unknown Source)
    </exception>
  </warn>
</log>

It’s checking permissions using POSIX attributes, so I put some code to detect OS(if windows, just return;) and rebuild.

Now the ssh server came up.

When I tried to connect, I got another exception:

<log realm="sshd" at="2016-09-22T10:58:04.367">
  <error>
    <exception name="null">
    java.lang.ArrayIndexOutOfBoundsException
        at java.lang.System.arraycopy(Native Method)
        at org.jpos.q2.ssh.AuthorizedKeysFileBasedPKA$AuthorizedKeysDecoder.decodeBigInt(AuthorizedKeysFileBasedPKA.java:139)
        at org.jpos.q2.ssh.AuthorizedKeysFileBasedPKA$AuthorizedKeysDecoder.decodePublicKey(AuthorizedKeysFileBasedPKA.java:102)
        at org.jpos.q2.ssh.AuthorizedKeysFileBasedPKA.parseAuthorizedKeys(AuthorizedKeysFileBasedPKA.java:60)
        at org.jpos.q2.ssh.AbstractPKA.authenticate(AbstractPKA.java:39)
        at org.apache.sshd.server.auth.UserAuthPublicKey.doAuth(UserAuthPublicKey.java:72)
        at org.apache.sshd.server.auth.AbstractUserAuth.auth(AbstractUserAuth.java:49)
        at org.apache.sshd.server.session.ServerUserAuthService.process(ServerUserAuthService.java:145)
        at org.apache.sshd.common.session.AbstractSession.doHandleMessage(AbstractSession.java:431)
        at org.apache.sshd.common.session.AbstractSession.handleMessage(AbstractSession.java:326)
        at org.apache.sshd.common.session.AbstractSession.decode(AbstractSession.java:780)
        at org.apache.sshd.common.session.AbstractSession.messageReceived(AbstractSession.java:308)
        at org.apache.sshd.common.AbstractSessionIoHandler.messageReceived(AbstractSessionIoHandler.java:54)
        at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:184)
        at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:170)
        at org.apache.sshd.common.io.nio2.Nio2CompletionHandler$1.run(Nio2CompletionHandler.java:32)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:30)
        at sun.nio.ch.Invoker.invokeUnchecked(Unknown Source)
        at sun.nio.ch.Invoker$2.run(Unknown Source)
        at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
    </exception>
  </error>
</log>

Can you point me a direction to make work?

Thanks,

Felipph

--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: sa...@jpos.org
 
Join us in IRC at http://webchat.freenode.net/?channels=jpos
 
You received this message because you are subscribed to the "jPOS Users" group.
Please see http://jpos.org/wiki/JPOS_Mailing_List_Readme_first
To post to this group, send email to jpos-...@googlegroups.com
To unsubscribe, send email to jpos-users+unsubscribe@googlegroups.com
For more options, visit this group at http://groups.google.com/group/jpos-users
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jpos-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/CAAgSK%3Dk8L1aoKwpWiqy6gEK18vgjcbdSx8hHW%2ByQBN2eq7xtvA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Alejandro Revilla

unread,
Sep 22, 2016, 1:19:13 PM9/22/16
to jPOS Users

It’s checking permissions using POSIX attributes, so I put some code to detect OS(if windows, just return;) and rebuild.

Can you share the code you’ve used, perhaps we can add it too.

As for the ArrayIndexOutOfBoundsException
​, what key type have you used? I tested it with ssh-dss.

​Are you using admin@localhost as the user?



Luiz Felipph

unread,
Sep 22, 2016, 2:17:24 PM9/22/16
to jpos-...@googlegroups.com

> Can you share the code you’ve used, perhaps we can add it too.


Of course:

```
    private void checkAuthorizedKeys (String s) throws IOException {
String OS = System.getProperty("os.name").toLowerCase();
if((OS.indexOf("win") >= 0)){
log.info("Windows Detected, ignoring file permissions check: "+OS);
return;
}
        Path file = Paths.get(s);
        PosixFileAttributes attrs =
          Files.getFileAttributeView(file, PosixFileAttributeView.class)
          .readAttributes();
        Set<PosixFilePermission> perms =  attrs.permissions();
        if (perms.size() != 1 || !perms.contains(PosixFilePermission.OWNER_READ))
            throw new IllegalArgumentException(
              String.format ("Invalid permissions '%s' for file '%s'", PosixFilePermissions.toString(perms), s)
            );
    }

```

> As for the ArrayIndexOutOfBoundsException
> ​, what key type have you used? I tested it with ssh-dss.

I generated with `puttygen` (never done before in Windows), picked SSH2-RSA option, 2049bits.

The key start with: `ssh-rsa AAAA....`

>​Are you using admin@localhost as the user?


No, just `admin`:


Putty output:
```
Using username "admin".
Server refused our key

```

You pointed `admin@localhost` made me look my keys on my server, so I realized that `puttygen` don't append username at end of line, so I picked a working one from server and put on `authorized_keys` file(is a `ssh-rsa` too). Behold:



And a nice and clear log on running jpos.



Felipph

Luiz Felipph

unread,
Sep 22, 2016, 2:19:03 PM9/22/16
to jpos-...@googlegroups.com
Behold:

Cheers!


Felipph

Alejandro Revilla

unread,
Sep 22, 2016, 2:43:41 PM9/22/16
to jPOS Users

Awesome, thank you for the code snipped, just applied it in https://github.com/jpos/jPOS/commit/89f40dbd0c663d5f3be3b9a6ab4d1cbb9c43e23c
(I’ve also forced a nightly build so a gradle --refresh-dependencies should get you the new version.

Good catch on the key username, good to know it’s working now.




Luiz Felipph

unread,
Sep 22, 2016, 3:11:20 PM9/22/16
to jpos-...@googlegroups.com
Late I'll try make work with putty client and send a step-by-step.

Thank you!

Felipph

Alejandro Revilla

unread,
Sep 22, 2016, 3:12:34 PM9/22/16
to jPOS Users
Perfect. Perhaps you can review the jPOS exception with the public key provided by Putty, may be we can catch it on the jPOS side so there's no need to tweak it manually adding the username.

Kind regards



Luiz Felipph

unread,
Sep 22, 2016, 5:53:55 PM9/22/16
to jpos-...@googlegroups.com
Hi,

I was wrong pointing the last element of a auth key as the username. It's just a comment, can be anything..

Well, I think I pasted a incomplete key to authorized_keys file. Now works with putty too.

Step by step:

Puttygen to generate public and private key:


Can leave default, just click "Generate". 

Move the mouse over blank area to provide some randomness, then wait key generation to complete.




Copy the highlighted text to authorized_keys and SAVE the `PRIVATE KEY`.

In putty provide the host and port. In the left panel, go to Connection -> Data. fill Auto-login username with "admin"


In Connection -> SSH -> Auth, browse to your generated PRIVATE KEY:



Click in "Open".


Voilá!

Felipph

Alejandro Revilla

unread,
Sep 22, 2016, 6:15:50 PM9/22/16
to jPOS Users

Awesome. Thank you.

Now it’s time to create your own commands, that’s the idea behind the CLI, your application can create commands relevant to its business logic, like we do in jPOS-EE with the ADDUSER, ADDROLE, etc.

Creating commands is extremely simple, they just have to implement the CLICommand interface.




Luiz Felipph

unread,
Sep 22, 2016, 7:13:21 PM9/22/16
to jpos-...@googlegroups.com
I'm thinking is a set of file management, focused in deploy dir...

I'll start with a `lsdeploy` to list all deployed configs.

What you think?

Thanks

Felipph

Alejandro Revilla

unread,
Sep 22, 2016, 7:23:02 PM9/22/16
to jPOS Users
That could be useful, an 'enable' and 'disable' command (that would just rename XMLs from .xml to .off and back to .xml) could be useful. Then there's a lot of fun that one can do against the JMX MBeanServer.

I made some changes to the CLI interface so that one can implement commands that actually are not interactive with the idea of sending commands over the space. Add the ReplicatedSpace to the picture and one could control a bunch of Q2s from a single terminal. Could be great, huh?




Reply all
Reply to author
Forward
0 new messages