Skip navigation

My previous blog post described how to secure EJBs deployed to WildFly 11 using Elytron and how to invoke them from a standalone remote client. This post describes how to invoke EJBs deployed on a WildFly server instance from another WildFly server instance using Elytron. We’ll refer to the server instance on which the EJBs are deployed as the destination server and we’ll refer to the server instance from which the EJB invocation takes place as the client server.

 

Configuring the client server

As in previous WildFly releases, to be able to invoke EJBs deployed on the destination server, you can add configuration to the Remoting subsystem on the client server to specify the information needed for the outbound connection to the destination server. In WildFly 11, a remote outbound connection can now be specified by two things: an Elytron authentication context and an outbound socket binding.

 

Creating an authentication context

The authentication context provides all of the security information that’s needed to connect to the destination server. For example, if you would like to use a user named “ejbUser” with password “secret” when connecting to the destination server, the following CLI commands can be used to create an appropriate authentication context:

 

/subsystem=elytron/authentication-configuration=ejb-auth-config:add(authentication-name=ejbUser, credential-reference={clear-text="secret"})
/subsystem=elytron/authentication-context=ejb-auth-context:add(match-rules=[{authentication-configuration=ejb-auth-config}])

 

The above commands result in the following configuration in the Elytron subsystem on the client server:

 

<subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
...
    <authentication-client>
        <authentication-configuration name="ejb-auth-config" authentication-name="ejbUser">
            <credential-reference clear-text="secret"/>
        </authentication-configuration>
        <authentication-context name="ejb-auth-context">
            <match-rule authentication-configuration="ejb-auth-config"/>
        </authentication-context>
    </authentication-client>
...
</subsystem>

 

Creating an outbound socket binding

As before, the outbound socket binding points to the destination server’s host and port for the connection. For example, if the destination server’s host is 10.20.30.40 and its port is 8080, the following CLI command can be used to create an outbound socket binding:

 

/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-ejb:add(host=10.20.30.40, port=8080)

 

Creating a remote outbound connection

Finally, you can create a remote-outbound-connection that references your newly created authentication context and outbound socket binding as follows:

 

/subsystem=remoting/remote-outbound-connection=remote-ejb-connection:add(authentication-context=ejb-auth-context, outbound-socket-binding-ref=remote-ejb)

 

The above command results in the following configuration in the Remoting subsystem on the client server:

 

<subsystem xmlns="urn:jboss:domain:remoting:4.0">
...
    <outbound-connections>
        <remote-outbound-connection name="remote-ejb-connection" outbound-socket-binding-ref="remote-ejb" authentication-context="ejb-auth-context"/>
    </outbound-connections>
...
</subsystem>

 

Invoking EJBs from a client server

As in my previous post, update any client code that looks up an EJB deployed on the destination server using JNDI to make use of the new Naming Client library. As an example, here’s a simple code snippet that could be used to look up an EJB deployed on the destination server using the new WildFlyInitialContextFactory:

 

Code snippet

// create an InitialContext
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
InitialContext context = new InitialContext(properties);

// look up an EJB and invoke one of its methods
RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup(
    "ejb:/ejb-remote-server-side//CalculatorBean!" + RemoteCalculator.class.getName());
int sum = statelessRemoteCalculator.add(101, 202);

 

Summary

This blog post has shown how to invoke EJBs deployed on a WildFly server instance from another WildFly server instance using Elytron. If you’d like to see a more advanced example application that shows how to propagate the security identity of an EJB deployed on the client server to an EJB deployed on the destination server, take a look at the ejb-security-context-propagation quickstart.

This blog post describes how to secure EJBs deployed to WildFly 11 using Elytron and how to invoke them from a standalone remote client. If you haven’t already, take a look at the Elytron documentation  on how to create security realms, security domains, and authentication factories. In this post, we’ll make use of a security domain (“ApplicationDomain”) and a SASL authentication factory (“application-sasl-authentication”) that are already defined in the default WildFly configuration file in the Elytron subsystem configuration.

 

To start the server, use the following command:

$WILDFLY_HOME/bin/standalone.sh

 

To connect to the running server to execute CLI commands, use:

$WILDFLY_HOME/bin/jboss-cli.sh --connect

 

Securing EJBs with Elytron

