Authorization is a key aspect of identity management and security in enterprise applications. There are various access control mechanisms such as
- User Centric Permission - where you define permission per user
- Role Based Access Control - where you assign set of users to a role and assign permission to that role
- Attribute Based Access Control - authorization is governed based on user attributes
There are drawbacks in these mechanisms such as non-scalability, coarse-grained permission and authorization logic being coupled with application logic which prevents flexibility. Policy-Based Access Control on the other hand is emerging as a flexible and scalable solution for access management. XACML is a powerful way of achieving PBAC in a fine grained manner.
Architecture of the Solution
Setting up the Solution
Running the Client
Described below is the sample scenario that the rest of the article is based on.
We have a RESTful back-end service which exposes methods to manage student entries with HTTP verbs: GET, POST, PUT and DELETE. We need to allow access to perform POST, PUT and DELETE operations of the service only to admin users (since those methods do modifications in the system) and allow access to GET method to all the other users.
Architecture of the Solution
One key aspect of PBAC solutions based on XACML is the reference architecture which defines key components involved in access management according to their responsibility. Following are the logical components present in our setup:
- PAP - Policy Administration Point - WSO2 Identity Server - this is where XACML authorization policies are governed.
- PEP - (Policy Enforcement Point) - WSO2 ESB - this is where users' requests to services are intercepted and the access is allowed or denied according to the decision given by the PDP.
- PDP - (Policy Decision Point) - WSO2 Identity Server - this is where an authorization decision is taken by evaluating the XACML authorization request sent by PEP, against a matching XACML policy found in PAP.
- PIP - Policy Information Point - User store of WSO2 Identity Server - this is from where required attributes of the user who is trying to access the resource will be read by PDP, in order to take the authorization decision.
Although there are four logical components listed above, we will have only two physical components in our access management solution since WSO2 Identity Server will play the roles of PAP, PDP and PIP as shown below.
Image 1: Solution Architecture
Setting up the Solution
1. Hosting the back-end service:
- You can obtain the source and archive of the REST service from here. If you want to learn more about RESTful services in Axis2, this article is a good reference.
- We host this back-end service in WSO2 App Server. (You can also host it in axis2 webapp deployed in Apache Tomcat as well.) Download and run the App Server.
- Upload RestService.aar to the app server by logging into its management console through the browser (https://localhost:9443/carbon/). You may need to wait for few minutes to see the service in the services list after uploading.
- Click on the RestService and obtain its url. e.g: http://localhost:9766/services/RestService
Image 2: Hosting the service in Application Server
2. Setting up WSO2 Identity Server (IS):
This plays the roles of PAP, PDP and PIP in our solution as mentioned above.
- Download Identity Server, change its Ports.Offset to 1 in carbon.xml found in [IS_HOME]/repository/conf and run the server.
- Login to management console (https://localhost:9444/carbon/) as admin.
- Create a user called 'hasini' that belongs to role 'everyone' by default. And give 'login' permission to role - 'everyone'.
- Now, download and import this XACML policy into IS through Entitlement->Administration->Import New Entitlement Policy as shown below. Once imported, 'enable' the policy from the icon in front of the policy name.
Image 3: Policy administration in Identity Server
3. Setting up WSO2 ESB as PEP:
- Download ESB and change its port offset to 2, as we did with IS above.
- We need to use the user store of IS, as the central user store of ESB as well. Therefore change user-mgt.xml of ESB which is found in [ESB_HOME] /repository/conf to point to the user store of IS by setting the following property:
- Give 'login' permission to role - ‘everyone’.
- Now we need to configure a secured proxy service with entitlement mediator in its 'in sequence' in order to intercept and authorize REST requests sent to our back-end service.
- Obtain the proxy service configuration from here and add it to the ESB configuration through Manage->Service Bus->Source View as shown below.
Image 4: Configuring ESB proxy service
Remarks On Proxy Service:
Please note the following configuration of the proxy service (just like what is shown above, which authenticates the user), obtains the authorization decision by communicating with IS and allows/denies access to back-end service.
- Proxy service is secured with User Name Token so that only the authenticated users will be able to access it.
- Endpoint is set to the back-end RESTful service.
- In sequence has three property mediators which are configured to specifically handle RESTful invocations.
- There is an entitlement mediator which communicates with EntitlementService in IS for obtaining authorization decisions.
- Header mediator removes the security header before sending the request to back-end service.
Running the Client
Let us have a look at our sample client code, (which you can download from here) which invokes the RESTful back-end service which is secured by ESB proxy service.
Here I need to highlight the REST way of invoking the proxy service when it is secured with User Name Token security policy.
Following is how we perform the subsequent operations on the service stub.
As you can see, we perform “add student” operation as admin user and “get student” and “update student” operations as a non admin user. According to the scenario we mentioned at the very beginning, only the first two operations should be successful and the third operations should be denied.
Since the first and the third operation are asynchronous, we can not observe whether the operation was allowed or denied from client side. To observe that, you need to enable debug level log for entitlement mediator in ESB.
Steps for running the client:
- Add the following folders to the class path of the sample: [ESB_HOME]/repository/components/plugins, [ESB_HOME]/lib/api
- Change the keystore path in line 40 of TestRestServiceStub to the wso2carbon.jks keystore of ESB which is in [ESB_HOME]/repository/resources/security
When you run the client, you will observe that “add student” operation and “get student” operation will pass and the “update student” operation will be denied (please refer to ESB logs) based on the user who invokes the operation and the defined XACML policy.
In this way, you can achieve fine-grained access control with PBAC solutions with XACML. Although this sample incorporates users' role as the attribute to define access control rules, you can use other attributes as well and manage access to your enterprise resources in a fine-grained manner.
I believe you got an overall idea of how to build up an access management solution with XACML using WSO2 products stack. Next, let’s go through the XACML policy used in this sample and the XACML requests sent to PDP in order to discuss how authorization decisions are taken. Let me begin by stating the authorization policy that we needed to enforce:
Allow access for admin users to perform all - POST, PUT ,GET and DELETE operations of the service (since three of the methods do modifications in the system) and allow access to GET method to all the users in 'admin' and 'everyone' roles.
Following is how XACML defines above mentioned authorization policy: (you can obtain it from here as well)
Well, it might not be convincing at the first glance. Let us look at it step by step.
1. Policy is consisted of a target and a set of rules. Information in the target element is used by the PDP to pick a matching policy for an incoming authorization request, out of many policies available in the PDP. Then the request is evaluated against the set of rules defined in the policy. In our case, above policy will be picked for any request whose "Subject" element matches the regexp : http://localhost:9766/services/RestService
2. Above XACML policy has three rules defined:
"admin_allow_rule": defines which operations to resources are allowed to users in admin role.
"everyone_allow_rule": defines which operations to resources are allowed to users in everyone role (In carbon products, all the users are belonged to everyone role by default.).
"deny-rule": defines that requests come in any other criteria should be denied.
3. Rule combining algorithm used in the above policy is "first-applicable" which means that the first rule that evaluates to true will take effect and others will be ignored.
4. A rule is consisted of a target and a set of conditions. Rule element has two parameters: rule-id and effect-which specifies the outcome of the rule if given conditions are met and the target is matched.
Rule conditions are useful when the target can not express the constraints adequately.
In our policy, the two rules have targets specifying for which subject type the rule should be evaluated for. In the first rule, its the subject of role type 'admin' and for the second rule, it is the subject of role type 'everyone'.
There is a series of blog posts by Prabath which will help you to master on writting XACML policies.
Now, let us have a look at the XACML requests sent by PEP (ESB) to the PDP (IS) for the three requests sent by the client to access the back-end service. (You can observe the XACML request at the Idenetity Server back-end if you enable debug level logs for the Entitlement Service in IS.)
A XACML request consists of:
- Subject - defines attributes of the entity who tries to access the resource
- Resource - defines the resource that is being accessed
- Action - the action that is being performed on the resource.
You can get a good understanding about XAML requests from the post: Anatomy of the XACML request
1. When admin tries to add a student:
The above request will be evaluated to true by the first rule in the above XACML policy since it matches the target and the conditions.
2. When non-admin user tries to get student:
Above request will be evaluated to by the second rule defined in the policy which allows all the users in admin and everyone role to allow access to GET operation.
3. When non-admin user tries to update student:
Above request will be denied since there is no rule defined with the effect of 'permit' that matches it. Hence it will be denied by the default deny rule.
This concludes the explanation on how to build up an access management solution with XACML using WSO2 product stack and also how the XACML policies and requests involve in taking authorization decisions.
Hasini Gunasinghe, Software Engineer, WSO2 Inc.