It seems most Provisioning has been fixed for the new request center, sending 1 request even if requesting multiple access objects through the request center. However, when removing multiple access objects in a Certification Campaign provisioning is still bundled into 1 operation for multiple accesses being revoked.
Is this the expected behaviour?
Currently we’re implementing a Web Service Connector where the PATCH operation only permits removing 1 entitlement per API request. How can we implement logic into our BeforeProvisioning Rule to allow sending multiple API requests if the provisioning plan contains more than 1 object (i.e as the situation with the current Certification behaviour).
Yes, this is the current behavior for certifications, which are a separate process from request center. We would treat any changes to the certification process as an enhancement, which will need to be an idea in ideas.sailpoint.com. Can you please submit one with your desired behavior for certifications revoking access.
As for the before provision rule to send multiple APi requests, could you just loop on the entitlements in the provisioning plan and send a patch request per entilement.
I’m not familiar enough with rules to know how to do this. I think there is an HTTP client you can use within a rule, so you could just loop over each account request and send the patch API call to the target source for each account request. However, I’m not sure how that will impact the provisioning plan…
Is it possible to loop over each account request and in the rule then create separate provisioningPlans without making several custom PATCH API calls? We already have a PATCH operation configured for the source in the GUI so we want to avoid setting up several API calls within the rule.
Maybe you have some input regarding this? @tyler_mairose
I realised just now that the only difference in Certification Campaigns is that the request object values in a campaign is of type PersistentArrayList (if there are more than 1 access-item being revoked), while all other requests outside of Certifications are of type String. My initial thought was that objects from a campaign would be bundled inside of 1 request and therefore an ArrayList, but it seems like this is not the case.
My solution to this was to match these 2 types, and if the request was of type PersistentArrayList i would loop through the requestedItemsList and send a JsonBody equivalent to these items. I realised that the API call was in fact working (200), but I was still receiving an error in IDN.
I then started wondering if perhaps campaigns actually do send 1 request per access-item and so I tried sending my requests from campaigns to a Webhook in stead. The result: It does, in fact, send 1 request per Access-object being removed. The only difference, like I said before, is that these are of type PersistentArrayList.
The error I am receiving now is because the API call finishes all tasks in the 1st API request, crashing on the 2nd request where there no longer is any object to be found (404).
Code as of now:
if (provisioningPlan != null && provisioningPlan.getAccountRequests().get(0).getAttributeRequests().get(0).getValue().getClass() == String.class) {
String requestedAccess = provisioningPlan.getAccountRequests().get(0).getAttributeRequests().get(0).getValue();
String[] entArr = requestedAccess.split(" - ");
String jsonBody = "[\n" +
"{\n" +
"\"op\": \"RemoveById\",\n" +
"\"path\": \"/roleAndCompany\",\n" +
"\"value\": {\n" +
"\"roleId\": \"" + entArr[0] + "\",\n" +
"\"companyId\": \"" + entArr[1] + "\",\n" +
"}\n" +
"}\n" +
"]";
Map body = requestEndPoint.getBody();
body.put("jsonBody", jsonBody);
requestEndPoint.setBody(body);
} else if (provisioningPlan != null && provisioningPlan.getAccountRequests().get(0).getAttributeRequests().get(0).getValue().getClass() == sailpoint.tools.xml.PersistentArrayList.class) {
List requestedAccessList = provisioningPlan.getAccountRequests().get(0).getAttributeRequests().get(0).getValue();
StringBuilder jsonBodyBuilder = new StringBuilder("[\n");
for (int i = 0; i < requestedAccessList.size(); ++i) {
String[] entArr = requestedAccessList.get(i).toString().split(" - ");
// Build JSON body for each item in the list
String itemJsonBody =
"{\n" +
" \"op\": \"RemoveById\",\n" +
" \"path\": \"/roleAndCompany\",\n" +
" \"value\": {\n" +
" \"roleId\": \"" + entArr[0] + "\",\n" +
" \"companyId\": \"" + entArr[1] + "\"\n" +
" }\n" +
"}";
jsonBodyBuilder.append(itemJsonBody);
// Add a comma and newline for all items except the last one
if (i < requestedAccessList.size() - 1) {
jsonBodyBuilder.append(",\n");
}
}
jsonBodyBuilder.append("\n]");
Map body = requestEndPoint.getBody();
body.put("jsonBody", jsonBodyBuilder.toString());
requestEndPoint.setBody(body);
} else {
log.info("Rule: plan is null");
}
return requestEndPoint;