JBoss Community Archive (Read Only)

GateIn Portal 3.8

Securing WSRP

Securing WSRP

There are two main ways to secure the communication between a producer and consumer:

  1. Securing the Transport Layer
    This requires using SSL and a HTTPS endpoint. By using this, the communication between the consumer and producer will be encrypted.

  2. Securing the Contents of the SOAP message
    This option requires using WS-Security to handle parts of the SOAP message. With this option you can specify things like encryption, signing, timestamps, etc as well as passing across user credentials to perform a login on the producer side. WS-Security is more powerful and has more options, but requires more complex configurations.

Depending on requirements, an HTTPs endpoint or/and WS-Security can be used.

WSRP over SSL with HTTPS endpoints

It is possible to use WSRP over SSL for a secure exchange of data. Since GateIn Portal does not come initially configured for HTTPS connectors, we will need to configure the producer's server for this first. This is a global configuration change to JBoss AS and will affect more than just GateIn Portal and WSRP. Please see the JBoss AS documentation for how to configure HTTPS connectors for the server.

Once the producer is configured for HTTPS connections, on the consumer you will just need to modify the URL for the WSRP endpoint to point to the new HTTPS-based url. This will require either manually updating the value in the WSRP admin application, or by specifying it using the wsrp-consumers-config.xml configuration file before the server is first started.

Sample Configuration For Enabling SSL With WSRP

This is just a simple, test configuration to be used as an example as to how its possible to setup the HTTPS/SSL with WSRP. It is not meant to show best practices for configuring HTTPS with JBoss AS and does things which should not be used in a production server (such as self-signed certificates). Please see the JBoss AS documentation for full configuration options.

Configure the Producer to Use HTTPS

First we will need to configure the producer's server to use HTTPS. This is handled in the same manner that you would configure any JBoss AS server for HTTPS.

  1. Generate the keystore for the producer

    keytool -genkey -alias tomcat -keyalg RSA -keystore producerhttps.keystore -dname "cn=localhost" -keypass changeme -storepass changeme
  2. Configure the server to add an https connection. This requires modifying the standalone/configuration/standalone.xml file with the following content in bold:

    ...
    <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
        <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
        <connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
            <ssl certificate-key-file="/path/to/producerhttps.keystore" password="changeme"/>
        </connector>
    <virtual-server name="default-host" enable-welcome-root="true">
        <alias name="localhost"/>
        <alias name="example.com"/>
    </virtual-server>
    ...

  3. Start the server and verify that https://localhost:8443/portal is accessible. Note that since you are using a self-signed certificate that your browser will give a warning that the certificate cannot be trusted.

    In this example case we are accessing the portal using 'localhost' hence why we are using "cn=localhost" in the keytool command. If you are using this across another domain, you will need to make the necessary change.

Configure the Consumer to Access the WSRP Endpoint over HTTPS

Ideally we should be able to just change the consumer configuration URL for the producer in the WSRP administration interface to use HTTPS, but we need to tell the consumer's server to trust our self-signed certificate first.

  1. Export the producer's public key from the producer's keystore

    keytool -export -alias tomcat -file producerkey.rsa -keystore producerhttps.keystore -storepass changeme
  2. Import the producer's public key into a new keystore for the consumer

    keytool -import -alias tomcat -file producerkey.rsa -keystore consumerhttps.keystore -storepass changeme -noprompt
  3. Configure the bin/standalone.conf file to add the following line at the end of the file:

    JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=/path/to/consumerhttps.keystore -Djavax.net.ssl.trustStorePassword=changeme"
  4. Start the consumer and change the selfv2 producer URL to https://localhost:8443/wsrp-producer/v2/MarkupService?wsdl and verify that the consumer can access the producer.

It is also possible to modify the wsrp-consumers-config.xml configuration file to change the URL instead of modifying it in the administration interface

WSRP and WS-Security

Portlets may present different data or options depending on the currently authenticated user. For remote portlets, this means having to propagate the user credentials from the consumer back to the producer in a safe and secure manner. The WSRP specification does not directly specify how this should be accomplished, but delegates this work to the existing WS-Security standards. The WS-Security standards can also be used to secure the SOAP message, such as encryption and signing the message.

Web Container Compatibility

