Sunday, September 21, 2014

ESB: Invoking secured backend - Part 1 - Username Token



Scenario 
  1. Backend service is secured using Username token. 
  2. Client invokes ESB proxy using http. ( no security between client and ESB) 
  3. At the ESB, proxy adds username token to outgoing message and invokes secured backend.
  4. ESB sends back echo service's response back to client. 

Setting up environment 

Backend ( WSO2 Application server 5.2.1)
  1. Start WSO2 AS 5.2.1 using ( Unix: sh wso2server.sh / Windows: wso2server.bat ) 
  2. Log in to management console. ( https://localhost:9443/carbon/ ) 
  3. Create two user called tom and bom
    • Goto Configure -> Users and Roles -> Users
    • Create an user called tom with password "tompass". 
    • Create another user called bob with password "bobpass"
    • Assign both users to "admin" role.
  4. Secure Echo service with Username token. 
    • Goto Main -> Services -> List 
    • Click on "echo" service. This will open up "Service Dashboard (echo)" page.
    • Under "Quality of Service Configuration", Select "security".
    • In "Security for the service" page, Select Enable security.
    • Under Security scenarios, select "Username token"  ( First security policy) and click next. 
    • In next page, select "admin" under user group. 
    • Click Finish. 
ESB ( WSO2 ESB 4.8.1 )
  1. Start WSO2 ESB with port offset =1 ( Unix: sh wso2server.sh -DportOffset=1 / Windows: wso2server.bat --DportOffset=1) 


Rampart configuration for UsernameToken  ( ESB )
  • Create an ESB in-line xml local entry called "UTOverTransport.xml" with following content. 
<wsp:Policy wsu:Id="UTOverTransport"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:user>tom</ramp:user>
<ramp:passwordCallbackClass>org.example.rampart.PWCBHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>

Password callback Implementation

  • Create a jar with following class, and drop it to /repository/components/lib/
  • Then restart ESB server. 
  • ( Maven Project is located here. )
package org.example.rampart;
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 java.io.IOException;
public class PWCBHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];
int usage = pwcb.getUsage();
String id = pwcb.getIdentifier();
if (usage == WSPasswordCallback.USERNAME_TOKEN) {
System.out.println("Resolving password for user " + id);
// Getting password
if ("tom".equals(id)) {
pwcb.setPassword("tompass");
}else if ("bob".equals(id)){
pwcb.setPassword("bobpass");
} else {
pwcb.setPassword("");
}
} else if (usage == WSPasswordCallback.SIGNATURE
|| usage == WSPasswordCallback.DECRYPT) {
// Logic to get the private key password for signature or
// decryption
// TODO : Implement me
}
}
}
}
Some useful References on Rampart password callback handler:  
  1. http://wso2.com/library/3733/
  2. http://wso2.com/library/240/

ESB Proxy

  • Create a proxy called EchoUTProxy with following content. 
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EchoUTProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<send>
<endpoint>
<address uri="https://localhost:9443/services/echo">
<enableSec policy="UTOverTransport.xml"/>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
name="wsse:Security"
scope="default"
action="remove"/>
<send/>
</outSequence>
</target>
<publishWSDL uri="http://localhost:9763/services/echo?wsdl"/>
<description/>
</proxy>
view raw EchoUTProxy.xml hosted with ❤ by GitHub


Testing Scenario

  • Enable Soap tracer on WSO2 AS.
  • Invoke EchoUTProxy  using SOAP UI. 
You can see Username token in request message as follows. 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:echo="http://echo.services.core.carbon.wso2.org">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-13">
<wsu:Created>2014-09-21T04:17:56.541Z</wsu:Created>
<wsu:Expires>2014-09-21T04:22:56.541Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-14">
<wsse:Username>tom</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">tompass</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<echo:echoString>
<!--Optional:-->
<in>?</in>
</echo:echoString>
</soapenv:Body>
</soapenv:Envelope>
view raw gistfile1.xml hosted with ❤ by GitHub



No comments:

Post a Comment