Sunday, August 9, 2015

WSO2 ESB Proxy authorization for SOAP endoint services based on XACML Policy in WSO2 IS

During this blogpost. I'm going to explain how to do XACML policy based authorization with wso2 ESB. I'm using WSO2 IS 5.0.0 and WSO2 ESB 4.8.1 for configuring the XACML sample.

This article shows how to perform authorization based on XACML policy define in WSO2 IS to control the access to Echo web service hosted in WSO2 AS or Axis2 Container.

This sample show how we can perform role base authorization for the calling web service operation in Echo Service. Echo Service is associate with three operations as follow.

echoInt = Will echo incoming integer back to client
echoString = Will echo incoming string back to client
echoOMElement  = will echo incoming OMElement back to client

Note 

Instead of hosting echo service in AS, please note that I'm using the echo service coming with the ESB for this sample. 

Common Cofigurations


  • Proxy Service need to secured with UT to authenticating a proxy service based on providing a username/password tokens in SOAP header which will forward to IS to check assigned roles of the user and perform actions based on it. 
  • use them against the underlying user store
  • User store should be shared with both IS and ESB
  • Create two roles named roleA and roleB
  • Create two users named user1 and user2 for test the scenario
  • Assign roleA to user1 and roleB to user2

Authorization Table

Service Operation
Required role
echoInt
roleA
echoString
roleA, roleB
echoOMElement
roleB

Overall Design Diagram of Sample



Sample Policy


<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"  PolicyId="echoRBACPolicy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
   <Target>
      <AnyOf>
         <AllOf>
            <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
               <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">/services/EchoProxy</AttributeValue>
               <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
            </Match>
         </AllOf>
      </AnyOf>
   </Target>
   <Rule Effect="Permit" RuleId="Rule-1">
      <Target>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">echoString</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
      </Target>
      <Condition>
         <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
            <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag">
               <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">roleA</AttributeValue>
               <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">roleB</AttributeValue>
            </Apply>
            <AttributeDesignator AttributeId="http://wso2.org/claims/role" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
         </Apply>
      </Condition>
   </Rule>
   <Rule Effect="Permit" RuleId="Rule-2">
      <Target>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">echoInt</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
      </Target>
      <Condition>
         <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of">
            <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"></Function>
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">roleA</AttributeValue>
            <AttributeDesignator AttributeId="http://wso2.org/claims/role" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
         </Apply>
      </Condition>
   </Rule>
   <Rule Effect="Permit" RuleId="Rule-3">
      <Target>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">echoOMElement</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
      </Target>
      <Condition>
         <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of">
            <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"></Function>
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">roleB</AttributeValue>
            <AttributeDesignator AttributeId="http://wso2.org/claims/role" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
         </Apply>
      </Condition>
   </Rule>
   <Rule Effect="Deny" RuleId="Deny-Rule"></Rule>
</Policy>        

WSO2 IS Configurations

Steps for adding policy


  • Go to Entitlement> PEP > Policy Administration tab and click add new entitlement policy link as shown in figure 1. 
Figure 1 : Policy Administration Page

  • After you clicking it, you can see multiple options to create XACML policy which associate with descripting text which exactly highlight what each option is done. For the testing purposes I'm going to upload the attached policy from Import Existing Policy option
  • You can also create your own policy with given options from Figure 2 view which come from Basic Policy Editor. 
Figure 2 : Create new policy

  • Here after click publish to PDP which list under the actions can be perform under added policy as in Figure 3. It will popup Fifure 4 UI which you can publish your policy to PDP. You can go to Entitlement> PDP > Policy View to check whether your policy has publish as in Figure 5
Figure 3 : Available Actions
Figure 4 : Policy Publish View
Figure 5 : Policy View

WSO2 ESB Configurations

Setup 
  • Create proxy service call EchoProxy 
  • Create in sequence name EchoServiceSeq
  • Create out sequence name EchoServiceSeqOut
Steps to configure

1. Add a in sequence and configure the entitlement mediator configurations as follow within this sequence requests going  to endpoint will be intercept from the proxy service, check the user authorized or not by sending the web service security header to Identity server and based on use permitted or not the service will be send to actual service or fail.
Figure 6 : Adding Entitlement Mediator to in sequence

Figure 6 shows the configurations of entitlement mediator

Figure 7 : Entitlement Mediator Configurations


  • Entitlement server : Endpoint of Identity servers authentication servlet (https:localhost:9443/services/)
  • Username : Valid user name that has admin rights (eg: admin) 
  • Password : password of the above user.
2. After filling above values, click on “Update” button.

3. Then add a send mediator to “OnAccept” path of Entitlement Mediator.In this configuration it has been instructed to Entitlement mediator if the user validated by the identity server with the XACML policy and permits to send the request to required endpoint.

