Provisioning Form Evaluation in custom code

I am using IIQ 8.4p2

I would like to know if anyone knows how to - in a custom workflow or anywhere else in code - load a form object and have it evaluated. That is to say that form field values are evaluated (whether they be straight string/values, scripts, etc.). OOTB workflows pick the form either from the role object or from the application - I’d like to be able to have the form that is selected be controlled by other means.

Do you want provisioning policy form evaluated? If Yes then all you need to do is create a provisioning plan (containing application / role access that has provisioning policy configured) and then in the next step call Identity Request Initialize workflow passing this plan as argument with other required arguments like identityName etc.. This workflow has all the steps that compiles plan (Compile Project), evaluates provisioning forms (Do Provisioning Forms) , Build Approval Set etc.

If you need any other form to be loaded then you can add a step with Approval and Form. You can instead reference the form object as well. Once you collect all the data on Form you can have a step after that to update provisioning plan based on data collected on the form

 <Step icon="Approval" name="Display Form for Update" posX="107" posY="115">
    <Approval mode="serial" owner="ref:sessionOwner" return="DataInput1" send="DataInput1,DataInput2,DataInput3 ">
      <Arg name="workItemDescription" value="Collect Addtional Attribute Data from User"/>
      <Arg name="launcher" value="ref:launcher"/>
      <Form>
        <Attributes>
//Add your Form attributes and fields here

Thank you for your reply… what you propose might work or not, so let me describe a little better what I’m looking for.

Custom forms can be used to specify constants for values as well as computed values through scripts and whatnot. I’m looking to use picking a form at provisioning time (whether that be inside a workflow or otherwise) so that I can manage many account flavors for one applications. Having one big glob of code for all the account flavors is not ideal and can get messy, not to mention that any new flavor addition requires regression testing, etc.

I might be wrong but application provisioning policies are nice but heavily tilted to a single flavor - but having a form per operation is nice and desirable. Role policies have some benefits but fire on every refresh don’t support operation specific application operation (e.g. update) - understandably as its a role.

I’d want to be able to say when your doing operation X for flavor of account Y use form Z. Fetch all of the variables needed for form evaluation and have SailPoint figure out and calculate the fields as it does in other scenarios it already handles.

Will what you propose work if none of the fields are configured without user input - basically get “auto-approved” and then filled out based on the logic for the fields?

Just add a little more context - I’d want to define my forms in the “Global Setting” → “Forms”
Look them up / fetch them and evaluate them.

@maroosisSailpoint Could you please provide more details when you say this: “I’d want to be able to say when your doing operation X for flavor of account Y use form Z. Fetch all of the variables needed for form evaluation and have SailPoint figure out and calculate the fields as it does in other scenarios it already handles.”

In case you want to have a form for each access, you can configure modify policy or for roles attach a provisioningpolicy..I might not ae able to understand what exactly you want to achieve by loading/evaluating forms in custom.. either you use OOTB or forms in code, both will get inputs from user. In case you want it to auto populate, why do you need a form, you can easily set it using Map or List and then pass them to your code.

At this time I don’t want user input, I just want to use the Form as a means to encapsulate code and values. I might want user input later - but there’s not guarantee there so I’m not tied to that as a req.

For example, say I want to create an “admin” AD account and a “regular user” account:

  • they might (will in my case) have different lifecycle (already know how I’d go about this one)
  • have different naming conventions applied
  • and different field values whose constant or code will be different

I’m going to have like requirements for several applications. Setting and identifying an account type/flavor is easy enough but once you have several flavor types I find that:

  • pre-provisioning gets large - any change to it has the risk of breaking the other flavors
  • using application forms means that each attribute needs logic for each flavor - not much better
  • role forms could work but then there frequency of form evaluation and the fact that each attribute on the form will need to know the operation. There are other nuances in the role based form that aren’t relevant to the whole here
  • If I have code modify the form in a workflow I’m still writing this big glob to deal with all of the variantes

Having the ability in a workflow for instance to say:

  • the account flavor is X and the plan operation is Y
    • load form with name Z - pass in the objects it requires and have the form values computed and add/replace to the plan - be they straight up strings or bean sheal, etc.

Custom objects are nice for string value/constants but what about when logic is needed - the Form construct already has all of that.

What other ways can sailpoint handle multiple account variants for the same cube?

Duplicating the Application definition feels like a bad approach - now i have entitlement duplication and that’s its own other ball game.

Please if I am missing something let me know.

@maroosisSailpoint We did this using a same form → nested field value.. we create two libraries one for regular user and other for admin user.. we had just one create form which calls the attached field value. based on the user type, we called regular user library to get value or the admin one for admin value.

Hi @maroosisSailpoint

I think this approach might be useful for your use case. You could use the workflow to determine which form to use based on the application, operation, and account flavor, and then use Formicator to load and evaluate that form:

Formicator is a SailPoint IIQ class used to process and expand forms by evaluating their dynamic field values, such as scripts and rules.

Form form = context.getObjectByName(Form.class, formName);

Map args = new HashMap();
args.put("identity", identity);
args.put("application", application);
// Add any other objects/values required by the form

