Search code examples
wso2identityxacml

WSOS Identity - PIP Extension with a Set of Multiple Elements Returns Blank


Our testing demonstrated that the WSO2 PIP extension module implements a "Set" class connecting with the PDP integration (=AttributeFinder). This interface currently is only capable to transfer one single element. Once we use a customized look-up for our groups definitions, generating a Set with multiple elements of type String, the WSO2 PDP returns a blank String with no information.

Sample Code from WSO2:

@Override
    public Set<String> getAttributeValues(String subject, String resource, String action,
                                  String environment, String attributeId, String issuer) throws Exception {

        Set<String> roles = new HashSet<String>();
        String role = findRole(subject);
        if(role != null){
            roles.add(role);
        }

        return roles;
    }    

PIP Extension Example Source for download:

https://svn.wso2.org/repos/wso2/carbon/platform/trunk/components/identity/org.wso2.carbon.identity.samples.entitlement.pip/src/main/java/org/wso2/carbon/identity/samples/entitlement/pip/

Our look-up program is using a String based data type, which matches the data type of the element, see XACML code below: .

<AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="http://w3.red.com/subject/groupsUserBelong" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"></AttributeDesignator> 

Access groups handling is a very common task in the XACML logic processing, so this is a crucial function for implementing XACML policies and rules.

Is this failure behaviour a bug (returns blank), or does WSO2 XACML deliver a programmatic implementation for a Set using multiple elements of Strings, automatically generating a string-bag according to the number of data elements, one String per element?

To complete the analysis, please check the sample code above, as well as the matching abstract class named AbstractPIPAttributeFinder. Both reference the return value named as "roles" and in the abstract class it is described as "values". Once the object to return is defined as a Set and the field names descries it in a plural, its basically self explaining the the values transported could be one or multiple elements that are part of the Set construction, usually each element of a String data-type.

The logic works well with a single element and it fails when using multiple elements, which at the XACML interface returns a "blank" string in place of a "String-bag".


Solution

  • After detailed analysis of the PIP data flow through modules, we circled the issue inside the PIP extension program. Below you find the logic used to address and transfer the data fields. The new logic is able to transport multiple elements (for ex. groups, or roles) which was tested with an ObligationExpression as well as with a String-bag comparison, which both executed successfully after deploy of the new extension code.

    public Set<String> getAttributeValues(String subject, String resource,
                    String action, String environment, String attributeId, String issuer)
                    throws Exception {
    
                Set<String> myHash = new HashSet<String>();
                Map<String, String> myMap = null;
                if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/versionOfPIP")) {
                    myHash.add(myversion.toString().trim());
                    System.out.println(myversion.toString().trim());
    
                } else if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/groupsUserBelong")) {
                    String myGroups = RedRedGroupAttrFinder.
                            getOnlyGroups(RedRedGroupAttrFinder.redGroupHTTPsSlaphAPI(subject));
                    ArrayList<String> myGroupsArrayL =RedRedGroupAttrFinder.convertStringToArraylist(myGroups);
                    for (String element : myGroupsArrayL) {
                        myHash.add(element.toString().trim());
                        }
    
                } else if (attributeId.trim().equalsIgnoreCase("http://w3.red.com/subject/employeeCountryCode")) {
                    myMap = LdapHash.searchRedPagesByIntranetEmail(subject);
                    myHash.add(myMap.get(attributeId.substring(26).toString().trim()));
    
                } else {
                    myHash.add("never");
                }
    
                return myHash;
            }
    }