Modern IdentityIQ (IIQ) environments often need to talk to other systems. REST APIs make that possible. Since version 6.2, SailPoint lets you create REST services without messing with Java classes or restarting servers. You can now build them entirely with workflows and BeanShell. Here’s how.
Why Use Workflows Instead of Java REST Classes?
- No need to touch
web.xml - Changes don’t require recompiling or restarting
- Debugging is easier
- You can version and reuse workflows easily
Workflows are ideal for exposing small services like identity lookups, status queries, or even onboarding events. And you can do it without touching IdentityIQ’s core code.
Example Use Case: Identity or Account Lookup
Let’s say an external system wants to get info on a user or their account (a.k.a. a “Link” in IIQ). You want to return a JSON object based on:
retrieveObjectType: either Identity or LinkretrieveObjectName: the identity name or account nameretrieveObjAppName: (for Link only) the application name
Workflow Logic (REST-Identity-Lookup)
The workflow will return a simple map with key details like email, username, and timestamps.
<Workflow name="REST-Identity-Lookup" type="LCM" explicitTransitions="true">
<Variable name="transient" initializer="true" />
<Variable name="trace" initializer="true" />
<Variable name="retrieveObjectType" input="true" initializer="" />
<Variable name="retrieveObjectName" input="true" initializer="" />
<Variable name="retrieveObjAppName" input="true" initializer="" />
<Variable name="objectDetails" output="true" />
<Step name="Start" icon="Start">
<Script>
<Source><![CDATA[
log.info("Workflow started: " + retrieveObjectType);
return;
]]></Source>
</Script>
<Transition to="FetchObjectDetails" />
</Step>
<Step name="FetchObjectDetails" resultVariable="objectDetails" icon="Default">
<Script>
<Source><![CDATA[
import sailpoint.object.*;
import sailpoint.api.SailPointContext;
import sailpoint.object.Filter;
import sailpoint.object.QueryOptions;
Map result = new HashMap();
if ("Identity".equals(retrieveObjectType)) {
Identity id = context.getObjectByName(Identity.class, retrieveObjectName);
if (id != null) {
result.put("username", id.getName());
result.put("email", id.getEmail());
result.put("firstName", id.getFirstname());
result.put("lastName", id.getLastname());
}
} else if ("Link".equals(retrieveObjectType)) {
QueryOptions qo = new QueryOptions();
qo.addFilter(Filter.eq("application.name", retrieveObjAppName));
qo.addFilter(Filter.eq("nativeIdentity", retrieveObjectName));
Iterator links = context.search(Link.class, qo);
if (links.hasNext()) {
Link link = (Link) links.next();
result.put("app", link.getApplicationName());
result.put("identity", link.getNativeIdentity());
result.put("created", link.getCreated());
result.put("modified", link.getModified());
}
}
return result;
]]></Source>
</Script>
<Transition to="Stop" />
</Step>
<Step name="Stop" icon="Stop" />
</Workflow>
Call It Using CURL
Here’s how to hit the workflow with a curl POST request. First, for Identity:
curl -u spadmin:admin -H "Content-Type: application/json" -X POST \
-d '{
"workflowArgs": {
"retrieveObjectType": "Identity",
"retrieveObjectName": "john.doe"
}
}' \
http://localhost:8080/identityiq/rest/workflows/REST-Identity-Lookup/launch
Now, querying a Link (application account):
curl -u spadmin:admin -H "Content-Type: application/json" -X POST \
-d '{
"workflowArgs": {
"retrieveObjectType": "Link",
"retrieveObjectName": "john.doe",
"retrieveObjAppName": "Active Directory"
}
}' \
http://localhost:8080/identityiq/rest/workflows/REST-Identity-Lookup/launch
Final Thoughts
With just one workflow, you’ve created a simple, callable REST service in IdentityIQ. No Java classes, no war file updates. This is the easiest way to expose user or account info to other systems securely and efficiently.
Seen a better way to do this? Got a clever use case? Drop your thoughts below. 🧠