-
1. Re: WildFly 11 - Domain mode, EJB RMI, 2Way SSL and DB authentication
mchoma Nov 16, 2017 4:28 PM (in response to spacegoat)1 of 1 people found this helpfulThis is too general to help
For beginning what is your exception you get?
What you can say works?
- Does 2-wayssl works? You use it for authentication?
- Does retrieving roles from DB works? You use DB for storing roles?
-
2. Re: WildFly 11 - Domain mode, EJB RMI, 2Way SSL and DB authentication
spacegoat Nov 17, 2017 4:45 PM (in response to mchoma)Right, I figured as much. I guess I was hoping for a quick overview of how it all flows, but I guess I should have asked for that.
I've made some progress since I posted this originally. Here's where I'm at:
- 2 way SSL seems to be working
- EJB RMI is working where the EJB method perm is "@PermitAll"
- The roles aren't being retrieved (I verified this by reviewing database query logs and the database isn't even being queried!)
I made the aforementioned progress by just creating new test configurations and following the documentation as much as possible.
So I made a table and added a user:
CREATE TABLE wildfly_users (username TEXT NOT NULL UNIQUE PRIMARY KEY, password TEXT, roles TEXT) INSERT INTO wildfly_users (username, password, roles) VALUES ('test', 'test123', 'developer')
Then added a test jdbc realm (the datasource was already present and tested successfully):
/profile=ha/subsystem=elytron/jdbc-realm=test-jdbc-realm:add(principal-query=[{sql=
"SELECT password,roles FROM wildfly_users WHERE username=?"
,data-source=TestDS,clear-password-mapper={password-index=
1
},attribute-mapping=[{index=
2
,to=groups}]}])
Then added a test security domain:
/profile=ha
/subsystem=elytron/security-domain=test-secdomain:add(realms=[{realm=test-jdbc-realm,role-decoder=groups-to-roles}],default
-realm=test-jdbc-realm,permission-mapper=
default
-permission-mapper)
Then added a test http auth factory:
/profile=ha
/subsystem=elytron/http-authentication-factory=test-http-auth-factory:add(http-server-mechanism-factory=global,security-domain=test-secdomain,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=test-secdomain}]}])Then added a test app security domain to Undertow:
/profile=ha
/subsystem=undertow/application-security-domain=test-app-domain:add(http-authentication-factory=test-http-auth-factory)Beyond this, there's other configurations that are probably important to mention:
- EJB3 subsystem has an Application Security Domains Mapping (Name is "test-elytron-security-domain", Elytron Security Domain is "test-secdomain")
- My served EJB uses the annotation "@SecurityDomain("test-elytron-security-domain")" to reference roles via "@RolesAllowed" annotation
The JavaFX client uses the following programmatic approach to EJB RMI:
AuthenticationConfiguration authcfg = AuthenticationConfiguration .empty() .useName(identity.getUsername()) // identity is just an object I created to hold uname/pw that caller submits .usePassword(identity.getPassword()); AuthenticationContext ctx = AuthenticationContext.empty().with(MatchRule.ALL, authcfg); Callable<Void> callable = () -> { Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory"); p.put(Context.PROVIDER_URL, "remote+https://" + MainApp.HOST_CONTROLLER_HC01 + ":" + MainApp.SERVICE_PORT); //ip of HC and port 8443 InitialContext c = new InitialContext(p); infoBean = (InfoManagerRemote)c.lookup(getInfoManagerLookupStr()); System.out.println("------------- Invoking bean (Any Role) -------------"); List<String> roles = infoBean.getRoles(); String rolestr = "Assigned roles: "; for(String r:roles) { rolestr += r; } System.out.println(rolestr); //this current results in printing out "none" because the EJB uses the @Resource SessionContext to check if the context isCallerInRole method for all possible roles and adds "none" to the returned list if none were found System.out.println("------------- Invoking bean (developer Role)-------------"); System.out.println("version: " + infoBean.getVersion()); //this results in an error because it uses "@RolesAllowed("developer")" annotation... see below for that error return null; }; try { ctx.runCallable(callable); } catch(Exception e) { e.printStackTrace(); }
The error that results from line 26 via the client running the above is:
javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public abstract java.lang.String com.test.ejbserver.iface.InfoManagerRemote.getVersion() of bean: InfoManager is not allowed
at org.jboss.as.ejb3.security.RolesAllowedInterceptor.processInvocation(RolesAllowedInterceptor.java:67)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.security.SecurityDomainInterceptor.processInvocation(SecurityDomainInterceptor.java:44)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.deployment.processors.StartupAwaitInterceptor.processInvocation(StartupAwaitInterceptor.java:22)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.deployment.processors.EjbSuspendInterceptor.processInvocation(EjbSuspendInterceptor.java:57)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:67)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:60)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:438)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:609)
at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:57)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:53)
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:198)
at org.wildfly.security.auth.server.SecurityIdentity.runAsFunctionEx(SecurityIdentity.java:380)
at org.jboss.as.ejb3.remote.AssociationImpl.invokeWithIdentity(AssociationImpl.java:535)
at org.jboss.as.ejb3.remote.AssociationImpl.invokeMethod(AssociationImpl.java:530)
at org.jboss.as.ejb3.remote.AssociationImpl.lambda$receiveInvocationRequest$0(AssociationImpl.java:193)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Suppressed: org.jboss.ejb.client.RequestSendFailedException: java.net.ConnectException: Connection refused: no further information
at org.jboss.ejb.protocol.remote.RemoteEJBReceiver$1.handleFailed(RemoteEJBReceiver.java:101)
at org.jboss.ejb.protocol.remote.RemoteEJBReceiver$1.handleFailed(RemoteEJBReceiver.java:74)
at org.xnio.IoFuture$HandlingNotifier.notify(IoFuture.java:215)
at org.xnio.AbstractIoFuture$NotifierRunnable.run(AbstractIoFuture.java:720)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:926)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.net.ConnectException: Connection refused: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
at org.xnio.nio.WorkerThread$ConnectHandle.handleReady(WorkerThread.java:327)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
at ...asynchronous invocation...(Unknown Source)
at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:570)
at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:536)
at org.jboss.remoting3.ConnectionInfo$None.getConnection(ConnectionInfo.java:82)
at org.jboss.remoting3.ConnectionInfo.getConnection(ConnectionInfo.java:55)
at org.jboss.remoting3.EndpointImpl.doGetConnection(EndpointImpl.java:487)
at org.jboss.remoting3.EndpointImpl.getConnectedIdentity(EndpointImpl.java:433)
at org.jboss.remoting3.UncloseableEndpoint.getConnectedIdentity(UncloseableEndpoint.java:51)
at org.jboss.ejb.protocol.remote.RemotingEJBDiscoveryProvider.getConnectedIdentityUsingClusterEffective(RemotingEJBDiscoveryProvider.java:311)
at org.jboss.ejb.protocol.remote.RemoteEJBReceiver.lambda$getConnection$1(RemoteEJBReceiver.java:182)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.ejb.protocol.remote.RemoteEJBReceiver.getConnection(RemoteEJBReceiver.java:181)
at org.jboss.ejb.protocol.remote.RemoteEJBReceiver.processInvocation(RemoteEJBReceiver.java:128)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:454)
at org.jboss.ejb.protocol.remote.RemotingEJBClientInterceptor.handleInvocation(RemotingEJBClientInterceptor.java:51)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:466)
at org.jboss.ejb.client.TransactionPostDiscoveryInterceptor.handleInvocation(TransactionPostDiscoveryInterceptor.java:79)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:466)
at org.jboss.ejb.client.DiscoveryEJBClientInterceptor.handleInvocation(DiscoveryEJBClientInterceptor.java:95)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:466)
at org.jboss.ejb.client.NamingEJBClientInterceptor.handleInvocation(NamingEJBClientInterceptor.java:63)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:466)
at org.jboss.ejb.client.TransactionInterceptor.handleInvocation(TransactionInterceptor.java:165)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:466)
at org.wildfly.common.context.Contextual.runExConsumer(Contextual.java:203)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequestInitial(EJBClientInvocationContext.java:302)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:161)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:100)
at com.sun.proxy.$Proxy7.getVersion(Unknown Source)
at com.test.rmiclient.EJBClient.lambda$authenticate$1(EJBClient.java:155)
at org.wildfly.common.context.Contextual.runCallable(Contextual.java:127)
at com.test.rmiclient.EJBClient.authenticate(EJBClient.java:172)
at com.test.rmiclient.BackgroundServiceEngine.run(BackgroundServiceEngine.java:137)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
... 3 more
There may be some relevant WildFly configurations I missed while writing this, LMK if there's more you need! Thanks!
-
3. Re: WildFly 11 - Domain mode, EJB RMI, 2Way SSL and DB authentication
mchoma Nov 20, 2017 3:48 AM (in response to spacegoat)If you don't see any database queries (even no authentication query), then it seems to me you are missing in your configuration something like:
/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory,value=test-sasl-auth-factory)
Could you turn logging of security stuff on:
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level, value=ALL) /subsystem=logging/logger=org.jboss.security:add(level=ALL) /subsystem=logging/logger=org.jboss.as.security:add(level=ALL) /subsystem=logging/logger=org.jboss.as.domain.management.security:add(level=ALL) /subsystem=logging/logger=org.wildfly.security:add(level=ALL) /subsystem=logging/logger=org.wildfly.elytron:add(level=ALL) # With Remoting /subsystem=logging/logger=org.jboss.sasl:add(level=ALL) /subsystem=logging/logger=org.jboss.as.ejb3:add(level=ALL) /subsystem=logging/logger=org.jboss.as.remoting:add(level=ALL) /subsystem=logging/logger=org.jboss.remoting3:add(level=ALL) /subsystem=logging/logger=org.jboss.remoting:add(level=ALL) /subsystem=logging/logger=org.jboss.naming.remote:add(level=ALL)
Also I wonder how do you specify client certificate?
-
4. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
spacegoat Nov 21, 2017 9:04 AM (in response to mchoma)One problem might be that I don't have a SASL authentication factory defined. I was using HTTP (see: "test-http-auth-factory" above). It looks like defining a SASL auth factory requires several parameters for "mechanism configuration" and I don't see anything about it in the WildFly documentation - how would I define this to authenticate/authorize via my database?
How I specify the client cert in the client? I set the system properties "javax.net.ssl.keyStore", "javax.net.ssl.trustStore", "javax.net.ssl.keyStorePassword", "javax.net.ssl.trustStorePassword".
Like so:
System.setProperty("javax.net.ssl.keyStore", MainApp.KEYSTORE); System.setProperty("javax.net.ssl.trustStore", MainApp.TRUSTSTORE); System.setProperty("javax.net.ssl.keyStorePassword", "keystorepw"); System.setProperty("javax.net.ssl.trustStorePassword, "truststorepw");
-
5. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
spacegoat Nov 21, 2017 10:02 AM (in response to spacegoat)It seems the problem I'm facing is a misconfiguration somewhere that should result in the database being queried for user/pass/roles after the end user submits credentials via the desktop application.
As I understand it (and I admit it's probably a misunderstanding, because it's all roughly derived from what I read in the WildFly documentation) the flow of authentication/authorization is this:
- End user submits credentials
- Remoting via 2-way SSL is established between the desktop application and the host controllers (I have a domain with two of them)
- WildFly naming is invoked to lookup the remote class/methods
- Desktop app invokes remote methods
- If remote method permits specific roles, the end user's credentials are provided to EJB3 subsystem (Application Security Domains Mapping), which references the Elytron security domain, which references the JDBC realm, which includes a SQL query via the datastore to retrieve "password,roles" mapping (clear-password-mapper password-index=1) and (attribute to="groups" index="2"), finally role decoder "groups-to-roles" translates the "groups" to "roles".
- ... <magic>
I assume 6 is some behind the scenes code that applies the roles to the principal so that the desktop app calling a RBAC method would check those roles (also assuming the credentials submitted by the user were correct and the database included roles for that user).
In any case, what does work is accessing remote methods where the "@PermitAll" annotation is applied. I used tcpdump to capture packets during the communication and SSL appears to be functioning correctly as everything is encrypted. So... what am I missing to make the Elytron system query my database?
-
6. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
mchoma Nov 21, 2017 11:42 AM (in response to spacegoat)I think
- 2-way SSL is established first of all.
- Then client should be authenticated with provided username password
Still I think your problem is you have to configure sasl authentication factory. Compared to http authentication factory use PLAIN SASL mechanism instead of BASIC http mechanism. Look at [1] and for reference [2].
Also turn logging to TRACE
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level, value=ALL) /subsystem=logging/logger=org.wildfly.security:add(level=ALL) /subsystem=logging/logger=org.wildfly.elytron:add(level=ALL) # With Remoting /subsystem=logging/logger=org.jboss.sasl:add(level=ALL) /subsystem=logging/logger=org.jboss.as.ejb3:add(level=ALL) /subsystem=logging/logger=org.jboss.as.remoting:add(level=ALL) /subsystem=logging/logger=org.jboss.remoting3:add(level=ALL) /subsystem=logging/logger=org.jboss.remoting:add(level=ALL) /subsystem=logging/logger=org.jboss.naming.remote:add(level=ALL)
[1] Getting started with EJBs and Elytron Part 1: Securing EJBs and invoking them from remote clients
[2] WildFly Elytron Security - Latest WildFly Documentation - Project Documentation Editor
-
7. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
spacegoat Nov 21, 2017 1:20 PM (in response to mchoma)Where can I find a list of available SASL mechanisms? I don't see in the documentation how to configure a PLAIN SASL mechanism.
-
8. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
mchoma Nov 22, 2017 1:53 AM (in response to spacegoat)Here is one example
./subsystem=elytron/sasl-authentication-factory=application-security-sasl:add(sasl-server-factory=elytron, security-domain=application-security, mechanism-configurations=[{mechanism-name=PLAIN}])
-
9. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
spacegoat Nov 22, 2017 9:46 AM (in response to mchoma)Ok, I added that and now when I try to authenticate with the client I get an exception. I think this is the notable part:
Caused by: javax.security.sasl.SaslException: Authentication failed: none of the mechanisms presented by the server (PLAIN) are supported
I tried adding the following to the client's AuthenticationConfiguration, but I still get the same error:
.setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("PLAIN"))
-
10. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
mchoma Nov 22, 2017 4:33 PM (in response to spacegoat)Bigger part of log would be useful. Do you have remoting on TRACE level? Which mechanisms does client expose?
Compare your client code with [1], but I don't see problem on first sight.