<sequence name="EchoServiceSeq">
      <log level="full">
      <entitlementservice callbackclass="org.wso2.carbon.identity.entitlement.mediator.callback.UTEntitlementCallbackHandler" client="basicAuth" remoteservicepassword="enc:kuv2MubUUveMyv6GeHrXr9il59ajJIqUI4eoYHcgGKf/BBFOWn96NTjJQI+wYbWjKW6r79S7L7ZzgYeWx7DlGbff5X3pBN2Gh9yV0BHP1E93QtFqR7uTWi141Tr7V7ZwScwNqJbiNoV+vyLbsqKJE7T3nP8Ih9Y6omygbcLcHzg=" remoteserviceurl="https://localhost:9443/services/" remoteserviceusername="admin">
         <onreject>
            <log level="custom">
               <property name="symbol" value="+++++++++++++++++++++++++++++++++++++">
            </property></log>
            <makefault version="soap11">
               <code value="soap11Env:VersionMismatch" xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/">
               <reason value="Error occurred while accessing the service">
               <role>
            </role></reason></code></makefault>
            <send>
         </send></onreject>
         <onaccept>
            <send>
               <endpoint>
                  </endpoint></send></onaccept></entitlementservice></log></sequence><br />
<address uri="https://localhost:8244/services/echo">
               </address>
<obligations>
         <advice>
      </advice></obligations>
      <br />
<br />
<header action="remove" name="wsse:Security" scope="default" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <drop>
   </drop></header>

Sample in sequence has shown in above. 

4. Add fault sequence to “OnReject” path of the entitlement mediator.


5. Go to the visual view of the sequence and click on “Entitlement Mediator” and “Add sibling”, select Transform - > Header.In this mediator we address ESB to remove the Security header from soap header and send to Entitlement server for authorization.

Figure 8 : Adding header mediator

In header mediator, configure it as follow.

Figure 9 : Header Mediator Configurations

  • Name: Security
  • Action: Remove
  • Click on “Namespace” link add “wsse” as prefix andhttp://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd as the URI.
Click on update.

6. Add out sequence

7. Create a proxy service and configure above in sequence and out sequence. 

8. Secure the proxy service UT and select the user roles which needed to invoke this proxy service by users. 

9. Below shows entire ESB configuration used in this tutorial.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
   <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
      <parameter name="cachableDuration">15000</parameter>
   </registry>
   <proxy name="EchoPrroxyTest"
          transports="https"
          startOnLoad="true"
          trace="disable">
      <description/>
      <target inSequence="EchoServiceSeq" outSequence="EchoServiceSeqOut"/>
      <publishWSDL uri="http://localhost:9000/services/echo?wsdl"/>
      <policy key="conf:/repository/axis2/service-groups/EchoPrroxyTest/services/EchoPrroxyTest/policies/UTOverTransport"/>
      <parameter name="ScenarioID">scenario1</parameter>
      <enableSec/>
   </proxy>
   <sequence name="EchoServiceSeq">
      <log level="full"/>
      <entitlementService remoteServiceUrl="https://localhost:9443/services/"
                          remoteServiceUserName="admin"
                          remoteServicePassword="enc:kuv2MubUUveMyv6GeHrXr9il59ajJIqUI4eoYHcgGKf/BBFOWn96NTjJQI+wYbWjKW6r79S7L7ZzgYeWx7DlGbff5X3pBN2Gh9yV0BHP1E93QtFqR7uTWi141Tr7V7ZwScwNqJbiNoV+vyLbsqKJE7T3nP8Ih9Y6omygbcLcHzg="
                          callbackClass="org.wso2.carbon.identity.entitlement.mediator.callback.UTEntitlementCallbackHandler"
                          client="basicAuth">
         <onReject>
            <log level="custom">
               <property name="symbol" value="+++++++++++++++++++++++++++++++++++++"/>
            </log>
            <makefault version="soap11">
               <code xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/"
                     value="soap11Env:VersionMismatch"/>
               <reason value="Error occurred while accessing the service"/>
               <role/>
            </makefault>
            <send/>
         </onReject>
         <onAccept>
            <send>
               <endpoint>
                  <address uri="https://localhost:8244/services/echo"/>
               </endpoint>
            </send>
         </onAccept>
         <obligations/>
         <advice/>
      </entitlementService>
      <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"/>
      <drop/>
   </sequence>
   <sequence name="EchoServiceSeqOut">
      <send/>
   </sequence>
   <sequence name="fault">
      <log level="full">
         <property name="MESSAGE" value="Executing default 'fault' sequence"/>
         <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
         <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
      </log>
      <drop/>
   </sequence>
   <sequence name="main">
      <in>
         <log level="full"/>
         <filter source="get-property('To')" regex="http://localhost:9000.*">
            <send/>
         </filter>
      </in>
      <out>
         <send/>
      </out>
      <description>The main sequence for the message mediation</description>
   </sequence>
</definitions>
10. Invoke the proxy service with security through SOAP UI and check the functionality.

No comments:

Post a Comment