Web Service After Operation Rule

Hi Team,

We are integrating Web Service Connector with SailPoint Identitynow. We do have 3 api endpoints with us as below:

  1. Users Endpoint: v1/users (this doesn’t have group details).
  2. Usergroup EndPoint: v1/usergroups(this does not have user details)
  3. Group Member Endpoint: v1/usergroup/grouid/user
    Currently i have created a parent endpoint Account aggregation and child endpoint of account aggregation using v1/users.
    I have written a afteroperationrule as below and from this im trying to do the following
    a. Read the groupendpoint, iterate through each group and get the members fro m groumembers endpoint. Get users from user endpoint and map the users to which they are memberof. In short im trying to acheive reverse entitlement aggregation to map group details to user’s account.
import java.util.*;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import sailpoint.connector.webservices.WebServicesClient;
import sailpoint.tools.GeneralException;
import org.apache.commons.lang.StringUtils;
import java.nio.charset.StandardCharsets;
import connector.common.JsonUtil;
import java.io.StringWriter;

log.error("Starting the FICBO WebServiceAfterOperationRule");

String authenticate(String url, String username, String password) throws Exception {
    WebServicesClient client = new WebServicesClient();
    Map args = new HashMap();
    Map headers = new HashMap();
    List allowedStatuses = new ArrayList();

    String request = String.format("%s/logon/long", url);
    args.put(WebServicesClient.ARG_URL, request);
    headers.put("Content-Type", "application/json");
    headers.put("Accept", "application/json");
    allowedStatuses.add("2**");
    String payload = String.format("{\"password\": \"%s\", \"clientType\": \"\", \"auth\": \"secEnterprise\", \"userName\": \"%s\"}", password, username);

    client.configure(args);
    try {
        String response = client.executePost(request, payload, headers, allowedStatuses);
        Map responseMap = JsonUtil.toMap(response);

        String logonToken = (String) responseMap.get("logonToken");
        return logonToken;
    } catch (Exception e) {
        log.error("Exception message: " + e.getMessage());
        if (e.getMessage().contains("404")) {
            throw new Exception("Authentication URL not found: " + request);
        } else {
            throw new Exception(String.format("Authentication call failed: %s", e.getMessage()));
        }
    }
}

