Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

SailPoint user certification integration for AEM

Avatar

Level 3

Is there any integration/steps documentation available for AEM integration with SailPoint user certification?

1 Accepted Solution

Avatar

Correct answer by
Former Community Member

hello Mahmood ,

The integration itself is relatively simple: the integration consists of an IntegrationConfig object as well as a plan initializer rule. Tickets can be initiated through any SailPoint provisioning action such as an access review revocation, access request, or role assignment. The integration converts a standard SailPoint provisioning plan into a SOAP message that is sent over to an endpoint within ServiceNow, which generates a ticket. When the ticket is generated, ServiceNow returns the ticket number to SailPoint, which stores the ticket number. SailPoint then periodically polls ServiceNow requesting the status of the open ticket and returning the ticket status to SailPoint.

Configuring the integration between ServiceNow and SailPoint consisted of the following steps:

1. Add the following JAVA options to the application server hosting SailPoint IdentityIQ:

1

<span style="line-height: 1.3em;">--Djavax.xml.soap.SOAPConnectionFactory=org.apache.axis2.saaj.SOAPConnectionFactoryImpl</span>

1

--Djavax.xml.soap.MessageFactory=org.apache.axis2.saaj.MessageFactoryImpl

1

2

3

<span style="line-height: 1.3em;">--Djavax.xml.soap.SOAPFactory=org.apache.axis2.saaj.SOAPFactoryImpl

</span>

2. Verify the ServiceNow instance is operating and available to the SailPoint server. From the SailPoint server, navigate to the address below. The WSDL of the ServiceNow endpoint should be returned.

1

2

3

<span style="line-height: 1.3em;">https://&lt;ServiceNowHost&gt;/incident.do?WSDL

</span>

3. Create the IntegrationConfig object within SailPoint. The default configuration for the Integration config object can be found in %IIQ_HOME%/WEB-INF/config/sampleServiceNowIntegration.xml. This file must be customized to work for the specific ServiceNow environment. Some of the fields that must be modified are below. This specifies how SailPoint is to communicate with ServiceNow.

1

&lt;entry key="endpoint" value="https://<ServiceNowHost/incident.do?SOAP"/&gt;

1

&lt;entry key="username value=admin/&gt;

1

&lt;entry key="password value=admin/&gt;

4. For any SailPoint applications that should be provisioned using the ServiceNow integration, create a ManagedResource reference in the ServiceNowIntegrationConfig.

1

<span style="line-height: 1.3em;">&lt;ManagedResources&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Application" id="" name="Application 1"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Application" id="" name="Application 2"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResources&gt;</span>

1

2

3

<span style="line-height: 1.3em;">&lt;/IntegrationConfig&gt;

</span>

5. Create a plan initializer rule. The OOB integration does not deal with XML reserved characters in application or entitlement names and will throw errors if not accounted for. We included the plan initializer rule to convert these characters into a character string that would be acceptable to SailPoint. For instance, an application name that was “Payroll & Accounting” would throw errors because of an ampersand (&). The plan initializer rule changed the application name to “Payroll &amp; Accounting”. The rule is referenced in the ServiceNowIntegrationConfig with the following tag:

1

<span style="line-height: 1.3em;">&lt;PlanInitializer&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Rule" id="" name="ServiceNowIntegrationRule"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/PlanInitializer&gt;</span>

1

<span style="line-height: 1.3em;">The rule that was used is as follows:</span>

1

<span style="line-height: 1.3em;"> import java.util.ArrayList;</span>

1

<span style="line-height: 1.3em;"> import java.util.List;</span>

1

<span style="line-height: 1.3em;"> import sailpoint.object.Identity;</span>

1

1

