Update URL in a web service connector

Hello developers

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:

https://myserver.com/test/nameOfEntitlement?action=add&user=myuser%40.domain.com&parts=all

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?

I appreciate your help.

Regard

@jacob_islas ,

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;

Hope this helps.

1 Like

Thank you for your quick response

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;

Thank you for your response

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.

<ProvisioningPlan nativeIdentity=\"19865\">
    <AccountRequest application=\"***** [source]\" nativeIdentity=\"[email protected]\" op=\"Create\">
        <AttributeRequest name=\"groups\" op=\"Add\" value=\"Support_TI\"></AttributeRequest>
        <AttributeRequest name=\"groups\" op=\"Add\" value=\"Aux_TI\"></AttributeRequest>
    </AccountRequest>
</ProvisioningPlan>

And the error is the following:

“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:

https://myserver.com/test/Support_TI?action=add&[email protected]$parts=all
And next:
https://myserver.com/test/Aux_TI?action=add&[email protected]$parts=all

I hope you can help me

Hello

Can anyone recommend what action to take to generate a new endpoint for each entitlement added please?

Regards

I think if you mark this option to false: Add or Remove Entitlements in a Single Request

Then it would create separate API call for each entitlement addition or removal. Lemme know if that helps