WSRP and WS-Security is currently only supported on GateIn Portal when running on top of JBoss AS 7.

Encryption

You will want to encrypt the credentials, and potentially the content and data, being sent between the consumer and producer, otherwise they will be sent in plain text and could be easily intercepted. You can either configure WS-Security to encrypt and sign SOAP messages being sent or secure the transport layer by using an HTTPS endpoint. Failure to encrypt SOAP messages or transport layer will result in the username and password being sent in plain text. Use of encryption is strongly recommended.

Credentials

When the consumer sends the user credentials to the producer, it is sending the credentials for the currently authenticated user in the consumer. This makes signing in to remote portlets transparent to end users, but also requires that the producer and consumer use the same credentials. This means that the username and password must be the same and valid on both servers.

The recommended approach for this situation would be to use a common LDAP configuration. Please see the user guide on how to configure LDAP for use with GateIn Portal.

Security Configuration

Introduction

JBoss AS7 uses a different web service implementation than the previous versions: it is now uses the JBossWS CXF Stack instead of the JBossWS Native Stack. Due to these changes, the way we configure WS-Security for WSRP with GateIn Portal on JBossAS 7 has changed.

We only support one WS-Security configuration option for the producer. All consumers accessing the producer will have to conform to this security constraint. This means if the producer requires encryption, all consumers will be required to encrypt their messages when accessing the producer.

We also only support one WS-Security configuration option to be used by all the consumers. A consumer has the option to enable or disable WS-Security, which allows for one or more consumers to use WS-Security while the others do not.

Overview

CXF uses interceptors to extend and configure its behaviour. There are two main types of interceptors: InInterceptors and OutInterceptors. InInterceptors are invoked for communication coming into the client or server, while OutInterceptors are invoked when the client or server sends a message.

So for the WSRP case, the communication from the consumer to the producer is governed by the consumer's OutInterceptor and the producer's InIntereceptor. The communication from the producer to the consumer is governed by the producer's OutInterceptor and the consumer's InInterceptor. This may mean having to configure 4 Interceptors.

When dealing with WS-Security, there are some things to consider here:

  • When dealing with user propagation, only the consumer sends the user credentials to the producer. So Username Tokens only need to be configured for the consumer's OutInterceptor and the producer's InInterceptor.

  • When dealing with things like encryption, you will most likely want to encrypt the message from the consumer to the producer and also the message from the producer to the consumer. This means that encryption properties must be configured for all 4 interceptors.

Please see the CXF Documentation for more details on interceptors and their types: http://cxf.apache.org/docs/interceptors.html

To support WS-Security, GateIn Portal uses CXF's WSS4J Interceptors which handle all WS-Security related tasks. Please see the CXF Documentation for more details: http://cxf.apache.org/docs/ws-security.html

WSS4J Interceptors and WSRP

The WSS4J Interceptors are configured using properties, and as such can be configured using simple property files.

WSRP looks for specific property files to know whether or not in/out interceptors must be added and configured for either consumers or producer. Theses files are located in the standalone/configuration/gatein/wsrp/cxf/ws-security directory of your the JBoss AS 7 home directory. Consumer-specific files are in the consumer subdirectory while producer-specific files should be located in the producer subdirectory. To add and configure a WSS4J interceptor, you just need to add the proper configuration file in the proper directory. If no configuration file is found for a specific interceptor type, then no such interceptor will be added. "In" interceptors are configured using WSS4JInInterceptor.properties files while "out" interceptors are configured using WSS4JOutInterceptor.properties files.

Putting things together, here are the files you need to add to configure each interceptor types for each WSRP side:

Side

Interceptor type

Configuration file

Consumer

IN

standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/WSS4JInInterceptor.properties

 

OUT

standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/WSS4JOutInterceptor.properties

Producer

IN

standalone/configuration/gatein/wsrp/cxf/ws-security/producer/WSS4JInInterceptor.properties

 

OUT

standalone/configuration/gatein/wsrp/cxf/ws-security/producer/WSS4JOutInterceptor.properties

Please refer to the CXF or WSS4J documentation for instructions and options available for each type of interceptors.

User Propagation

