This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Configuring WSO2 ESB Entitlement Mediator with Identity Server

With the latest WSO2 ESB, you can add fine-grained XACML authorization for proxy services, using the entitlement mediator. XACML-based authorization allows you to have an extremely flexible way of defining the rules of accessing resources based on the user, the user's role, the environment, time and date, etc. Now, the WSO2 product platform allows you to incorporate XACML based authorization into your SOA deployment.

The problem in most security schemes is that it does not give you the ability to fine-grain your authorization scheme unless a substantial amount of work goes into implementing such a scheme from scratch. The WSO2 product platform relieves this burden off the system architect and allows you to integrate XACML-based authorization into a deployment and have a full blown authorization scheme in place with minimum effort.

For more information about the WSO2 ESB, please visit the Enterprise Service Bus Documentation.

The following sections provide more information on how to configure this.

Configuring the Identity Server as a XACML engine

The first step is to configure the WSO2 Identity Server to act as a XACML engine. XACML support for fine-grained authorization comes with WSO2 Identity Server. It includes full support for policies based on XACML 2.0.

  1. Sign in. Enter your user name and password to log on to the Management Console.
  2. Navigate to the Main menu to access the Entitlement menu. Click Policy Administration under PAP.
  3. Add a new policy or import external policy files to the system. Once you click "Add," a template policy will be added. You can edit it to suit your requirements, or you may add a completely new policy.
  4. Evaluate the template policy with no changes. Click on the "Evaluate Entitlement Policies" link.

Here you can build your own XACML request to evaluate the policy you just added. Copy and paste the following and click "Evaluate."

<Request xmlns="urn:oasis:names:tc:xacml:2.0:context:schema:os" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<Subject>
		<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://www.w3.org/2001/XMLSchema#string">
			<AttributeValue>admin</AttributeValue>
		</Attribute>
		<Attribute AttributeId="group" DataType="http://www.w3.org/2001/XMLSchema#string">
			<AttributeValue>admin</AttributeValue>
		</Attribute>
	</Subject>
	<Resource>
		<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string">
			<AttributeValue>http://localhost:8280/services/echo/echoString</AttributeValue>
		</Attribute>
	</Resource>
	<Action>
		<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string">
			<AttributeValue>read</AttributeValue>
		</Attribute>
	</Action>
</Request>

The above request means that the "admin" user who belongs to the group "admin" is trying to access the echoString operation of the http://localhost:8280/services/echo service.

The template policy evaluates the above in the following manner. Find the following section of the template policy:

<Resources>
	<Resource>
		<ResourceMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
			<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/echo/</AttributValue>
			<ResourceAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string"/>
		</ResourceMatch>
	</Resource>
</Resources>

In this policy, we use function:string-regexp-match to validate the service name and operation name combination. You can modify it to suit your own requirements.

For example, if you want to allow users to access all of the services deployed on a certain server, then simply change it to http://localhost:8280/. Or, if you want a user to access only a certain set of operations, you can simply change regex to http://localhost:8280/services/echo/(echoString|echoInt).

The following code is used to evaluate the user name and the user's group:

<Condition>
	<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
		<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
		<SubjectAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://www.w3.org/2001/XMLSchema#string" SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"/>
	</Apply>
</Condition>
<Condition>
	<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
		<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
		<SubjectAttributeDesignator AttributeId="group" DataType="http://www.w3.org/2001/XMLSchema#string"/>
	</Apply>
</Condition>

Here we validate the "admin" user and any user in the "admin" group.

Configuring the ESB entitlement mediator

