Customizing XACML Policy Information Point of WSO2 Identity Server 5.10.0

Pamoda Wimalasiri
Identity Beyond Borders
5 min readJun 6, 2020

--

This is my third blog of a series of blogs about XACML. In the previous blogs, I discussed the basics of XACML and how to adapt the WSO2 Identity Server as an XACML engine.

  1. “A beginner’s guide to XACML”
  2. WSO2 Identity Server as an XACML Engine

In this blog, I’m going to tell you how you can customize the XACML Policy Information Point of WSO2 Identity Server.

What is the Policy Information Point(PIP)?

According to the XACML reference architecture, PIP is the system entity that acts as a source of attribute values. Basically, if there are missing attributes in the XACML request which is sent by PEP, PIP would find them for the PDP to evaluate the policy.

The behavior of WSO2 Identity Server Default PIP

WSO2 Identity Server has the concept of claim management that each user’s attributes can be mapped into a unique entity called a claim. Therefore XACML engine can refer to the user’s attributes using this claim. The default PIP supports the claims that are stored in the server’s user store. When the XACML Policy Decision Point(PDP) is looking for an attribute supported by the PIP, it is retrieved from the userstore and returned.

Before moving to the customization part, let’s see the PIP architecture of the WSO2 Identity Server and the extendability of the WSO2 Identity Server for custom PIP modules.

PIP Architecture of WSO2 Identity Server

WSO2 Identity Server is based on the sun XACML implementation. Sunxacml provides an interface for plugging different PIP implementations as modules. “AttributeFinderModule” is the interface that would allow us to do this.

Therefore when we are writing a PIP module for WSO2 Identity Server, we need to register it with the “CarbonAttributeFinder”. Also, this PIP module must be implemented the “PIPAttributeFinder” interface in org.wso2.carbon.identity.entitlement.pip package.

The above diagram shows how things are getting registered and retrieved back when executing the XACML in WSO2 Identity Server.

  1. When the WSO2 Identity Server startup, the entitlement core component is started and builds the configuration that is used for initializing the entitlement engine.
  2. It initializes the listed PIP attribute finder modules in that entitlement configuration file.
  3. These initialization and configuration data are kept in the “EntitlementConfigHolder”.
  4. PDP initializes the “CarbonAttributeFinder” and reads PIP attribute finder data from the “EntitlementConfigHolder”.
  5. CarbonAttributeFinder” calls to all registered PIPs and stores the supported attributes of each PIP.
  6. If an XACML request comes with missing attribute id, PDP calls to “CarbonAttributeFinder” for help.
  7. CarbonAttributeFinder” calls the supported PIP attribute finder modules.
  8. Then results from each PIP are combined and sends back to the PDP for request evaluation.

Now you know all the theories related to the PIP module of WSO2 Identity Server. Let’s move to the implementation. (Customization and deployement details are given relevant to the WSO2 Identity Server 5.10.0)

Scenario:

  1. User permission details are stored externally and exposed by an API.
  2. An XACML policy is defined to authorize the user based on the permissions given for the user. (Sample XACML policy is given below)
  3. Therefore PIP should call the external API and get the attributes.

Implementing the custom PIP

You can refer to the pom.xml file for the project from the sample given. This has the dependencies relevant to the WSO2 IS 5.10.0. I have attached the complete source code for your reference and check the inline comments for more details.

Write a PIP module by extending “AbstractPIPAttributeFinder”.

You need to implement the following methods.

  1. init (Properties properties):

Here you can write the logic to initialize your module. Any properties that are defined for the custom module in the deployment.toml can be used.
In our sample, the external service URL is configured in the file as the property, “ExternalServiceUrl

2. getSupportedAttributes():
Here you can define all the attribute IDs supported by your custom module.
Our sample PIP module will support retrieving permissions of the user and the attribute is given the ID https://pamtech.com/claims/permission

3. getAttributeValues (String subjectId, String resourceId, String actionId, String environmentId, String attributeId, String issuer):

Here you can write the logic to find the required attributes.

subject, resource, action and environment are retrieved from the XACML request.

subject –> attribute value which can be identified by the following attribute in the request, urn:oasis:names:tc:xacml:1.0:subject:subject-id

resource –> attribute value which can be identified by the following attribute in the request, urn:oasis:names:tc:xacml:1.0:resource:resource-id

action –> attribute value which can be identified by the following attribute in the request, urn:oasis:names:tc:xacml:1.0:action:action-id