User propagation can be configured to be used over WSRP with ws-security. What this means is that a user logged into a consumer can have their credentials propagated over to the producer. This allows the producer to authenticate the user and any portlet on the producer (a remote portlet from the consumer's perspective) will view the user as being properly authenticated. This allows for remote portlets to access things like user information.

This only works if the user's credentials on the producer and consumer are the same. This may require using a common authentication mechanism, such as LDAP.

This requires some special options when configuring the producer and server.

Consumer Configuration

In order to configure ws-security on the consumer side, you will have to configure the WSS4J Interceptors as seen above. This will require having to configure the WSS4JInInterceptor and/or WSS4JOutInterceptor.
You will also need to check the 'Enable WS-Security' checkbox on the WSRP Admin Portlet for the consumer configuration to take effect.

images/author/download/attachments/78709355/config_wss_selected.png

Special GateIn Portal Configuration Options for User Propagation

In order to handle user propagation in GateIn Portal across ws-security, a couple of special configuration options have been created which should be applied to the consumer's WSS4JOutInterceptor.

Custom 'user' option:
user=gtn.current.user

What this option will do is it will set the 'user' property to the currently authenticated user on the consumer.

Custom 'action' option
action=gtn.UsernameToken.ifCurrentUserAuthenticated

If a user is currently authenticated, it will replace the 'gtn.UsernameToken.ifCurrentUserAuthenticated' with 'UsernameToken'. If the current user is an unauthenticated user, 'gtn.UsernameToken.ifCurrentUserAuthenticated' will be removed from the action list. If no other actions are specified, then the WSS4J interceptor will not be added to the consumer. This allows you to only use ws-security when dealing with authenticated users, and not for anonymous users.

This requires that the user option is set to 'gtn.current.user'

Custom PasswordCallbackClass

To set the password for the username token, we need to specify the password in a callback class. See the cxf ws-security documentation for more details (http://cxf.apache.org/docs/ws-security.html).

A special callback class has already been created which handles this for you: CurrentUserPasswordCallback. This class will retrieve the currently authenticated user's password and set this as the password in the callback object.

passwordCallbackClass=org.gatein.wsrp.wss.cxf.consumer.CurrentUserPasswordCallback

Producer Configuration

The configuration of the producer is similar to that of the consumer. It also requires having to configure the WSS4JInInterceptor and/or WSS4JOutInterceptor.

Special GateIn Portal Configuration Options for User Propagation

To properly propagate user information on the producer-side, you will need to use GTNSubjectCreatingInterceptor instead of a regular WSS4JInInterceptor. This GateIn Portal specific "in" interceptor is an extension of the traditional WSS4JInInterceptor and therefore can be configured similarly and accept the same configuration properties. To specify that you want to use the GTNSubjectCreatingInterceptor, please create a property file at standalone/configuration/gatein/wsrp/cxf/ws-security/producer/GTNSubjectCreatingInterceptor.properties instead of the regular WSS4JInInterceptor.properties file.

This Interceptor will handle the ws-security headers and retrieve the users credentials. It will then use these credentials to perform a login on the producer site, thus authenticating the user on the producer and makes the user available to remote portlets.

This class also extends org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingInterceptor and can accept the same properties this class normally accepts. See the JBossWS documentation for options and more information.

Custom 'action' option
action=gtn.UsernameToken.ifAvailable

When this option is activated, the interceptor will set the action to 'UsernameToken' when the received SOAP message contains ws-security headers. If no ws-security header is included in the message, then no action is taken and the interceptor is not run. This is useful for dealing with authenticated and unauthentcated users trying to access the producer.

Sample Configuration using the UsernameToken and User Propagation

This example configuration does not encrypt the message. This means the username and password will be sent between the producer and consumer in plain text. This is a security concern and is only being shown as a simple example. It is up to administrators to properly configure the WSS4J Interceptors to encrypt messages or to only use https communication between the producer and consumer.

Producer Setup
  1. create the following file: standalone/configuration/gatein/wsrp/cxf/ws-security/producer/GTNSubjectCreatingInterceptor.properties

  2. set the content of GTNSubjectCreatingInterceptor.properties created in step 1 to:

    action=gtn.UsernameToken.ifAvailable
  3. start the producer server

Consumer Setup
  1. create the following file: standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/WSS4JOutInterceptor.properties

  2. set the content of the WSS4JOutInterceptor.properties created in step 1 to:

    passwordType=PasswordText
    user=gtn.current.user
    action=gtn.UsernameToken.ifCurrentUserAuthenticated
    passwordCallbackClass=org.gatein.wsrp.wss.cxf.consumer.CurrentUserPasswordCallback
  3. start the consumer server

  4. in the WSRP admin portlet, click the 'enable ws-security' checkbox

  5. access a remote portlet (for example, the user identity portlet included as an example portlet in GateIn Portal) and verify that the authenticated user is the same as the one on the consumer

Sample Configuration Securing the Endpoints using Encryption and Signing

The following steps outline how to configure the producer and consumer to encrypt and sign SOAP messages passed between the producer and consumer. This example only deals with SOAP messages being sent between the producer and consumer, and not with user propagation.

Some of the configuration options specified here are based on the content at http://cxf.apache.org/docs/ws-security.html and http://www.jroller.com/gmazza/entry/cxf_x509_profile More information may be available at these sites.

Password Callback Class

WSS4J uses a Java class to specify the password when performing any security related actions. For the purpose of these encryption and signing examples, we will use the same password for the producer's and consumer's keystore (wsrpAliasPassword). This simplifies things a bit as it means we can use just one password callback class for both the producer and consumer.

Example test.TestCallbackHandler class:

package test;
 
import java.io.IOException;
 
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
 
import org.apache.ws.security.WSPasswordCallback;
import org.gatein.wsrp.wss.cxf.consumer.CurrentUserPasswordCallback;
 
public class TestCallbackHandler implements CallbackHandler
{
 
    @Override
    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException
    {
 
        //First check if we have any user name token call backs to add.
        //NOTE: only needed if using username tokens, and you want the currently authenticated users password added
        CurrentUserPasswordCallback currentUserPasswordCallback = new CurrentUserPasswordCallback();
        currentUserPasswordCallback.handle(callbacks);
 
        for (Callback callback: callbacks)
        {
            if (callback instanceof WSPasswordCallback)
            {
                WSPasswordCallback wsPWCallback = (WSPasswordCallback)callback;
                // since the CurrentUserPasswordCallback already handles the USERNAME_TOKEN case, we don't want to set it in this case
                if (wsPWCallback.getUsage() != WSPasswordCallback.USERNAME_TOKEN)
                {
                    wsPWCallback.setPassword("wsrpAliasPassword");
                }
            }
        }
    }
}

CallbackHandler implementations are provided to GateIn Portal using the standard Java ServiceLoader infrastructure. As such, CallbackHandler implementations need to be bundled in a jar containing a file META-INF/services/javax.security.auth.callback.CallbackHandler specifying the fully qualified name of the CallbackHandler implementation class. This jar then needs to be put in the gatein/extensions directory of your GateIn Portal installation.

You can see a working example of a CallbackHandler implentation at https://github.com/gatein/gatein-wsrp/tree/master/examples/wss-callback

Configuring the Keystores

In this example we are making it a bit easier by specifying the same keystore password for both the producer and consumer, as they can use the same password callback class.

  1. Generate the producer's private encryption keys

    keytool -genkey -alias producerAlias -keypass wsrpAliasPassword -keystore producer.jks -storepass keyStorePassword -dname "cn=producerAlias" -keyalg RSA
  2. Export the producer's public key

    keytool -export -alias producerAlias -file producerkey.rsa -keystore producer.jks -storepass keyStorePassword
  3. Generate the consumer's private encryption keys

    keytool -genkey -alias consumerAlias -keypass wsrpAliasPassword -keystore consumer.jks -storepass keyStorePassword -dname "cn=consumerAlias" -keyalg RSA
  4. Export the consumer's public key

    keytool -export -alias consumerAlias -file consumerkey.rsa -keystore consumer.jks -storepass keyStorePassword
  5. Import the consumer's public key into the producer's keystore

    keytool -import -alias consumerAlias  -file consumerkey.rsa -keystore producer.jks -storepass keyStorePassword -noprompt
  6. Import the producer's public key into the consumer's keystore

    keytool -import -alias producerAlias  -file producerkey.rsa -keystore consumer.jks -storepass keyStorePassword -noprompt
  7. Copy the producer.jks file to the standalone/configuration/gatein/wsrp/cxf/ws-security/producer directory on the producer

  8. Copy the consumer.jks file to the standalone/configuration/gatein/wsrp/cxf/ws-security/consumer directory on the consumer

Configuring the Producer
  1. Create standalone/configuration/gatein/wsrp/cxf/ws-security/producer/WSS4JInInterceptor.properties with the following content. This will configure the incoming message between the producer and the consumer

    action=Signature Encrypt Timestamp
    signaturePropFile=producer-security.properties
    decryptionPropFile=producer-security.properties
    passwordCallbackClass=test.TestCallbackHandler
  2. Create standalone/configuration/gatein/wsrp/cxf/ws-security/producer/WSS4JOutInterceptor.properties with the following content. This will configure the outgoing message between the producer and the consumer

    action=Signature Encrypt Timestamp
    signaturePropFile=producer-security.properties
    encryptionPropFile=producer-security.properties
    passwordCallbackClass=test.TestCallbackHandler
    user=producerAlias
    encryptionUser=consumerAlias
    signatureUser=producerAlias
  3. Create standalone/configuration/gatein/wsrp/cxf/ws-security/producer/producer-security.properties with the following content:

    org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
    org.apache.ws.security.crypto.merlin.keystore.type=jks
    org.apache.ws.security.crypto.merlin.keystore.password=keyStorePassword
    org.apache.ws.security.crypto.merlin.file=producer.jks
  4. The passwordCallbackClass property in these configuration files needs to match the fully qualified name of your CallbackHandler implementation class. In our case, it is test.TestCallbackHandler.

Configuring the Consumer
  1. Create standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/WSS4JOutInterceptor.properties with the following content. This will configure the outgoing message between the consumer and the producer

    action=Signature Encrypt Timestamp
    signaturePropFile=consumer-security.properties
    encryptionPropFile=consumer-security.properties
    passwordCallbackClass=test.TestCallbackHandler
    user=consumerAlias
    encryptionUser=producerAlias
    signatureUser=consumerAlias
  2. Create standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/WSS4JInInterceptor.properties with the following content. This will configure the incoming message between the consumer and the producer

    action=Signature Encrypt Timestamp
    signaturePropFile=consumer-security.properties
    decryptionPropFile=consumer-security.properties
    passwordCallbackClass=test.TestCallbackHandler
  3. Create standalone/configuration/gatein/wsrp/cxf/ws-security/consumer/consumer-security.properties with the following content:

    org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
    org.apache.ws.security.crypto.merlin.keystore.type=jks
    org.apache.ws.security.crypto.merlin.keystore.password=keyStorePassword
    org.apache.ws.security.crypto.merlin.file=consumer.jks
  4. The passwordCallbackClass property in these configuration files needs to match the fully qualified name of your CallbackHandler implementation class. In our case, it is test.TestCallbackHandler.

Sample Configuration using UsernameToken, Encryption and Signing with User Propagation

The following setps outline how to configure the producer and consumer to encrypt and sign the soap message as well as use user propagation between the producer and consumer.

Configure the Producer

Follow the steps outlined in the Sample Configuration Securing the Endpoints using Encryption and Signing section but make the following changes:

  1. rename the WSS4JInInterceptor.properties file to GTNSubjectCreatingInterceptor.properties

  2. set the action property in GTNSubjectCreatingInterceptor.properties as:

    action= gtn.UsernameToken.ifAvailable Signature Encrypt Timestamp
  3. set the passwordType in GTNSubjectCreatingInterceptor.properties as:

    passwordType=PasswordText
Configure the Consumer

Follow the steps outlined in the Sample Configuration Securing the Endpoints using Encryption and Signing section but make the following changes:

  1. set the action property in WSS4JOutInterceptor.properties as:

    action=gtn.UsernameToken.ifCurrentUserAuthenticated Signature Encrypt Timestamp
  2. set the user in the WSS4JOutInterceptor.properties as:

    user=gtn.current.user
  3. set the passwordType in the WSS4JOutInterceptor.properties as:

    passwordType=PasswordText
JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 13:21:38 UTC, last content change 2013-04-23 15:18:47 UTC.