I am configuring a web service connector for an application where entitlements must be assigned, but for this it is necessary to modify the end point by placing some parameters such as the name of the entitlement and the email of the user account, escaping the “@” character, for example:
I have seen that it is with a before provisioning rule, however I am confused about how the structure of this rule would be. Can someone please guide me?
By implementing this WebService Before Operation Rule, you can dynamically modify the endpoint URL to include necessary parameters, ensuring that your web service calls are constructed correctly for assigning entitlements.
Example WebService Before Operation Rule Code
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import java.util.List;
import java.util.Map;
import java.net.URLEncoder;
// Initialize variables
String userEmail = null;
String entitlementName = null;
// Retrieve user's email and entitlement name from the provisioning plan
if (provisioningPlan != null) {
// Iterate over account requests
List<AccountRequest> accountRequests = provisioningPlan.getAccountRequests();
for (AccountRequest accountRequest : accountRequests) {
// Get the native identity (user's account identifier)
if (accountRequest.getNativeIdentity() != null) {
userEmail = accountRequest.getNativeIdentity();
}
// Iterate over attribute requests to find email and entitlement name
List<AttributeRequest> attrRequests = accountRequest.getAttributeRequests();
if (attrRequests != null) {
for (AttributeRequest attrReq : attrRequests) {
String attrName = attrReq.getName();
Object attrValue = attrReq.getValue();
// Retrieve the user's email
if ("email".equalsIgnoreCase(attrName) && attrValue != null) {
userEmail = attrValue.toString();
}
// Retrieve the entitlement name
if ("entitlementName".equalsIgnoreCase(attrName) && attrValue != null) {
entitlementName = attrValue.toString();
}
}
}
}
}
// Handle missing email
if (userEmail == null || userEmail.isEmpty()) {
throw new Exception("User email is not available in the provisioning plan.");
}
// Escape the '@' character in the email
String escapedEmail = userEmail.replace("@", "%40");
// Handle missing entitlement name
if (entitlementName == null || entitlementName.isEmpty()) {
throw new Exception("Entitlement name is not available in the provisioning plan.");
}
// URL-encode the entitlement name
String encodedEntitlementName = URLEncoder.encode(entitlementName, "UTF-8");
// Construct the new endpoint URL
String baseUrl = "https://myserver.com/test/";
String newEndpointUrl = baseUrl + encodedEntitlementName + "?action=add&user=" + escapedEmail + "&parts=all";
// Set the new endpoint URL in the requestEndPoint
requestEndPoint.setFullUrl(newEndpointUrl);
// Optionally, log the new URL for debugging
log.info("Modified endpoint URL: " + newEndpointUrl);
// Return the modified requestEndPoint
return requestEndPoint;
This example is very helpful to me, just one question, if the identity email is not included in the provisioning plan and the nativeIdentity is not the email, how can I get it?
Hi @jacob_islas ,
If the user’s email is not included in the provisioning plan and the ‘nativeIdentity’ is not the email, you can retrieve the email from the Identity object within IdentityNow, using the IdentityService API or the SailPoint Object Model. Below is a sample updated Before Provisioning Rule to fetch the email from the Identity object if it’s not directly provided in the provisioning plan referenced from @officialamitguptaa sample rule.
Hope this helps!!
import sailpoint.object.Identity;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.api.IdentityService;
import sailpoint.api.SailPointContext;
import sailpoint.tools.GeneralException;
import java.util.List;
import java.util.Map;
import java.net.URLEncoder;
// Initialize variables
String userEmail = null;
String entitlementName = null;
String nativeIdentity = null;
// Get the current SailPoint context (this is automatically available in the rule)
SailPointContext context = context;
// Retrieve user's email and entitlement name from the provisioning plan
if (provisioningPlan != null) {
// Iterate over account requests
List<AccountRequest> accountRequests = provisioningPlan.getAccountRequests();
for (AccountRequest accountRequest : accountRequests) {
// Get the native identity (user's account identifier)
if (accountRequest.getNativeIdentity() != null) {
nativeIdentity = accountRequest.getNativeIdentity();
}
// Iterate over attribute requests to find email and entitlement name
List<AttributeRequest> attrRequests = accountRequest.getAttributeRequests();
if (attrRequests != null) {
for (AttributeRequest attrReq : attrRequests) {
String attrName = attrReq.getName();
Object attrValue = attrReq.getValue();
// Retrieve the user's email if present in the plan
if ("email".equalsIgnoreCase(attrName) && attrValue != null) {
userEmail = attrValue.toString();
}
// Retrieve the entitlement name
if ("entitlementName".equalsIgnoreCase(attrName) && attrValue != null) {
entitlementName = attrValue.toString();
}
}
}
}
}
// If email is not in provisioning plan, retrieve from Identity object
if (userEmail == null || userEmail.isEmpty()) {
if (nativeIdentity != null) {
try {
IdentityService identityService = new IdentityService(context);
Identity identity = identityService.getIdentityByAccountId(provisioningPlan.getTarget(), nativeIdentity);
// Retrieve the email from the Identity object
if (identity != null) {
userEmail = identity.getAttribute("email");
}
// If email is still missing, handle the error
if (userEmail == null || userEmail.isEmpty()) {
throw new Exception("User email could not be found in the provisioning plan or the Identity object.");
}
} catch (GeneralException e) {
throw new Exception("Error retrieving Identity: " + e.getMessage());
}
} else {
throw new Exception("Native identity is not available in the provisioning plan.");
}
}
// Escape the '@' character in the email
String escapedEmail = userEmail.replace("@", "%40");
// Handle missing entitlement name
if (entitlementName == null || entitlementName.isEmpty()) {
throw new Exception("Entitlement name is not available in the provisioning plan.");
}
// URL-encode the entitlement name
String encodedEntitlementName = URLEncoder.encode(entitlementName, "UTF-8");
// Construct the new endpoint URL
String baseUrl = "https://myserver.com/test/";
String newEndpointUrl = baseUrl + encodedEntitlementName + "?action=add&user=" + escapedEmail + "&parts=all";
// Set the new endpoint URL in the requestEndPoint
requestEndPoint.setFullUrl(newEndpointUrl);
// Optionally, log the new URL for debugging
log.info("Modified endpoint URL: " + newEndpointUrl);
// Return the modified requestEndPoint
return requestEndPoint;
I have created and associated the rule to the connector and it is now returning the correct URL. However, when assigning an access profile that contains more than one entitlement, the rule returns the requestEndPoint but with all the entitlements that are in the provisioning plan. For example, this is the plan for a request.
“Exception while updating account.Url: https://myserver.com/test/[Support_TI,%20Aux_TI]?action\u003dadd\u0026user\[email protected]\u0026parts\u003dall, Message: 404 : Not Found : {"status":"error","Data":{"status":"error","exceptionType":"com.ibm.bpm.wle.api.NoSuchGroupException","errorNumber":"CWTBG0006E","errorMessage":"CWTBG0006E: Group \u0027[Support_TI, Aux_TI]\u0027 not found.","errorMessageParameters":["[Support_TI, Aux_TI]"],"responses":null,"errorData":null}}, HTTP Error Code: 404”]
How can I make it so that when I generate the new requestEndPoint it creates one for each entitlement?, That is, first I generate the URL: