Webservice connector before provisioing Rule issue

HI

The provisioning rule outlined below is based on the following two points. However, it appears that the code is being skipped, resulting in no updates to the target. Is there any issue in the rule.

  1. Sync should occur only when emailAddr is not blank and not NO_EMAIL.

  2. when the request is modified emailAddr, oprid and destEmailAddr = @@testnet.test.asin

import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.Application;
import sailpoint.object.Identity;
import sailpoint.connector.Connector;
import java.util.List;
import java.util.ArrayList;

log.info("Before Provisioning Rule: Validate Email Start");

if (plan != null && plan.getAccountRequests() != null) {

    List accountRequests = plan.getAccountRequests();
    List requestsToRemove = new ArrayList();

    for (Object accReqObj : accountRequests) {
        AccountRequest accReq = (AccountRequest)accReqObj;
        boolean removeThisRequest = false;
        String removalReason = "";

        if (AccountRequest.Operation.Create.equals(accReq.getOperation()) || AccountRequest.Operation.Modify.equals(accReq.getOperation())) {

            AttributeRequest emailAttrReq = accReq.getAttributeRequest("emailAddr");

            if (emailAttrReq != null && emailAttrReq.getValue() instanceof String && "NO_EMAIL".equalsIgnoreCase((String)emailAttrReq.getValue())) {
                removeThisRequest = true;
                removalReason = "emailAddr attribute value is 'NO_EMAIL'";
            } else {
                if (emailAttrReq == null) {
                    removeThisRequest = true;
                    removalReason = "Mandatory emailAddr attribute is missing";
                } else {
                    Object emailValue = emailAttrReq.getValue();
                    boolean valueIsInvalid = false;

                    if (emailValue == null) {
                        valueIsInvalid = true;
                    } else if (emailValue instanceof String) {
                        if (((String)emailValue).trim().isEmpty()) {
                            valueIsInvalid = true;
                        }
                    }

                    if (valueIsInvalid) {
                        removeThisRequest = true;
                        removalReason = "Mandatory emailAddr attribute value is null or empty after cleanup";
                    } else {
                        // -------------------------------------------------------
                        // NEW LOGIC: Email is valid
                        // -------------------------------------------------------
                        Identity identity = plan.getIdentity();
                        if (identity != null) {
                            // 1. Retrieve Attributes from Identity
       
                            String uid = identity.getStringAttribute("uid");
                            String oprid = identity.getStringAttribute("oprid");

                            // 2. Construct destEmailAddr ($uid@mednet.test.asin)
                            if (uid != null) {
                                String destEmailAddr = uid + "@testnet.test.asin";
                                // Add to Plan (Operation.Set ensures it is sent)
                                accReq.add(new AttributeRequest("destEmailAddr", ProvisioningPlan.Operation.Set, destEmailAddr));
                            } else {
                                log.warn("Rule HCMWriteBack: 'uid' attribute is missing for identity " + identity.getName());
                            }

                            // 3. Add oprid to Plan
                            if (oprid != null) {
                                accReq.add(new AttributeRequest("oprid", ProvisioningPlan.Operation.Set, oprid));
                            } else {
                                log.warn("Rule testkrule: 'oprid' attribute is missing for identity " + identity.getName());
                            }
                            
                            // Note: emailAddr is already present as 'emailAttrReq'
                        } else {
                            log.warn("Rule BRBack: Could not retrieve Identity object from Plan.");
                        }
                    }
                }
            }

            if (removeThisRequest) {
                log.error("Marking AccountRequest for '" + accReq.getNativeIdentity() + "' for removal from plan. Reason: " + removalReason);
                requestsToRemove.add(accReq);
            }
        }
    }

    if (!requestsToRemove.isEmpty()) {
        log.info("Removing " + requestsToRemove.size() + " account requests from the provisioning plan.");
        accountRequests.removeAll(requestsToRemove);
    }

} else {
    log.info("Plan is null or has no requests.");
}
log.info("Before Provisioning Rule: Validate Email and Filter Plan End");