try {
    WebServicesClient client = new WebServicesClient();
    Map mainHeaders = new HashMap();
    List allowedStatuses = new ArrayList();
    allowedStatuses.add("2**");

    String baseUrl = "https://cafil0110win.intl.intlroot.fid-intl.com:8443/biprws";
    String username = (String) application.getStringAttributeValue("username");
    String password = (String) application.getStringAttributeValue("password_CA");

    String token;
    try {
        token = authenticate(baseUrl, username, password);
    } catch (Exception e) {
        log.error("Authentication failed: " + e.getMessage());
        return;
    }

    Map headers = new HashMap();
    headers.put("X-SAP-LogonToken", token);
    headers.put("Content-Type", "application/xml");
    headers.put("Accept", "application/xml");

    String groupsEndpoint = "http://cafil0110win.intl.intlroot.fid-intl.com:8080/biprws/v1/usergroups";
    log.error("Printing the groupsEndpoint: " + groupsEndpoint);

    // Hardcoded values for userGroupMapping
    Map userGroupMapping = new HashMap();
    Map groupInfo1 = new HashMap();
    groupInfo1.put("groupname", "Test View On Demand");
    groupInfo1.put("grouptype", "UserGroup");
    groupInfo1.put("userIds", Arrays.asList("1769682"));
    userGroupMapping.put("1416819", groupInfo1);

    String usersEndpoint = "http://cafil0110win.intl.intlroot.fid-intl.com:8080/biprws/v1/users";

    // Fetch user data
    Map args2 = new HashMap();
    args2.put(WebServicesClient.ARG_URL, usersEndpoint);
    client.configure(args2);
    String usersResponse = client.executeGet(usersEndpoint, headers, allowedStatuses);
    log.error("Raw usersResponse: " + usersResponse);

    // Process the user data
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document usersDocument = builder.parse(new java.io.ByteArrayInputStream(usersResponse.getBytes(StandardCharsets.UTF_8)));
    usersDocument.getDocumentElement().normalize();
    NodeList entryNodes1 = usersDocument.getElementsByTagName("entry");
    List finalList = new ArrayList();

    for (int i = 0; i < entryNodes1.getLength(); i++) {
        log.error("Entering i loop of users end point");
        Node entryNode1 = entryNodes1.item(i);

        if (entryNode1.getNodeType() == Node.ELEMENT_NODE) {
            log.error("Entering for loop of users end point");
            Element userElement = (Element) entryNode1;
            NodeList userNodes = userElement.getElementsByTagName("attr");
            log.error("Printing the userNodes:" + userNodes);
            Map userMap = new HashMap();
            String userId = null;
            String userName = null;
            String fullName = null;

            for (int j = 0; j < userNodes.getLength(); j++) {
                log.error("Entering j loop of users end point");
                Element userAttrElement = (Element) userNodes.item(j);
                String name = userAttrElement.getAttribute("name");
                log.error("Printing name:" + name);
                String value = userAttrElement.getTextContent();
                log.error("Printing value:" + value);

                if ("id".equals(name)) {
                    userId = value;
                    log.error("Printing userId:" + userId);
                } else if ("name".equals(name)) {
                    userName = value;
                    log.error("Printing userName:" + userName);
                } else if ("fullname".equals(name)) {
                    fullName = value;
                    log.error("Printing fullName:" + fullName);
                }
            }

            List userGroups = new ArrayList();
            Iterator it = userGroupMapping.entrySet().iterator();
            while (it.hasNext()) {
                log.error("Entering while loop");
                Map.Entry entry = (Map.Entry) it.next();
                String groupId = (String) entry.getKey();
                Map groupInfo = (Map) entry.getValue();
                List userIds = (List) groupInfo.get("userIds");

                if (userIds.contains(userId)) {
                    log.error("Entering if loop");
                    Map groupDetails = new HashMap();
                    groupDetails.put("groupid", groupId);
                    groupDetails.put("groupname", (String) groupInfo.get("groupname"));
                    groupDetails.put("grouptype", (String) groupInfo.get("grouptype"));
                    userGroups.add(groupDetails);
                }
            }

            // Add group details to XML
            Element attrsElement = (Element) userElement.getElementsByTagName("attrs").item(0);
            Element groupidsElement = usersDocument.createElement("groupids");
            for (Map groupDetails : userGroups) {
                Element groupIdElement = usersDocument.createElement("groupid");
                groupIdElement.appendChild(usersDocument.createTextNode((String) groupDetails.get("groupid")));
                groupidsElement.appendChild(groupIdElement);

                Element groupNameElement = usersDocument.createElement("groupname");
                groupNameElement.appendChild(usersDocument.createTextNode((String) groupDetails.get("groupname")));
                groupidsElement.appendChild(groupNameElement);

                Element groupTypeElement = usersDocument.createElement("grouptype");
                groupTypeElement.appendChild(usersDocument.createTextNode((String) groupDetails.get("grouptype")));
                groupidsElement.appendChild(groupTypeElement);
            }
            attrsElement.appendChild(groupidsElement);

            log.error("printing userGroups" + userGroups);
            userMap.put("name", userName);
            userMap.put("fullname", fullName);
            userMap.put("groupids", userGroups);
            userMap.put("userid", userId);
            log.error("printing userMap" + userMap);
            finalList.add(userMap);
            log.error("Processed user data: " + finalList);
        }
    }

    log.error("Processed user data: " + finalList);

    Map updatedMapInfo = new HashMap();
    updatedMapInfo.put("data", finalList);
    log.error("Updated map info: " + updatedMapInfo);

    if (processedResponseObject != null) {
        log.error("Entering processedResponseObject null check");
        List updatedProcessedResponse = new ArrayList();
        for (Iterator it = processedResponseObject.iterator(); it.hasNext();) {
            Map iterateMap = (Map) it.next();
            if (iterateMap != null) {
                log.error("iterateMap null check");
                Object userIdObj = iterateMap.get("userid");
                List userGroups = new ArrayList();
                if (userIdObj instanceof String || userIdObj instanceof Integer) {
                    String userId = userIdObj.toString();
                    log.error("Printing userId" + userId);
                    Iterator itUserGroup = userGroupMapping.entrySet().iterator();
                    while (itUserGroup.hasNext()) {
                        log.error("Entering while loop");
                        Map.Entry entry = (Map.Entry) itUserGroup.next();
                        String groupId = (String) entry.getKey();
                        Map groupInfo = (Map) entry.getValue();
                        List userIds = (List) groupInfo.get("userIds");
                        log.error("Printing userIds" + userIds);
                        if (userIds.contains(userId)) {
                            Map groupDetails = new HashMap();
                            groupDetails.put("groupid", groupId);
                            groupDetails.put("groupname", (String) groupInfo.get("groupname"));
                            groupDetails.put("grouptype", (String) groupInfo.get("grouptype"));
                            userGroups.add(groupDetails);
                            log.error("Printing userGroups inside if loop" + userGroups);
                        }
                    }
                } else if (userIdObj instanceof List) {
                    List userIdList = (List) userIdObj;
                    for (Object userIdElement : userIdList) {
                        String userId = userIdElement.toString();
                        log.error("Printing userId" + userId);
                        Iterator itUserGroup = userGroupMapping.entrySet().iterator();
                        while (itUserGroup.hasNext()) {
                            log.error("Entering while loop");
                            Map.Entry entry = (Map.Entry) itUserGroup.next();
                            String groupId = (String) entry.getKey();
                            Map groupInfo = (Map) entry.getValue();
                            List userIds = (List) groupInfo.get("userIds");
                            log.error("Printing userIds" + userIds);
                            if (userIds.contains(userId)) {
                                Map groupDetails = new HashMap();
                                groupDetails.put("groupid", groupId);
                                groupDetails.put("groupname", (String) groupInfo.get("groupname"));
                                groupDetails.put("grouptype", (String) groupInfo.get("grouptype"));
                                userGroups.add(groupDetails);
                                log.error("Printing userGroups inside if loop" + userGroups);
                            }
                        }
                    }
                } else {
                    log.error("Unexpected type for userIdObj: " + userIdObj.getClass().getName());
                }
                iterateMap.put("groupids", userGroups);
                log.error("Printing the iterateMap inside loop" + iterateMap);
                updatedProcessedResponse.add(iterateMap);
                log.error("Printing the updatedProcessedResponse inside loop" + updatedProcessedResponse);
            }
        }
        log.error("Printing updatedProcessedResponse values outside the loop" + updatedProcessedResponse);
        updatedMapInfo.put("data", updatedProcessedResponse);
        log.error("updatedMapInfo inside loop" + updatedMapInfo);
    }
    log.error("Final updatedMapInfo" + updatedMapInfo);
    Map connectorStateMap = new HashMap();
    connectorStateMap.put("refresh_token", token);
    updatedMapInfo.put("connectorStateMap", connectorStateMap);

    // Convert updated XML document to string
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource source = new DOMSource(usersDocument);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    transformer.transform(source, result);
    String updatedXml = writer.toString();
    log.error("Updated XML: " + updatedXml);

    log.error("Final updatedMapInfo" + updatedMapInfo);
    log.error("RULEWS processedResponseObject after is " + processedResponseObject);
    log.error("Final rawResponseObject" + rawResponseObject);
    log.error("Final rawResponseObject" + rawResponseObject.toString());
    return updatedMapInfo;
} catch (Exception e) {
    log.error("Error parsing group members response for group: " + e.getMessage());
}```

I am not getting any error and i have modified the xml to get the response as below:

<entry xmlns="">
<title type="text">a636185</title>
<id>tag:sap.com,2010:bip-rs/ASYnf9MlWkpIjWEolQev3D0</id>
<updated>2025-03-13T07:48:29.009Z</updated>
<link href="http://cafil0110win.intl.intlroot.fid-intl.com:8080/biprws/v1/users/1769682" rel="alternate"/>
<content type="application/xml">
<attrs xmlns="http://www.sap.com/rws/bip">
<attr xmlns="" name="cuid" type="string">ASYnf9MlWkpIjWEolQev3D0</attr>
<attr xmlns="" name="name" type="string">a636185</attr>
<attr xmlns="" name="description" type="string"/>
<attr xmlns="" name="id" type="string">1769682</attr>
<attr xmlns="" name="fullname" type="string">Gong, Roy</attr>
<attr xmlns="" name="type" type="string">User</attr>
<attr xmlns="" name="ownerid" type="string">1769682</attr>
<attr xmlns="" name="updated" type="string">Mar 13, 2025 3:48 AM</attr>
<attr xmlns="" name="parentid" type="string">19</attr>
<attr xmlns="" name="groupid" type="string">
<value>groupid1</value>
<value>groupid2</value>
</attr>
</attrs>
</content>
</entry>

However i am still not able to get the group values.
Could you please help me know if i am doing something wrong or any suggestions which could help me here?
Thanks

Actually You don’t need After Operation Rule, this is a common requirement.

You will have user ID or something in Groups end point rite, we can pull user groups based on that. If you can get me sample responses of these endpoints masking sensitive data, I might be able to get you the config mostly without After Operation Rule.

1 Like

Hi @MVKR7T

  1. V1/users users endpoint where group details are not available
  2. V1/usergroups details where user detail is nor available
  3. V1/usergroups/groupid/users where only member details is available without group details.
    Hence there is no direct way to map group to users.
    Let me provide you the sample data for all 3 response

Here are the Responses

  1. Users v1/users:
<entry xmlns="http://www.w3.org/">
    <title type="text">user</title>
    <updated>2025-03-15T20:47:26.619Z</updated>
    <link href="/v1/users/1743316" rel="alternate"></link>
    <content type="application/xml">
        <attrs xmlns="http://www.sap.com/rws/bip">
            <attr name="cuid" type="string"></attr>
            <attr name="forcepasswordchange" type="bool">false</attr>
            <attr name="parentcuid" type="string"></attr>
            <attr name="description" type="string"></attr>
            <attr name="type" type="string">User</attr>
            <attr name="ownerid" type="string">1743316</attr>
            <attr name="parentid" type="string">19</attr>
            <attr name="accountstatus" type="string">Enabled</attr>
            <attr name="nameduser" type="bool">false</attr>
            <attr name="name" type="string">a787306</attr>
            <attr name="lastlogon" type="string"></attr>
            <attr name="disabled" type="bool">false</attr>
            <attr name="id" type="string">1743316</attr>
            <attr name="fullname" type="string">Sreevally, Praveenkumar</attr>
            <attr name="updated" type="string">Mar 13, 2025 3:50 AM</attr>
            <attr name="email" type="string">xxx@mail.com</attr>
            <attr name="passwordexpire" type="bool">false</attr>
            <attr name="allowchangepassword" type="bool">false</attr>
        </attrs>
    </content>
</entry>
  1. Groups v1/usergroups
<entry xmlns="http://www.w3.org/">
    <title type="text">Test View On Demand</title>
    <updated>2025-03-15T20:49:07.521Z</updated>
    <link href="/v1/usergroups/1416819" rel="alternate"></link>
    <link href="/v1/usergroups/1416819/users" rel="alternate"></link>
    <link href="/v1/usergroups/1416819/usergroups" rel="alternate"></link>
    <content type="application/xml">
        <attrs xmlns="http://www.sap.com/rws/bip">
            <attr name="cuid" type="string"></attr>
            <attr name="keywords" type="string"></attr>
            <attr name="parentcuid" type="string"></attr>
            <attr name="created" type="datetime"></attr>
            <attr name="name" type="string">Test View On Demand</attr>
            <attr name="description" type="string">Group</attr>
            <attr name="id" type="string">1416819</attr>
            <attr name="updated" type="string" null="true"></attr>
            <attr name="parentid" type="string">20</attr>
        </attrs>
    </content>
</entry>
  1. Members v1/usergroups/groupid/user
<feed xmlns="http://www.w3.org/">
    <title type="text">usergroup</title>
    <updated></updated>
    <entry>
        <title type="text">ViewOnDemand</title>
        <updated>2025-03-15T20:49:30.372Z</updated>
        <link href="v1/usergroups/1416819/users" rel="alternate"></link>
        <content type="application/xml">
            <attrs xmlns="http://www.sap.com/rws/bip">
                <attr name="cuid" type="string"></attr>
                <attr name="keywords" type="string"></attr>
                <attr name="created" type="string"></attr>
                <attr name="name" type="string">ViewOnDemand</attr>
                <attr name="description" type="string"></attr>
                <attr name="id" type="string">1416822</attr>
                <attr name="fullname" type="string"></attr>
                <attr name="updated" type="string" null="true"></attr>
                <attr name="email" type="string"></attr>
            </attrs>
        </content>
    </entry>
    <entry>
        <title type="text">a787306</title>
        <updated>2025-03-15T20:49:30.395Z</updated>
        <link href="/v1/usergroups/1416819/users" rel="alternate"></link>
        <content type="application/xml">
            <attrs xmlns="http:/">
                <attr name="cuid" type="string"></attr>
                <attr name="keywords" type="string"></attr>
                <attr name="created" type="string"></attr>
                <attr name="name" type="string">a787306</attr>
                <attr name="description" type="string"></attr>
                <attr name="id" type="string">1743316</attr>
                <attr name="fullname" type="string">Sreevally, Praveenkumar</attr>
                <attr name="updated" type="string" null="true"></attr>
                <attr name="email" type="string"></attr>
            </attrs>
        </content>
    </entry>
</feed>

Also please note that the rule i have provided above is hardcoded with groups and users so that the aggregation would not take time. I was trying to modify the user’s xml to hold the groupid values.However the values are not being updated in user’s account
Please help me with this issue

From First API end point, we have CUID.

By using this CUID can we get user groups from 2nd API ?

No. CUID of users and usergroups are different.I cannot use cuid of user to find the usergroups.
For ex. If CUID of user is A1234fjexxxxxxxxxx_jxxxx, and cuid of group assigned to user is AaT3hhexxxxxxxxxx_jxxxx i cannot use this as below
a. v1/usergroups/users?cuid=A1234fjexxxxxxxxxx_jxxxx or
b. v1/users/AaT3hhexxxxxxxxxx_jxxxx/usergroups.
I get 404 No found error.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.