10 Replies Latest reply on Nov 22, 2017 4:33 PM by Martin Choma

    WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)

    Joe Schmoe Newbie

      Original post below the line - see my reply with detailed information where I narrowed this down to a role assignment issue. Thanks for reading!

       

      ----

       

      I'm at a loss for how to achieve this configuration!

       

      I had this working in WildFly 10 using Picketbox, but now in 11 I couldn't migrate it successfully to a working Elytron configuration. I followed the documentation for what I could find (migrate 2Way SSL over, setup EJB naming/invocation and DB authentication) but I think it's falling apart where it all couples together. I also feel like I'm missing how this all comes together.

       

      The following is my environment overview:

       

      - 1x domain controller

      - 2x host controllers each with a database they can connect to (they're not cross connected)

      - JavaFX client attempting to utilize EJB RMI from a remote workstation

       

      I would like this to work so that the client tries to authenticate/authorize with each host controller (incase one is down, or its respective database is down). Then I would like to use the role mappings from authorization to allow/deny access to my hosted business logic EJBs via annotations. I wanted to use remoting via 2 way SSL.

       

      Message was edited by: Joe Schmoe Updated to reflect troubleshooting results

        • 1. Re: WildFly 11 - Domain mode, EJB RMI, 2Way SSL and DB authentication
          Martin Choma Master

          This 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?

          1 of 1 people found this helpful
          • 2. Re: WildFly 11 - Domain mode, EJB RMI, 2Way SSL and DB authentication
            Joe Schmoe Newbie

            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
              Martin Choma Master

              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)
                Joe Schmoe Newbie

                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)
                  Joe Schmoe Newbie

                  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:

                   

                  1. End user submits credentials
                  2. Remoting via 2-way SSL is established between the desktop application and the host controllers (I have a domain with two of them)
                  3. WildFly naming is invoked to lookup the remote class/methods
                  4. Desktop app invokes remote methods
                  5. 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".
                  6. ... <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)
                    Martin Choma Master

                    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)
                      Joe Schmoe Newbie

                      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)
                        Martin Choma Master

                        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}])
                        

                         

                        [1] Migrate Legacy Security to Elytron Security - Latest WildFly Documentation - Project Documentation Editor

                        • 9. Re: WildFly 11 - Roles not assigned (Domain mode, EJB RMI, 2Way SSL, DB auth)
                          Joe Schmoe Newbie

                          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)
                            Martin Choma Master

                            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.

                             

                            [1] Migrate Legacy Security to Elytron Security - Latest WildFly Documentation - Project Documentation Editor