Skip navigation
2017

Some SASL mechanisms support channel binding to external secure channels like TLS. The name of a SASL mechanism tells us if channel binding is supported. In particular, SASL mechanisms that support the optional use of channel binding have two SASL mechanism names - one name that includes the “-PLUS” suffix, which implies that channel binding is supported, and one name without the “-PLUS” suffix, which implies that channel binding is not supported (e.g., GS2-KRB5 and GS2-KRB5-PLUS, SCRAM-SHA-256 and SCRAM-SHA-256-PLUS, etc.). Whether or not channel binding is used is determined during SASL mechanism negotiation.

 

This blog post is going to show the server and client configuration needed to connect to the JBoss CLI using the SCRAM-SHA-256-PLUS mechanism, one of the SASL PLUS mechanisms provided by Elytron.

 

Prerequisite configuration

 

First, add a management user for the server - this is the user that we’re going to use later on when attempting to connect to the CLI. For this example, we’re going to create a filesystem-based identity store and add a user named “bob” with password “pAssw0rd” using the following CLI commands:

 

/subsystem=elytron/filesystem-realm=exampleRealm:add(path=fs-realm-users,relative-to=jboss.server.config.dir)
/subsystem=elytron/filesystem-realm=exampleRealm:add-identity(identity=bob)
/subsystem=elytron/filesystem-realm=exampleRealm:set-password(identity=bob,clear={password=pAssw0rd})

 

Now, we’re going to add the filesystem-realm that we just created to the “ManagementDomain” security domain that is already defined in the default Elytron subsystem configuration and we’re going to make this the default security realm for this security domain:

 

/subsystem=elytron/security-domain=ManagementDomain:list-add(name=realms, value={realm=exampleRealm})
/subsystem=elytron/security-domain=ManagementDomain:write-attribute(name=default-realm, value=exampleRealm)

 

Next, use the following commands to secure the management interface using Elytron:

 

/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade,value={enabled=true, sasl-authentication-factory=management-sasl-authentication})
/core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory,value=management-http-authentication)
/core-service=management/management-interface=http-interface:undefine-attribute(name=security-realm)

 

Finally, generate a server keystore and a client truststore using the keytool command, as shown below. We’re going to use these to enable one-way SSL/TLS for the management interface.

 

Generate the server keystore:

keytool -genkeypair -alias localhost -keyalg RSA -keysize 1024 -validity 365 -keystore server.keystore.jks -dname "CN=localhost" -keypass secret -storepass secret

 

Export the server certificate:

keytool -exportcert  -keystore server.keystore.jks -alias localhost -keypass secret -storepass secret -file server.cer

 

Import the server certificate into the client’s truststore:

keytool -importcert -keystore client.truststore.jks -storepass secret -alias localhost -trustcacerts -file server.cer

 

Now we’re ready to proceed with the server and client configuration needed to use the SCRAM-SHA-256-PLUS mechanism.

 

Configuring the server

 

First, configure a key-store, key-manager, and server-ssl-context in the Elytron subsystem using the server keystore that we just created (the following commands assume the server.keystore.jks file is located in the $WILDFLY_HOME/standalone/configuration directory):

 

/subsystem=elytron/key-store=exampleKS:add(path=server.keystore.jks, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, type=JKS)
/subsystem=elytron/key-manager=exampleKM:add(key-store=exampleKS, credential-reference={clear-text=secret})  
/subsystem=elytron/server-ssl-context=exampleSSC:add(key-manager=exampleKM, protocols=["TLSv1.2"])

 

Next, enable HTTPS on the management interface using the newly created server-ssl-context:

 

/core-service=management/management-interface=http-interface:write-attribute(name=ssl-context, value=exampleSSC)
/core-service=management/management-interface=http-interface:write-attribute(name=secure-socket-binding, value=management-https)

 

Now, update the “management-sasl-authentication” SASL authentication factory to also offer the SCRAM-SHA-256-PLUS mechanism:

 

/subsystem=elytron/sasl-authentication-factory=management-sasl-authentication:list-add(name=mechanism-configurations, value={mechanism-name=SCRAM-SHA-256-PLUS})

 

Finally, reload the server using the :reload command.

 

Configuring the client

 

We can use a wildfly-config.xml file to provide the information that’s needed to connect to the CLI:

 

<configuration>
    <authentication-client xmlns="urn:elytron:1.0">
        <authentication-rules>
            <rule use-configuration="auth-config"/>
        </authentication-rules>
        <authentication-configurations>
            <configuration name="auth-config">
                <sasl-mechanism-selector selector="SCRAM-SHA-256-PLUS"/>
                <set-user-name name="bob"/>  
                <credentials>  
                    <clear-password password="pAssw0rd"/>  
                </credentials> 
            </configuration>
        </authentication-configurations>
        <key-stores>
            <key-store name="truststore" type="JKS">
                <file name="/path/to/client.truststore.jks" />
                <key-store-clear-password password="secret" />
            </key-store>
        </key-stores>
        <ssl-contexts>
            <ssl-context name="client-cli-context">
                <trust-store key-store-name="truststore" />
            </ssl-context>
        </ssl-contexts>
        <ssl-context-rules>
            <rule use-ssl-context="client-cli-context" />
        </ssl-context-rules>
    </authentication-client>
</configuration>

 

Notice that the wildfly-config.xml file specifies that the SCRAM-SHA-256-PLUS mechanism should be used and the username and password that should be used when attempting to connect to the CLI. It also configures an ssl-context using the client truststore that we created earlier.

 

Now, we just need to specify this wildfly-config.xml file when connecting to the CLI. The following command connects to the CLI and executes the :whoami command.

 

$WILDFLY_HOME/jboss-cli.sh -c --controller=remote+https://127.0.0.1:9993 -Dwildfly.config.url=/path/to/wildfly-config.xml :whoami

 

You should see the following output, which indicates that we’ve successfully connected to the CLI using the SCRAM-SHA-256-PLUS mechanism.

 

{
    "outcome" => "success",
    "result" => {"identity" => {"username" => "bob"}}
}

 

Summary

 

This blog post has shown how to set up one-way SSL/TLS for the management interface and how to then use a SASL mechanism that supports channel binding to connect to the CLI.

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-outbound-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.