Hi All,
We have integrated ServiceNow Service Desk Service Request in SailPoint IdentityNow for disconnected sources. We are generating REQ request for provisioning and deprovisioning and also mapping IDN with REQ ticket status.
In Leaver scenario, when an identity in deprovisioned lifecycle state then IDN raise a REQ type ticket for the disconnected sources. If identity have access to 4 different disconnected sources, 4 RITM tickets are created and tagged with 4 SCTASK for the same REQ request.
We have tested below 3 test scenarios:
Leaver for user with multiple disconnected systems - all SCTASK marked closed complete
Leaver for user with multiple disconnected systems - all SCTASK marked closed incomplete
Leaver for user with multiple disconnected systems - some all SCTASK marked closed complete and some SCTASK marked closed incomplete.
1st and 2nd scenarios are working as expected.
But, for the 3rd scenario, since the some of the SCTASK are marked as closed incomplete for that reason the REQ is status also set as closed incomplete even we set some of RITM as closed completed (Also ServiceNow system changing the closed completed RITM tickets status as closed incomplete). Since the REQ is set as closed incomplete the identity’s disconnected sources are not removed for the accounts.
I also have few questions here -
Can we generate separate REQ request for all the disconnect source the identity has access?
Can we only remove or leave specific source according to the RITM ticket status?
Based on what you are describing would be managed on the ServiceNow Workflow side. I would review the workflow that is being called in ServiceNow that the service desk integration is using and ensure that the flow is addressing the 3rd user correctly.
We have a system that each application listed creates a new TASK for the team that needs to add/remove access but are all the same REQ.
For this particular use case, it’s important to know what the scripted REST endpoint on the ServiceNow side is actually doing. Here’s the script showing that
/**
* (c) Copyright 2019 SailPoint Technologies, Inc., All Rights Reserved.
*/
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
// main
var request_body = request.body.nextEntry();
var requestedItems = request_body.items || [];
var returnRitm = false;
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("SailPoint Cart Js API - Create Ticket: Number of catalog item recevied in the request : "+ requestedItems.length);
var rc;
var cartId = gs.generateGUID();
var cart = new sn_sc.CartJS(cartId);
if (!gs.nil(cart)) {
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("SailPoint Cart Js API - Create Ticket: Cart created using GUID ["+ cartId + "], Cart id ["+ cart.getCartID() + "], Requested for ["+ requestedItems[0].variables.requested_for + "].");
var req={};
for (var i=0; i<requestedItems.length; i++) {
var itemDetails = requestedItems[i];
var itemId = itemDetails.sysparm_id;
// When true, webservice will return RITM number instead of REQ number in the response.
if (itemDetails.variables.track_ritm == "true") {
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("track_ritm is set to true." );
returnRitm = true;
}
cart = new sn_sc.CartJS(cartId);
try {
var item = cart.addToCart(itemDetails);
} catch (err) {
var error_message = err.message;
x_sap_sdim.SailPointForServiceDeskLogger.get().error("Error Occured: " + error_message);
throw "Ensure valid catalog items details provided for catalog item: " + itemId;
}
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("SailPoint Cart Js API - Create Ticket: Added catalog item with sys id ["+ itemId + "] to the cart.");
}
// Perform the cart checkout simultaneously.
rc = cart.submitOrder(req);
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("SailPoint Cart Js API - Create Ticket: Placed request details - " + JSON.stringify(rc));
} else {
x_sap_sdim.SailPointForServiceDeskLogger.get().error("SailPoint Cart Js API - Create Ticket: Cart creation failed.");
var cartGenError = new sn_ws_err.ServiceError();
cartGenError.setStatus(500);
cartGenError.setMessage("Cart creation failed.");
return cartGenError;
}
x_sap_sdim.SailPointForServiceDeskLogger.get().debug("SailPoint Cart Js API - Create Ticket: Ticket number is ["+ rc.request_number + "]");
// Get the ticket number from the response.
var requestNumber = rc.request_number;
if (gs.nil(requestNumber)) {
x_sap_sdim.SailPointForServiceDeskLogger.get().error("SailPoint Cart Js API - Request number not found in the response. " + JSON.stringify(rc));
return new sn_ws_err.NotFoundError("SailPoint Cart Js API - Request number not found in the response. " + JSON.stringify(rc));
}
// Prepare response
response = {"request_number": rc.request_number};
// Return REQ number
if (returnRitm === false) {
response = {"request_number": rc.request_number};
return response;
}
var responseJson = "";
var item1 = [];
var ritmRecord = new GlideRecord('sc_req_item');
ritmRecord.addQuery('request', rc.request_id);
ritmRecord.query();
while (ritmRecord.next()) {
var variables = ritmRecord.variables.getElements();
for (var j = 0; j < variables.length; j++) {
if (variables[j] != '' && variables[j] != undefined) {
var question = variables[j].getQuestion();
var label = question.getLabel();
var value = question.getDisplayValue();
if (label.equals('Tracking ID')) {
item1.push({trackingId: value, ticketNumber: ritmRecord.number.toString()});
break;
}
}
}
}
response = {items:item1};
return response;
})(request, response);
Here’s a summary of what I see it doing
The request body sent from SailPoint might contain one or multiple items in the items property of the request body. For each item in the items property, it will add them to the cart. Once that is done, it will submit the order.
The result of this is that everything in the items property of the request body will each have their own RITM and fall under the same REQ record. In theory, you could modify this code to make each record have its own REQ, however, SailPoint only has a single account activity for tracking all these, so you can’t really do that because it will lose track of the other REQs that are generated.
So basically, scenario 3 that you describe just isn’t something that can be done IF you are tracking at the REQ level. I’m not sure exactly how SailPoint will behave if you are tracking at the RITM level. That might be worth trying out.