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
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.
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.
Sample in sequence has shown in above.<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>
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.
10. Invoke the proxy service with security through SOAP UI and check the functionality.<?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>
No comments:
Post a Comment