Search code examples
authorizationxacmlabacalfawso2-identity-server

WSO2 Identity Server - Sending Multiple Attributes in the Request to a Custom Policy Info Point (PIP) in WSO2IS


I'm using WSO2IS 5.3.0 and I have followed the instructions on this web site: https://docs.wso2.com/display/IS530/Writing+a+Custom+Policy+Info+Point

I've successfully implemented the custom PIP attribute finder (KMarketJDBCAttributeFinder), so far so good. The problem I'm having is that I want to send more than one attribute, but the AttributeFinder only picks one. Next, my policy and request:

XACML Policy:

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
        xmlns:xacml="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
        PolicyId="My-Custom-Policy"
        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">subj-id</AttributeValue>
        <AttributeDesignator
                MustBePresent="false"
                Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
                DataType="http://www.w3.org/2001/XMLSchema#string"/>
      </Match>
    </AllOf>
  </AnyOf>
</Target>
<Rule RuleId="rule1" Effect="Permit">
  <Target>
    <AnyOf>
      <AllOf>
        <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">action-value</AttributeValue>
          <AttributeDesignator
                  MustBePresent="false"
                  Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
                  AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
                  DataType="http://www.w3.org/2001/XMLSchema#string"/>
        </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"/>
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">some-value-returned-by-custom-pip-finder-jar</AttributeValue>
      <AttributeDesignator
              Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
              AttributeId="urn:my:custom:id:data-one"
              DataType="http://www.w3.org/2001/XMLSchema#string"
              MustBePresent="false"/>
    </Apply>
  </Condition>
</Rule>
<Rule RuleId="rule2" Effect="Deny"/>
</Policy>

XACML Request:

<Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
    <Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">subj-id</AttributeValue>
        </Attribute>
    </Attributes>

    <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">action-value</AttributeValue>
        </Attribute>
    </Attributes>

    <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
        <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">re-src-id</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:my:custom:id:data-one" IncludeInResult="false">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">data-one</AttributeValue>
        </Attribute>
        <Attribute AttributeId="urn:my:custom:id:data-two" IncludeInResult="false">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">data-two</AttributeValue>
        </Attribute>
    </Attributes>
</Request>

As you can see, I'm sending three attributes as part of the resource category; but when I debug the code, I only see that one of those attributes is picked up (the others are ignored)

Also, from the request and policy I have used customs AttributeId: urn:my:custom:id:data-one and urn:my:custom:id:data-two

¿How can I send multiple attributes (without using the option "Multiple Requests", I just one to send one single request) and confirm that all attributes are properly obtained by my custom attributeFinder PIP extension?


Solution

  • Analyzing the code of the Abstract class in charge of picking up the attributes from the request, the method that creates the bag of attributes only picks one; and that's way my test is not working.

    The solution I found was to create my own abstract class that implements the class PIPAttributeFinder and pick up all attributes from the request:

    ... (other code)
    
        List<String> resourceList = new ArrayList<String>();
    
        EvaluationResult resource = evaluationCtx.getAttribute(new URI("http://www.w3.org/2001/XMLSchema#string"), new URI("urn:oasis:names:tc:xacml:1.0:resource:resource-id"), issuer, new URI("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"));
        if (resource != null && resource.getAttributeValue() != null && resource.getAttributeValue().isBag()) {
            key = (BagAttribute) resource.getAttributeValue();
            if (key.size() > 0) {
                Iterator iterator = key.iterator();
                String encodeAttribute = "";
                while(iterator.hasNext()) {
                    AttributeValue attributeValue = (AttributeValue)iterator.next();
                    encodeAttribute = attributeValue.encode();
                    resourceList.add(encodeAttribute);
                }
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Finding attributes for the resource %1$s", new Object[]{encodeAttribute}));
                }
                resourceId = "empty-value";
            }
        }
    
    ... (other code)
    
        attributeValues = this.getAttributeValues(subjectId, resourceId, resourceList, actionId, environmentId, attributeId.toString(), issuer);
    
    ... (other code)
    

    Keep in mind that you need to modify the signature of the method getAttributeValues