Multi-Endpoint Group Aggregation Requirements

Which IIQ version are you inquiring about?

8.5sp1

Share all details about your problem, including any error messages you may have received.

My Goal: I need to aggregate all groups from a target system. The API requires a two-step process:

  1. First, I must fetch a list of all “organizations” from a primary endpoint.

  2. Then, for each of those organizations, I must call a separate endpoint to get the groups that belong to it.

API Endpoints:

  1. Get Organizations Endpoint: GET https://api.example.com/v1/organizations

    • This is my partitioning endpoint. It returns a JSON array of organization objects.

    • Example Response:

      [
          {
              "orgId": "org_12345",
              "name": "Sales Department"
          },
          {
              "orgId": "org_67890",
              "name": "Engineering"
          }
      ]
      
      
  2. Get Groups by Organization Endpoint: GET https://api.example.com/v1/organizations/{orgId}/groups

    • This is my main group aggregation endpoint, which needs the orgId from the first call.

    • Example Response (for org_12345):

      [
          {
              "groupId": "group_abc",
              "displayName": "East Coast Sales"
          },
          {
              "groupId": "group_def",
              "displayName": "Sales Team Leads"
          }
      ]
      
      

What I’ve Done So Far:

I have attempted to use the built-in chaining/partitioning features directly within the Group Aggregation operation.

  1. Created a “Get Partition” Operation: In the connector’s Operations list, I configured a new operation:

    • Operation Type: Get Partition

    • HTTP Resource: https://api.example.com/v1/organizations

    • Root Path: $ (to iterate over the array)

    • Success Code: 200

  2. Configured Group Aggregation: I then set up the main Group Aggregation operation:

    • HTTP Resource: https://api.example.com/v1/organizations/$partition.orgId$/groups

    • Partitioning Operation: I selected the “Get Partition” operation I created in the previous step.

My expectation was that the connector would first execute the “Get Partition” operation, iterate through each object in the response, and then use the orgId from each object to substitute into the $partition.orgId$ variable in the Group Aggregation URL.

The Problem:

When I run the Group Aggregation task, it fails. The logs indicate that the substitution is not happening as expected. The connector seems to be making a literal call to .../$partition.orgId$/groups or fails to resolve the variable, resulting in an invalid URL and a 404 or 400 error from the target system.

My Question:

  1. Is this “Get Partition” operation chaining approach supported for Group Aggregation, or does it only work for Account Aggregation?

  2. If this is the wrong approach, what is the standard method for telling IdentityIQ to fetch a list of IDs from one endpoint and use them to make multiple calls to another endpoint for group data?

I feel like I’m very close but am just missing a small piece of the configuration. Any help would be greatly appreciated.

Thank you

I also have tried the endpoint chaining, as that makes more sense:

Looking at syslog, I see it is looking for the “group” object type. However, I don’t have organizationId in the schema because the rest object doesn’t return it from the /roles

I am locked out with this method because I have to use the id field as the primary identity attribute for the given group. However, I cannot retrieve that primary field for the account group until I do the secondary endpoint with the correct organizationID.

Hi @acrumley ,

Kindly refer below link.

https://community.sailpoint.com/t5/IdentityIQ-Forum/Webservice-account-aggregation-not-bringing-groups/m-p/236308/thread-id/179435

Thank you,

Harikrishna

@acrumley ,I think you can use the Group Aggregation operation instead of Get Partitions. You can call two endpoints using the Parent Endpoint Name.

Thanks,

PVR.

@acrumley You should be able to achieve this using chaining. Could you please share the app xml or group aggregation configuration details available in attribute: connectionParameters in application xml?

@Peddapolu @neel193

Sure can. Here is how the endpoints are structured:

ORG ID 11343

→ Role 1 ID =79127340
→Role 2 ID =173491293084

ORGID 112343
→Role3 ID = 7894582735
→Role4 ID = 1632478645876

Need to collect list of 1-4 into the entitlement catalogue. However, you can see I am only getting two objects returned:

My structure:

Group Aggregation - Get OrganizationIds

Group Aggregation - Get Roles for each orgID

As you can see, I attempted to do the chaining, but IIQ things that two organization IDs equals 2 roles. However, I have to do a more “partitioning approach” where each org ID could return any number of roles to aggregate in.

Hi @acrumley ,

You can use parent end point configuration to get any number of roles with an organizationId.

Could you give more details about the issue you are facing with the parent endpoint configuration and check if the organizationId is getting retrieved properly from the first endpoint.

The parent endpoint is activating and the data is being retrieved. The syslog errors here show it is getting the two organization IDs. Then, the next API call to get the roles under the org is being chained properly.

However, it is grouping the sets of roles under the orgIDs rather than expanding them out into their separate rows for each roleId (see the “id” column)

See the lists inside the individual rows? That shouldn’t be happening, it needs to be expanded out. The “sets” of roles merged in those rows should be expanded out. That’s why I attempted the partition step.

Maybe I have to do some advanced pagination? That doesn’t seem right though. The chaining calls should work. However, the data isn’t getting transformed properly. Does this mean I have to do an After Action Rule?

Hi @acrumley ,

can you share the sample response of first endpoint.

Once check in the postman also , if the APIs are returning grouped values for an attribute.

If not you can modify the response attribute mapping to expand them.

Yes you can use the after operation rule to modify the response.

I have verified in Postman that they are not returning in lists but separated role object entities with the individual calls. It is the web service connector interpreting and binding them together under grouped organization IDs. It seems to believe that since there are two organization IDs returned from the first endpoint that means there are two roles.