before we jump into the code, where did you attach this code? is this SAS based connector or VA? you add more loggers?

it is a VA based connector and attached beforeProvisioningRule in the web service connector.

add more loggers and try to work your login in the below :

import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.Application;
import sailpoint.object.Identity;
import sailpoint.connector.Connector;
import java.util.List;
import java.util.ArrayList;

log.info(ā€œBefore Provisioning Rule: Validate Email Startā€);

if (plan != null && plan.getAccountRequests() != null) {

List accountRequests = plan.getAccountRequests();
List requestsToRemove = new ArrayList();

for (AccountRequest accReq : accountRequests) {
    
    boolean removeThisRequest = false;
    String removalReason = "";

    if (AccountRequest.Operation.Create.equals(accReq.getOperation()) || AccountRequest.Operation.Modify.equals(accReq.getOperation())) {
		List updatedAttrList = new ArrayList();
		for (AttributeRequest attributeRequest : accReq.getAttributeRequests()) {
				String name = attributeRequest.getName();
				String value = attributeRequest.getValue();
				if(!name.equalsIgnoreCase(emailAddr))
					updatedAttrList.add(attributeRequest)
				else {
				if(name.eaqualsIgnoreCase(emailAddr) && value != null && value.eaqualsIgnoreCase(NO_EMAIL)){
					//removal logic
				}
				}
				accReq.setAttributeRequests(updatedAttrList);
		}

        if (removeThisRequest) {
            log.error("Marking AccountRequest for '" + accReq.getNativeIdentity() + "' for removal from plan. Reason: " + removalReason);
            requestsToRemove.add(accReq);
        }
    }
}

if (!requestsToRemove.isEmpty()) {
    log.info("Removing " + requestsToRemove.size() + " account requests from the provisioning plan.");
    accountRequests.removeAll(requestsToRemove);
}

} else {
log.info(ā€œPlan is null or has no requests.ā€);
}
log.info(ā€œBefore Provisioning Rule: Validate Email and Filter Plan Endā€);

Hi @Pkkumar ,

Can you make sure your rule matches the input arguments shown in this documentation - Web Services Before Operation Rule | SailPoint Developer Community

I see you make references to ā€˜plan’ instead of ā€˜provisioningPlan’. There’s also an example on how to iterate through the account requests and attribute requests in the provisioningPlan argument that you could follow.

Let me know if that helps!

Thanks,

Liam

If this rule needs to run during the Create operation, you can attach it directly to the HTTP operation using the ā€œbeforeRule" key.

I think we need to clarify what type of rule we are discussing here first:

Is this a BeforeProvisioning Rule or a BeforeOperation Rule for the WebService? There is a distinction here in that BeforeProvisioning rules are run in the Cloud and require review by SailPoint and the BeforeOperation rules is a Connector Rule, and therefore runs on the VA.

Based on what I see in the rule, this appears to be a BeforeProvisioning rule. If this is the case, it would need to be reviewed and installed by SailPoint first before you could use it as the BeforeProvisioning Rule. This may be why it is not getting called in this case.

It seems that the other responses are discussing the BeforeOperation rules, which can be uploaded directly and added to the HTTP Operations of the WebService Connector without SailPoint PS.

For more information, you can review the Rule guide found here: Rules | SailPoint Developer Community

While more info is expected as mentioned by others above, I wanted to point out something here. If you are cancelling an update in BP rule based on certain condition, that means the Modify operation triggered by the attribute sync will not complete which means the target attribute will not be updated to match the identity attribute that syncs to it. This will result in attribute sync continuously being triggered which will keep on getting cancelled by the BP rule. This is not a good design, especially when you would have a large number of updates being stopped

The Attribute Sync will come into action after BP. so if you are excluding something in the BP, the attr sync process will never go thru for that attr.