environment –> attribute value which can be identified by the following attribute in the request, urn:oasis:names:tc:xacml:1.0:environment:environment-id

issuer –> issuer which is related to the attributeId that is needed to be resolved.

The AbstractPIPAttributeFinder has defined the method getAttributeValues(URI attributeType, URI attributeId, URI category, String issuer, EvaluationCtx evaluationCtx) to retrieve the above mentioned attribute values from the evaluation context. Once they are retrieved, the AbstractPIPAttributeFinder calls the customized getAttributeValues method in the custom PIP class. The AbstractPIPAttributeFinder handles the caching mechanism of the attributes as well.

4. getModuleName(): return the name for the module

Deploying the custom PIP

  1. When the implementation is done, go to the project home(sample-entitlement-service) and run the command,
mvn clean install

2. When the compilation completes, you can find the com.pamtech.entitlement.service-1.0.0.jar inside the sample-entitlement-servicel/target. Copy the jar file to the directory <IS_HOME>/repository/components/lib.

NOTE:

Due to a known limitation of the product the extension package name should be in the format of, org.wso2.carbon.identity.entitlement.{{extension.name}}. This is fixed as a WUM update. If you are not subscribed for updates, you can do the following workaround.

* Edit the entitlement.properties.j2 file in repository/resources/conf/templates/repository/conf/identity directory.

* Search for identity.entitlement.extension and change the templated configs as follows.

{% if identity.entitlement.extension is defined %}
{% for extension in identity.entitlement.extension %}
{% for key,value in extension.properties.items() %}
{{extension.name}}.{{loop.index}}={{key}},{{value}}
{% endfor %}
{% endfor %}
{% endif %}

3. Add the following configurations to the deployment.toml file located in <IS_HOME>/repository/conf/ folder to register the custom module.

[identity.entitlement.policy_point.pip]
attribute_designators = [
"org.wso2.carbon.identity.entitlement.pip.DefaultAttributeFinder",
"org.wso2.carbon.identity.application.authz.xacml.pip.AuthenticationContextAttributePIP",
"com.pamtech.entitlement.service.pip.SampleAttributeFinder"
]

4. To define the properties required by the custom module, add the following configs to the deployment.toml.

[[identity.entitlement.extension]]
name = "com.pamtech.entitlement.service.pip.SampleAttributeFinder"
[identity.entitlement.extension.properties]
ExternalServiceUrl = "http://beeceptor.com/console/pamtech"

In this configuration,

  • com.pamtech.entitlement.service.pip.SampleAttributeFinder is the classpath of the custom attribute finder java class.
  • ExternalServiceUrl is the property required by the custom module. Any key-value pair required can be defined like this.
  • If you more than one custom attribute finder and required properties, you can add them as follows.
[[identity.entitlement.extension]]
name = "custom.clazz1"
[identity.entitlement.extension.properties]
property1 = "value1"
[[identity.entitlement.extension]]
name = "custom.clazz2"
[identity.entitlement.extension.properties]
propertyA = "valueA"
propertyB = "valueB"

5. Restart the server.

Try out the custom PIP

Deploy the following XACML policy which checks the attributehttps://pamtech.com/claims/permission.

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"  PolicyId="custom_attribute_policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
<Target></Target>
<Rule Effect="Permit" RuleId="rule1">
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">View</AttributeValue>
<AttributeDesignator AttributeId="https://pamtech.com/claims/permission" 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>
</Policy>

You may follow the WSO2 official document or my previous blog to deploy the XACML policy and with sample XACML requests using the TryIt Tool of the product.

WSO2 Identity Server comes with amble extensible capabilities. So you can plug in custom XACML policy information points as required and enforce the authorization rules. Try out custom XACML PIPs with WSO2 Identity Server and share your thoughts.

Thanks for reading.

References

Sample Source Code:

https://github.com/pamodaaw/sample-entitlement-service

My other blogs on XACML:

  1. A beginner’s guide to XACML
  2. WSO2 Identity Server as an XACML Engine
  3. Custom XACML functions for WSO2 Identity Server 5.10.0

Official WSO2 documentation: https://is.docs.wso2.com/en/5.10.0/develop/writing-a-custom-policy-info-point/

--

--

Pamoda Wimalasiri
Identity Beyond Borders

Associate Technical Lead @ WSO2 focused on the IAM domain