Form resolved = new Formicator(context).expand(form, args);

This way, the workflow is really just deciding which form to use. For example:

AD + Create + Admin   -> AD Admin Create Form
AD + Create + Regular -> AD Regular Create Form

Then you can keep the constants, scripts, and rules for each account flavor in its own form instead of adding more and more logic to one large pre-provisioning rule.

This should also work well for the case where you don’t need any user input. If the form can calculate all the required values itself, you may not need to display it to the user just to evaluate those fields.

For getting the resolved values back into provisioning, you could also look into the workflow library methods assimilateProvisioningForm() and assimilatePlanApprovalForm(). The first works with a ProvisioningProject, while the second works with a ProvisioningPlan.

@maroosisSailpoint -
@bohorapujan answer in the last reply is the right approach, and it’s worth spelling out why it also answers your original question about doing this anywhere in code, not just inside a workflow. Formicator only needs a SailPointContext to construct, so the same two lines work identically in a Rule, a custom Task’s execute method, a plugin service, or a workflow step. It isn’t tied to the “Do Provisioning Forms” library step @SanjeevIAM answer goes through.

It also lines up with what you said you actually want in your third post: context.getObjectByName(Form.class, formName) loads by name, so it works cleanly for a form saved as its own object under Global Settings > Forms. A form embedded inline inside a Role, Application, or Workflow definition isn’t addressable that way since it doesn’t exist as a standalone named object, only a top-level Form does. That matches the distinction in SailPoint’s own Form Examples doc between forms embedded in Application/Bundle/Workflow definitions and Report Forms, which are the one type documented as independent, separately-referenced objects.

One thing worth adding since the snippet stops at expand(): that call resolves the form in place. Each field’s script, rule, or literal value gets evaluated against the args map you pass in, and you get back the same Form object with its fields now populated. You read the computed values back off the returned form’s fields rather than expecting expand() to hand you a plain value map.

I am still trying to understand how is it better than mapping it against the application or roles? Using a Formicator complicates a solution which Sailpoint provides OOTB. Attaching a form takes care of provisioning initiates from multiple sources LCM, Refresh, Batch, Rule, etc.. but with Formicator, you need to plug the same code at every possible module to have a consistent behavior. It is definitely an option to be used as last resort, but would not recommend for go-to implementation.

Thank you Very much Pujan Bohora and Amit Gupta. That’s what I was looking for. I suspect I will be exploring this next.

Neelmadvah, I’m trying to understand your concerns but I’m not sure I’m getting the nuances. Would you mind expanding a little more - I’d like to make sure I’m clear before committing.

@maroosisSailpoint When you add ProvisioningPolicy in application, then any process initiating the particular transaction this policy will be triggered.. for example, if you have create provisioningpolicy, then the create request coming via LCM, Batch, Roles, or Rules or any other source, IIQ will make sure to launch the provisioningpolicy and populate the relevants fields on the request.

But in case of Formicator, you need to inject your code at all your sources to figure out the values, means in LCM workflow, batch workflow and rules. For Roles, i don’t think you have any workflow exposed. So, a create request initiated via LCM would have a different form-field values value than create request initiated via Roles.

I think I understand your concern Neelmadvah.

My intent is to have this happen in the workflow - most likely “do provisioning forms” (tbh i noticed that a form can be evaluated as early as “identity request initialize” so i need to do more digging here for “right place”).

I’ve kicked the tires at role forms and their behavior from a create/update/etc. is difficult to sum up other than to say it behaves somewhat differently… I liked that the value from a role form wins out over the value from an app form, but there’s other “behaviors” in the role forms that aren’t ideal imho to be the sole thing to drive account “flavor”.

I like the app forms and that their operation specific but i find that they those work it doesn’t lend itself to having account flavors whose logic varies. If the variances are minor then sure some logic with lookups from one or several custom objects might do it, but when flavors have different - say algorithms to compute the value - then that’s not easily put into a custom object that’s holding the “flavor” stuff together. Like I said, a big glob of code - whatever for it takes - lacks encapsulation.

It feels to me like being able to say to sailpoint: “hey for this account and operation use this form”. SailPoint does this already, it just doesn’t assume you might have “flavors”. The option to define and manage forms as unit and then being able to link up through logic of my that that determines “app/flavor/operation = this form” lets me have a role define the flavor of the account (this is where the role form shines - have it specify the value(s) that drive flavor along with the account selector rule). Now all you need is the config that links the role/flavor to a whole set of operations based forms. Your role can even drive the on role removal behavior of disable or delete.

“Do Provisioning Forms” workflow step does exist for LCM and Batch workflows. However, for role-triggered provisioning, the ProvisioningPolicy is still evaluated by the framework even without a workflow step — it’s just that you can’t inject custom Formicator code there.

@maroosisSailpoint A hybrid approach might work well here:

  1. Use a base ProvisioningPolicy on the application for role-triggered requests (handles the default/fallback behavior)
  2. Use Formicator in the “Do Provisioning Forms” step for LCM/Batch requests where you need flavor-specific form selection

This way you get the best of both worlds — consistency for role-triggered provisioning and flexibility for interactive/batch requests.