The next step is to configure the entitlement mediator in the WSO2 ESB.

  1. Create a Proxy Service. Under "In Sequence," create an Anonymous sequence to include the Entitlement, Header, and Send mediators. Add the Advanced/Entitlement Mediator to InSequence. See Adding a Proxy Service. The Entitlement Server should be the endpoint for the Identity Server where the entitlement engine is running https://IDENTITY_SERVER:PORT/services/. Additionally, the user should have login and "manage configuration" permissions in the Identity Server.
  2. Add the Transform/Header mediator. See Adding a Mediator to a Sequence and Mediators. Remove the "Security" header. Click on the "Namespaces" link to set the wsse namespace.
  3. Create a Core/Send mediator, and save to return to the main flow.
  4. Add a Core/Send mediator to the "Out Sequence" as an "Anonymous" sequence, and save to return to the main flow to complete the creation of the Proxy Service.
  5. Apply the UsernameToken security policy to the Proxy Service you just created, as explained here. The security policy being applied to the binding by the policy editor causes an issue with Proxy Services that must be resolved. To overcome the Proxy Services issue, from the service listing, select the Proxy Service, and then select "Policies." Remove the applied policies from the Binding Hierarchy, and add the security policy to the Service Hierarchy.
  6. You are ready to use the Proxy Service. Write a client to invoke the secured Proxy Service.

The client in the following example has tried to invoke the echo service deployed in ESB through the previously created Proxy Service.

package org.apache.ws.axis2;
    import org.apache.axiom.om.OMAbstractFactory;
    import org.apache.axiom.om.OMElement;
    import org.apache.axiom.om.OMFactory;
    import org.apache.axiom.om.OMNamespace;
    import org.apache.axiom.om.impl.builder.StAXOMBuilder;
    import org.apache.axis2.Constants;
    import org.apache.axis2.addressing.EndpointReference;
    import org.apache.axis2.client.Options;
    import org.apache.axis2.client.ServiceClient;
    import org.apache.axis2.context.ConfigurationContext;
    import org.apache.axis2.context.ConfigurationContextFactory;
    import org.apache.neethi.Policy;
    import org.apache.neethi.PolicyEngine;
    import org.apache.rampart.RampartMessageData;

    public class TestClient {

    final static String ADDR_URL = "http://192.168.1.2:8280/services/echo";
    final static String TRANS_URL = "https://192.168.1.2:8243/services/test";

    public static void main(String[] args) throws Exception {
    ServiceClient client = null;
    Options options = null;
    OMElement response = null;
    ConfigurationContext context = null;
    String trustStore = null;

    // You need to import the ESBs public certificate to this key store.
    trustStore = "mykeystore.jks";
    // We are accessing ESB over HTTPS - so need to set trustStore parameters.
    System.setProperty("javax.net.ssl.trustStore", trustStore);
    // Password of mykeystore.jks
    System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");

    // Create configuration context - you will have Rampart module engaged in the client.axis2.xml
    context = ConfigurationContextFactory.createConfigurationContextFromFileSystem("repo","repo/conf/client.axis2.xml");

    // This is the security policy of the proxy service applied UT.
    StAXOMBuilder builder = new StAXOMBuilder("policy.xml");
    Policy policy = PolicyEngine.getPolicy(builder.getDocumentElement());

    context = ConfigurationContextFactory.createConfigurationContextFromFileSystem("repo","repo/conf/client.axis2.xml");
    client = new ServiceClient(context, null);
    options = new Options();
    options.setAction("urn:echoString");
    // This is the addressing URL pointing to the echo service deployed in ESB
    options.setTo(new EndpointReference(ADDR_URL));
    // To the ESB, the proxy service
    options.setUserName("admin");
    options.setPassword("admin");
    // TRANS_URL points to proxy service
    options.setProperty(Constants.Configuration.TRANSPORT_URL, TRANS_URL);
    options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, policy);
    client.setOptions(options);
    client.engageModule("addressing");
    client.engageModule("rampart");
    response = client.sendReceive(getPayload("Hello world"));
    System.out.println(response);
    }

    private static OMElement getPayload(String value) {
    OMFactory factory = null;
    OMNamespace ns = null;
    OMElement elem = null;
    OMElement childElem = null;

    factory = OMAbstractFactory.getOMFactory();
    ns = factory.createOMNamespace("http://echo.services.core.carbon.wso2.org", "ns1");
    elem = factory.createOMElement("echoString", ns);
    childElem = factory.createOMElement("in", null);
    childElem.setText(value);
    elem.addChild(childElem);
    return elem;
    }
    }