<span style="line-height: 1.3em;"> private String escapeXml(s){</span>

1

<span style="line-height: 1.3em;"> String str = s;</span>

1

<span style="line-height: 1.3em;"> if (str!=null)</span>

1

<span style="line-height: 1.3em;"> {</span>

1

<span style="line-height: 1.3em;"> System.out.println("escapeXML start: "+str);</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&amp;","&amp;amp;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&gt;","&amp;gt;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&lt;","&amp;lt;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("\"","&amp;quot;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("'","&amp;apos;");</span>

1

<span style="line-height: 1.3em;"> System.out.println("escapeXML end: "+str);</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> return str;</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> </span><span style="line-height: 1.3em;"> Map map = (Map)plan.getIntegrationData();</span>

1

<span style="line-height: 1.3em;"> map.put("identityName", escapeXml(identity.getName()));</span>

1

<span style="line-height: 1.3em;"> if (identity.getFirstname() != null) {</span>

1

<span style="line-height: 1.3em;"> map.put("identityFirstname", escapeXml(identity.getFirstname()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> if (identity.getLastname() != null) {</span>

1

<span style="line-height: 1.3em;"> map.put("identityLastname", escapeXml(identity.getLastname()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> List requesters = new ArrayList();</span>

1

<span style="line-height: 1.3em;"> List planRequesters = plan.getRequesters();</span>

1

<span style="line-height: 1.3em;"> if (planRequesters != null) {</span>

1

<span style="line-height: 1.3em;"> for (int i = 0 ; i &lt; planRequesters.size() ; i++) {</span>

1

<span style="line-height: 1.3em;"> Identity req = (Identity)planRequesters.get(i);</span>

1

<span style="line-height: 1.3em;"> requesters.add(escapeXml(req.getDisplayableName()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> } else</span>

1

<span style="line-height: 1.3em;"> requesters.add("IIQRequestor");</span>

1

<span style="line-height: 1.3em;"> map.put("requesters", requesters);</span>

1

<span style="line-height: 1.3em;"> map.put("sourceId", escapeXml(plan.getSourceId()));</span>

1

<span style="line-height: 1.3em;"> map.put("sourceName", escapeXml(plan.getSourceName()));</span>

1

2

3

<span style="line-height: 1.3em;"> map.put("sourceType", escapeXml(plan.getSourceType()));

</span>

6. Test the integration with either an access request, role assignment, or access review revocation.

Once the integration is working and creating tickets in ServiceNow, the SOAP message for provisioning can be modified. The out-of-the-box integration relies mostly on static values for assignment group, and priority levels. These can be customized as needed within the IntegrationConfig.

1

<span style="line-height: 1.3em;">&lt;assignment_group&gt;Service Desk&lt;/assignment_group&gt;</span>

1

<span style="line-height: 1.3em;">&lt;category&gt;request&lt;/category&gt; </span>

1

<span style="line-height: 1.3em;">&lt;contact_type&gt;email&lt;/contact_type&gt;</span>

1

<span style="line-height: 1.3em;">&lt;impact&gt;3&lt;/impact&gt;</span>

1

<span style="line-height: 1.3em;">&lt;incident_state&gt;1&lt;/incident_state&gt;</span>

1

<span style="line-height: 1.3em;">&lt;caller_id&gt;$provisioningPlan.integrationData.requester&lt;/caller_id&gt;</span>

1

<span style="line-height: 1.3em;">&lt;opened_by&gt;$config.username&lt;/opened_by&gt;</span>

1

<span style="line-height: 1.3em;">&lt;urgency&gt;3&lt;/urgency&gt;</span>

1

<span style="line-height: 1.3em;">&lt;short_description&gt;IdentityIQ provisioning request for: $provisioningPlan.integrationData.identityName $!</span>

1

2

3

<span style="line-height: 1.3em;">provisioningPlan.integrationData.identityRequestId&lt;/short_description&gt;

</span><span style="line-height: 1.3em; color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12px;"> </span>

Overall, the integration was relatively easy to setup, though it required a little customization to get it to function the way the customer wanted. The integration is not without its faults. While it returns back a ticket number, it lacks the true bidirectional communication the SailPoint direct connectors support. Also, comments and notes added to the ServiceNow ticket that is created do not flow back into SailPoint.  SailPoint only tracks the status of the ticket.

View solution in original post

5 Replies

Avatar

Administrator

What exactly do you like to achieve?

You can achieve the workflow related tasks in AEM by using OOTB workflows or create a custom workflow:- Adobe Experience Manager Help | Creating custom AEM workflow steps that send email messages



Kautuk Sahni

Avatar

Level 1

hai mahamood.

yes there is there documentation available for AEM integration with SailPoint user certification. you learn sailpoint here

Avatar

Correct answer by
Former Community Member

hello Mahmood ,

The integration itself is relatively simple: the integration consists of an IntegrationConfig object as well as a plan initializer rule. Tickets can be initiated through any SailPoint provisioning action such as an access review revocation, access request, or role assignment. The integration converts a standard SailPoint provisioning plan into a SOAP message that is sent over to an endpoint within ServiceNow, which generates a ticket. When the ticket is generated, ServiceNow returns the ticket number to SailPoint, which stores the ticket number. SailPoint then periodically polls ServiceNow requesting the status of the open ticket and returning the ticket status to SailPoint.

Configuring the integration between ServiceNow and SailPoint consisted of the following steps:

1. Add the following JAVA options to the application server hosting SailPoint IdentityIQ:

1

<span style="line-height: 1.3em;">--Djavax.xml.soap.SOAPConnectionFactory=org.apache.axis2.saaj.SOAPConnectionFactoryImpl</span>

1

--Djavax.xml.soap.MessageFactory=org.apache.axis2.saaj.MessageFactoryImpl

1

2

3

<span style="line-height: 1.3em;">--Djavax.xml.soap.SOAPFactory=org.apache.axis2.saaj.SOAPFactoryImpl

</span>

2. Verify the ServiceNow instance is operating and available to the SailPoint server. From the SailPoint server, navigate to the address below. The WSDL of the ServiceNow endpoint should be returned.

1

2

3

<span style="line-height: 1.3em;">https://&lt;ServiceNowHost&gt;/incident.do?WSDL

</span>

3. Create the IntegrationConfig object within SailPoint. The default configuration for the Integration config object can be found in %IIQ_HOME%/WEB-INF/config/sampleServiceNowIntegration.xml. This file must be customized to work for the specific ServiceNow environment. Some of the fields that must be modified are below. This specifies how SailPoint is to communicate with ServiceNow.

1

&lt;entry key="endpoint" value="https://<ServiceNowHost/incident.do?SOAP"/&gt;

1

&lt;entry key="username value=admin/&gt;

1

&lt;entry key="password value=admin/&gt;

4. For any SailPoint applications that should be provisioned using the ServiceNow integration, create a ManagedResource reference in the ServiceNowIntegrationConfig.

1

<span style="line-height: 1.3em;">&lt;ManagedResources&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Application" id="" name="Application 1"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Application" id="" name="Application 2"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ApplicationRef&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResource&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/ManagedResources&gt;</span>

1

2

3

<span style="line-height: 1.3em;">&lt;/IntegrationConfig&gt;

</span>

5. Create a plan initializer rule. The OOB integration does not deal with XML reserved characters in application or entitlement names and will throw errors if not accounted for. We included the plan initializer rule to convert these characters into a character string that would be acceptable to SailPoint. For instance, an application name that was “Payroll & Accounting” would throw errors because of an ampersand (&). The plan initializer rule changed the application name to “Payroll &amp; Accounting”. The rule is referenced in the ServiceNowIntegrationConfig with the following tag:

1

<span style="line-height: 1.3em;">&lt;PlanInitializer&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;Reference class="sailpoint.object.Rule" id="" name="ServiceNowIntegrationRule"/&gt;</span>

1

<span style="line-height: 1.3em;"> &lt;/PlanInitializer&gt;</span>

1

<span style="line-height: 1.3em;">The rule that was used is as follows:</span>

1

<span style="line-height: 1.3em;"> import java.util.ArrayList;</span>

1

<span style="line-height: 1.3em;"> import java.util.List;</span>

1

<span style="line-height: 1.3em;"> import sailpoint.object.Identity;</span>

1

1

<span style="line-height: 1.3em;"> private String escapeXml(s){</span>

1

<span style="line-height: 1.3em;"> String str = s;</span>

1

<span style="line-height: 1.3em;"> if (str!=null)</span>

1

<span style="line-height: 1.3em;"> {</span>

1

<span style="line-height: 1.3em;"> System.out.println("escapeXML start: "+str);</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&amp;","&amp;amp;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&gt;","&amp;gt;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("&lt;","&amp;lt;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("\"","&amp;quot;");</span>

1

<span style="line-height: 1.3em;"> str = str.replace("'","&amp;apos;");</span>

1

<span style="line-height: 1.3em;"> System.out.println("escapeXML end: "+str);</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> return str;</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> </span><span style="line-height: 1.3em;"> Map map = (Map)plan.getIntegrationData();</span>

1

<span style="line-height: 1.3em;"> map.put("identityName", escapeXml(identity.getName()));</span>

1

<span style="line-height: 1.3em;"> if (identity.getFirstname() != null) {</span>

1

<span style="line-height: 1.3em;"> map.put("identityFirstname", escapeXml(identity.getFirstname()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> if (identity.getLastname() != null) {</span>

1

<span style="line-height: 1.3em;"> map.put("identityLastname", escapeXml(identity.getLastname()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> List requesters = new ArrayList();</span>

1

<span style="line-height: 1.3em;"> List planRequesters = plan.getRequesters();</span>

1

<span style="line-height: 1.3em;"> if (planRequesters != null) {</span>

1

<span style="line-height: 1.3em;"> for (int i = 0 ; i &lt; planRequesters.size() ; i++) {</span>

1

<span style="line-height: 1.3em;"> Identity req = (Identity)planRequesters.get(i);</span>

1

<span style="line-height: 1.3em;"> requesters.add(escapeXml(req.getDisplayableName()));</span>

1

<span style="line-height: 1.3em;"> }</span>

1

<span style="line-height: 1.3em;"> } else</span>

1

<span style="line-height: 1.3em;"> requesters.add("IIQRequestor");</span>

1

<span style="line-height: 1.3em;"> map.put("requesters", requesters);</span>

1

<span style="line-height: 1.3em;"> map.put("sourceId", escapeXml(plan.getSourceId()));</span>

1

<span style="line-height: 1.3em;"> map.put("sourceName", escapeXml(plan.getSourceName()));</span>

1

2

3

<span style="line-height: 1.3em;"> map.put("sourceType", escapeXml(plan.getSourceType()));

</span>

6. Test the integration with either an access request, role assignment, or access review revocation.

Once the integration is working and creating tickets in ServiceNow, the SOAP message for provisioning can be modified. The out-of-the-box integration relies mostly on static values for assignment group, and priority levels. These can be customized as needed within the IntegrationConfig.

1

<span style="line-height: 1.3em;">&lt;assignment_group&gt;Service Desk&lt;/assignment_group&gt;</span>

1

<span style="line-height: 1.3em;">&lt;category&gt;request&lt;/category&gt; </span>

1

<span style="line-height: 1.3em;">&lt;contact_type&gt;email&lt;/contact_type&gt;</span>

1

<span style="line-height: 1.3em;">&lt;impact&gt;3&lt;/impact&gt;</span>

1

<span style="line-height: 1.3em;">&lt;incident_state&gt;1&lt;/incident_state&gt;</span>

1

<span style="line-height: 1.3em;">&lt;caller_id&gt;$provisioningPlan.integrationData.requester&lt;/caller_id&gt;</span>

1

<span style="line-height: 1.3em;">&lt;opened_by&gt;$config.username&lt;/opened_by&gt;</span>

1

<span style="line-height: 1.3em;">&lt;urgency&gt;3&lt;/urgency&gt;</span>

1

<span style="line-height: 1.3em;">&lt;short_description&gt;IdentityIQ provisioning request for: $provisioningPlan.integrationData.identityName $!</span>

1

2

3

<span style="line-height: 1.3em;">provisioningPlan.integrationData.identityRequestId&lt;/short_description&gt;

</span><span style="line-height: 1.3em; color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12px;"> </span>

Overall, the integration was relatively easy to setup, though it required a little customization to get it to function the way the customer wanted. The integration is not without its faults. While it returns back a ticket number, it lacks the true bidirectional communication the SailPoint direct connectors support. Also, comments and notes added to the ServiceNow ticket that is created do not flow back into SailPoint.  SailPoint only tracks the status of the ticket.

Avatar

Level 3

Thanks for the details steps. It helps. I will post more details as we go for actual implementation.

Avatar

Level 1

Certifications in Sailpoint: Access Certification: It means acknowledgment of current users' access. It presents the data in a business-friendly language. It archives the certification history. It has a capability to track reviewer progress & actions.

The following has evaluated to null or missing: ==> liqladmin("SELECT id, value FROM metrics WHERE id = 'net_accepted_solutions' and user.id = '${acceptedAnswer.author.id}'").data.items [in template "analytics-container" at line 83, column 41] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign answerAuthorNetSolutions = li... [in template "analytics-container" at line 83, column 5] ----