I’m not trying to merge attributes together necessarily, but IIQ thinks that I am where since it only got 2 items from the parent endpoint, it will only create two items once the child endpoint is done

Hi @acrumley Can you share a sample JSON? I think you need to write the before operation rule for this use case.

Thanks,

PVR.

Hi @acrumley - Please check following documentation link- Multiple Independent Endpoints

Yes! Here a sample response from the first /organizations endpoint:

{
  "message": "OK",
  "firstPageUri": "https://api.everbridge.net/rest/organizations?pageNumber=1",
  "lastPageUri": "https://api.everbridge.net/rest/organizations?pageNumber=1",
  "page": {
    "pageSize": 102,
    "start": 1,
    "data": [
      {
        "lastModifiedTime": 1774865536493,
       
        "dataCenterId": 241901148045313,
        "showMessage": true,
        "organizationId": 88684095340675,
        ...
      },
      {
        "lastModifiedTime": 1774863636572,
        "dataCenterId": 241901148045313,
        "showMessage": true,
        "organizationId": 92979062636645,
		...
      }
    ],
    "totalCount": 2,
    "totalPageCount": 1,
    "currentPageNo": 1
  }
}

Here is a sample of the what is returned from the /roles endpoint scoped with the orgID

/roles/{organizationId}

{
  "message": "OK",
  "firstPageUri": "https://api.everbridge.net/rest/roles/88684095340675?pageNumber=1",
  "lastPageUri": "https://api.everbridge.net/rest/roles/88684095340675?pageNumber=1",
  "page": {
    "pageSize": 10,
    "start": 0,
    "data": [
      {
        "id": 88684095340731,
        "roleTemplate": "ORGANIZATION_ADMIN",
        "name": "Organization Admin"
      },
      {
        "id": 2396662081257493,
        "roleTemplate": "CUSTOMIZED",
        "name": "test Limit incidents",
      },
      {
        "id": 2396799520211012,
        "roleTemplate": "CUSTOMIZED",
        "name": "test Limit 2",
      }
    ],
    "totalCount": 3,
    "totalPageCount": 1,
    "currentPageNo": 1
  }
}

NOTE: The organizationID attribute is not returned in the Role objects (the children of the organization object)

So, is BEFORE provisioning rule the only thing I can do?

I tried to be cheecky with the Get-Partition with the partitions being the “organizationId” attribute, but no luck there.

Before the operation rule is the only option as per the JSON data. Since there is no direct, proper data b/w them , the API is not providing the expected results.

Thanks,

PVR.

@acrumley I checked the documentation but not able to find the partitioning details for group aggregations. Get Objects and Partitioning is defined for Accounts. Have you already validated this?

I attempted the Get Objects and Partitioning, but as the documentation describes, it only works for accounts.

Because I honestly don’t know how to tackle a Before Provisioning Rule, I attempted to do an After Provisioning rule to attempt to split up the coalesced lists into separate role objects. However, that did not work and I got the same data structure. Funny enough the “processedResponseObject” does return a list maps that define each role object, but IIQ does the coalescing after that…

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// This is the main map that will be returned by the rule.
Map updatedMapInfo = new HashMap();

// The 'processedResponseObject' is a List<Map> from a single API call.
// We just need to ensure it's not null and place it in the return map.
if (processedResponseObject != null) {
    
    // As you suggested, we can inject the organizationId from the endpoint URL here.
    // The 'requestEndPoint' object is available in the rule's context.
    String fullUrl = requestEndPoint.getFullUrl();

    // --- Example Logic to Extract Org ID from URL ---
    // This part is an example. You will need to tailor the parsing logic
    // to match your exact URL structure (e.g., ".../roles/{organizationId}").
    String organizationId = null;
    try {
        // Assuming a URL structure like ".../roles/12345"
        String[] urlParts = fullUrl.split("/");
        if (urlParts.length > 0) {
            organizationId = urlParts[urlParts.length - 1];
        }
    } catch (Exception e) {
        // Log an error if the URL format is not what we expect.
        log.error("Could not parse organizationId from URL: " + fullUrl, e);
    }
    // --- End of Example Logic ---
    
    // If we successfully found an organizationId, add it to every role map.
    if (organizationId != null @and !organizationId.isEmpty()) {
        for (Map roleMap : processedResponseObject) {
            roleMap.put("organizationId", organizationId);
        }
    }

    // Place the (now potentially enriched) list into the return map under the "data" key.
    updatedMapInfo.put("data", processedResponseObject);

} else {
    // If the response was empty, return an empty list to avoid errors.
    updatedMapInfo.put("data", new ArrayList());
}
log.error(updatedMapInfo);
// Return the wrapper map. The connector will process the contents of "data".
return updatedMapInfo;

If you have guidance on the before provisioning rule, I would greatly appreciate it.

EDIT: For future readers, I meant “Before Operation” rule

@acrumley You need to try with before and after operation rule, not before/after provisioning rules. These are available inside endpoint configuration.

For your usecase, may be you can try pagination kinda logic using before rule and after rule. What i meant is:

  • You can create a ruler runner task and make an API call to get all organization id and store it in custom object.
  • then in before operation rule, check if hasMore value is set to true.. then get the next organization id and update the url.
  • then in after operation rule, check if custom objects has any entry left, then set hasMore = true in application.

Give it a try, if this works.

Yes I misspoke. I meant that I was trying an “After Operation” rule. Thank you for your guidance on this subject. I will experiment further with this architecture.

through this process, I’ve learned a lot about the web services connector and its limitations.

Hi @acrumley Yep, after operation rules is a good option for your use case.

Thanks,

PVR.