By default, security for EJBs deployed to WildFly 11 will continue to be handled by the legacy security subsystem. To indicate that security for an EJB should be handled by the Elytron subsystem instead, you need to add some configuration to the EJB subsystem to map the security domain name that’s configured for an EJB in a deployment to the Elytron security domain that you would like to use. For example, if “other” is the security domain name that is configured for an EJB (e.g., via a @SecurityDomain annotation or in a jboss-ejb3.xml deployment descriptor) and “ApplicationDomain” is the Elytron security domain that you would like to use, the following CLI command can be used to add the required mapping:

 

/subsystem=ejb3/application-security-domain=other:add(security-domain=ApplicationDomain)

 

The above command results in the following configuration in the EJB subsystem:

 

<subsystem xmlns="urn:jboss:domain:ejb3:5.0">
...
    <application-security-domains>
        <application-security-domain name="other" security-domain="ApplicationDomain"/>
    </application-security-domains>
...
</subsystem>

 

Notice that an application-security-domain mapping has two main attributes:

  • name - the name of the security domain as specified in a deployment
  • security-domain - a reference to the Elytron security domain that should be used

 

Next, update the http-remoting-connector in the Remoting subsystem to reference the SASL authentication factory that is backed by your Elytron security domain:

 

/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory, value=application-sasl-authentication)
/subsystem=remoting/http-connector=http-remoting-connector:undefine-attribute(name=security-realm)

 

The latter command above just clears the legacy security-realm attribute since it is no longer needed.

 

Finally, reload the server using the :reload command.

 

Invoking EJBs from a standalone remote client

Prior to WildFly 11, many WildFly client libraries used different configuration strategies. WildFly 11 introduces a new wildfly-config.xml file which unifies all client configuration in a single place. EJBs deployed to WildFly 11 can still be invoked using existing standalone remote clients that make use of the legacy naming and EJB client libraries from previous WildFly releases. This section walks through an example of how to migrate a remote client to make use of the new WildFly Naming Client and EJB Client libraries.

 

Consider a legacy client application that has a jboss-ejb-client.properties configuration file and looks up an EJB deployed on a remote server using JNDI, as follows:

 

jboss-ejb-client.properties

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=10.20.30.40
remote.connection.default.port=8080
remote.connection.default.username=bob
remote.connection.default.password=secret

 

Code snippet

// create an InitialContext
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
InitialContext context = new InitialContext(properties);

// look up an EJB and invoke one of its methods
RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup(
    "ejb:/ejb-remote-server-side//CalculatorBean!" + RemoteCalculator.class.getName());
int sum = statelessRemoteCalculator.add(101, 202);

 

To migrate this example to the new Naming Client and EJB Client libraries, the first thing you can do is remove the jboss-ejb-client.properties file since it is no longer needed. Instead, all of the information that’s needed to connect to the remote server can be specified in a wildfly-config.xml file in the client application’s META-INF directory, as follows:

 

wildfly-config.xml

<configuration>
    <authentication-client xmlns="urn:elytron:1.0">
        <authentication-rules>
            <rule use-configuration="default"/>
        </authentication-rules>
        <authentication-configurations>
            <configuration name="default">
                <set-user-name name="bob"/>
                <credentials>
                    <clear-password password="secret"/>
                </credentials>
            </configuration>
        </authentication-configurations>
    </authentication-client>
    <jboss-ejb-client xmlns="urn:jboss:wildfly-client-ejb:3.0">
        <connections>
            <connection uri="remote+http://10.20.30.40:8080" />
        </connections>
    </jboss-ejb-client>
</configuration>

 

To learn more about the contents of the above file, take a look at the Elytron Client documentation.

 

Next, update the client code that sets up the InitialContext to make use of the new WildFlyInitialContextFactory from the new Naming Client library:

 

Code snippet

// create an InitialContext
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
InitialContext context = new InitialContext(properties);

// look up an EJB and invoke one of its methods (this part is the same as before)
RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup(
    "ejb:/ejb-remote-server-side//CalculatorBean!" + RemoteCalculator.class.getName());
int sum = statelessRemoteCalculator.add(101, 202);

 

Additional client migration examples can also be found here.

 

Summary

This blog post has shown how to secure EJBs deployed to WildFly 11 with Elytron and how to invoke them from a standalone remote client using the new Naming Client and EJB Client libraries. If you’d like to see a complete example application that pulls everything described here together, take a look at the ejb-security quickstart. My next post will cover EJB invocations from a remote server using Elytron.