Hi everyone,
We have configured “Test” a web service API based source in ISC and able to load the users and roleids/teamids entitlement information but getting error "\“Message\”:\“A non-empty request body is required.\ error” during HTTP “Remove Roles” and “Remove Teams” operations.
We have defined HTTP remove operations and configured a web service before operation rule
Example: During user access review using PUT API call if the user is having 3 roleIds/teamIds multivalued multiple entitlements then the reviewer tries to revoke one or more roleIds/teamIds from the user then the rest remaining should be updated accordingly after removal of the one or more roleIds/teamIds from the user.
Postman API looks like as below:
the method is PUT. so any details sent in payload are retained.So the above payload indicates that role 10 & team 12 are retained / created to the user. All other roles and teams are removed. if user is part of 3 teams with 3 roles the get user payload shows"roleIds": [12,13,15],“teamIds”: [10,11,20],if you want to remove roles 13,15 or teams 11 & 20 u should update user and pass only what you want to retain i.e.,“roleIds”: [ 12 ],“teamIds”: [ 10 ],
Method: PUT
Payload:{“firstName”: “test1”,“lastName”: “Sailpoint”,“active”: true,“email”: “test1@f5sailpoint.com”,“cellPhoneNumber”: “9123456789”,“country”: “India”,“expirationDate”: “2028-10-25T18:30:00Z”,“jobTitle”: “test user2”,“other”: “otherfieldinfo”,“phoneNumber”: “22221111”,“roleIds”: [12],“teamIds”: [10],“localeId”: 1}Success Repsonse:Response Code: 204Response Body - Null / no Response. Only response code.
HTTP: PUT Payload:
{
“roleIds”: $response.roleIds$,
“removeRoleIds”: $plan.roleIds$,
“teamIds”: $response.teamIds$,
“firstName”: “$response.firstName$”,
“lastName”: “$response.lastName$”,
“email”: “$response.email$”,
“phoneNumber”: “$response.phoneNumber$”,
“cellPhoneNumber”: “$response.cellPhoneNumber$”,
“jobTitle”: “$response.jobTitle$”,
“other”: “$response.otherInfo$”,
“country”: “$response.country$”,
“active”: $response.active$,
“expirationDate”: “$response.expirationDate$”,
“allowedIpList”: $response.allowedIpList$,
“localeId”: $response.localeId$
}
web service before provisioning rule:
<?xml version='1.0' encoding='UTF-8'?> Before-operation rule to clean roleIds/teamIds and update user attributes.import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import sailpoint.tools.Util;
import connector.common.JsonUtil;
log.info("CheckmarxBeforeOp: Start processing");
if (requestEndPoint == null) {
log.warn("requestEndPoint is null");
return requestEndPoint;
}
Map bodyMap = requestEndPoint.getBody();
if (bodyMap == null) {
bodyMap = new java.util.HashMap();
}
Object jsonBodyObj = bodyMap.get("jsonBody");
String jsonBody = null;
if (jsonBodyObj instanceof String) {
jsonBody = ((String) jsonBodyObj).trim();
}
if (Util.isNullOrEmpty(jsonBody)) {
jsonBody = "{}";
}
Map jsonMap = null;
try {
jsonMap = JsonUtil.toMap(jsonBody);
} catch (Exception e) {
log.error("JSON parse error", e);
jsonMap = new java.util.HashMap();
}
// --- Update attributes ---
if (provisioningPlan != null && provisioningPlan.getAccountRequests() != null) {
List accReqs = provisioningPlan.getAccountRequests();
for (int i = 0; i < accReqs.size(); i++) {
Object o = accReqs.get(i);
ProvisioningPlan.AccountRequest accReq = (ProvisioningPlan.AccountRequest) o;
if (accReq.getAttributeRequests() == null) continue;
List atts = accReq.getAttributeRequests();
for (int j = 0; j < atts.size(); j++) {
Object a = atts.get(j);
ProvisioningPlan.AttributeRequest attReq = (ProvisioningPlan.AttributeRequest) a;
String name = attReq.getName();
Object val = attReq.getValue();
if (val == null) continue;
String lower = name.toLowerCase();
if (lower.equals("firstname") && val instanceof String) {
jsonMap.put("firstName", ((String)val).trim());
} else if (lower.equals("lastname") && val instanceof String) {
jsonMap.put("lastName", ((String)val).trim());
} else if (lower.equals("email") && val instanceof String) {
jsonMap.put("email", ((String)val).trim());
} else if (lower.equals("cellphonenumber") && val instanceof String) {
jsonMap.put("cellPhoneNumber", ((String)val).trim());
} else if (lower.equals("phonenumber") && val instanceof String) {
jsonMap.put("phoneNumber", ((String)val).trim());
} else if (lower.equals("jobtitle") && val instanceof String) {
jsonMap.put("jobTitle", ((String)val).trim());
} else if (lower.equals("other") && val instanceof String) {
jsonMap.put("other", ((String)val).trim());
} else if (lower.equals("country") && val instanceof String) {
jsonMap.put("country", ((String)val).trim());
} else if (lower.equals("active") && val instanceof Boolean) {
jsonMap.put("active", val);
} else if (lower.equals("localeid") && val instanceof Integer) {
jsonMap.put("localeId", val);
}
}
}
}
// --- Remove roleIds ---
List removeRoleIds = (List) jsonMap.get("removeRoleIds");
if (removeRoleIds != null) {
List existingRoles = (List) jsonMap.get("roleIds");
if (existingRoles == null) existingRoles = new ArrayList();
List newRoles = new ArrayList();
for (int i = 0; i < existingRoles.size(); i++) {
Object rid = existingRoles.get(i);
if (!removeRoleIds.contains(rid)) newRoles.add(rid);
else log.info("Removing roleId → " + rid);
}
jsonMap.put("roleIds", newRoles);
jsonMap.remove("removeRoleIds");
}
// --- Ensure teamIds exists ---
List teamIds = (List) jsonMap.get("teamIds");
if (teamIds == null) teamIds = new ArrayList();
jsonMap.put("teamIds", teamIds);
// --- Ensure jsonMap is not empty ---
if (jsonMap.isEmpty()) jsonMap.put("dummy", "placeholder");
// --- Render JSON ---
String newJsonBody = JsonUtil.render(jsonMap);
log.info("Final JSON → " + newJsonBody);
bodyMap.put("jsonBody", newJsonBody);
requestEndPoint.setBody(bodyMap);
return requestEndPoint;
]]>