Tuesday, September 28, 2021

AD Provisioning Error - ERROR http-nio-8080-exec-1 sailpoint.connector.ADLDAPConnector:3871 - 1158736412 Exception occurred in handling Object Request.

 More often then not, this is because IIQ machine is not able to connect to IQService. 

  • Check the status of IQService
  • Check network
  • Check firewalls

Full Stack Trace:

2021-09-28 15:10:11,539 ERROR http-nio-8080-exec-1 sailpoint.connector.ADLDAPConnector:3871 - 1158736412 Exception occurred in handling Object Request.
sailpoint.tools.GeneralException: Network is unreachable (connect failed)
        at sailpoint.connector.RPCService.execute(RPCService.java:429)
        at sailpoint.connector.ADLDAPConnector.handleObjectRequest(ADLDAPConnector.java:4203)
        at sailpoint.connector.ADLDAPConnector.provision(ADLDAPConnector.java:3862)
        at sailpoint.connector.ConnectorProxy.provision(ConnectorProxy.java:882)
        at sailpoint.integration.ConnectorExecutor.provision(ConnectorExecutor.java:165)
        at sailpoint.provisioning.PlanEvaluator.provision(PlanEvaluator.java:1541)
        at sailpoint.provisioning.PlanEvaluator.execute(PlanEvaluator.java:884)
        at sailpoint.provisioning.PlanEvaluator.execute(PlanEvaluator.java:788)
        at sailpoint.provisioning.PlanEvaluator.execute(PlanEvaluator.java:687)
        at sailpoint.api.Provisioner.execute(Provisioner.java:1685)
        at sailpoint.workflow.IdentityLibrary.provisionProject(IdentityLibrary.java:3058)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at sailpoint.server.ScriptletEvaluator.doCall(ScriptletEvaluator.java:136)
        at sailpoint.server.ScriptletEvaluator.evalSource(ScriptletEvaluator.java:65)
        at sailpoint.api.Workflower.evalSource(Workflower.java:5966)
        at sailpoint.api.Workflower.advanceStep(Workflower.java:5121)
        at sailpoint.api.Workflower.advance(Workflower.java:4510)
        at sailpoint.api.Workflower.startCase(Workflower.java:3091)
        at sailpoint.api.Workflower.launchSubcase(Workflower.java:5424)
        at sailpoint.api.Workflower.launchSubcases(Workflower.java:5317)
        at sailpoint.api.Workflower.advanceStep(Workflower.java:5108)
        at sailpoint.api.Workflower.advance(Workflower.java:4510)
        at sailpoint.api.Workflower.startCase(Workflower.java:3091)
        at sailpoint.api.Workflower.launchSubcase(Workflower.java:5424)
        at sailpoint.api.Workflower.launchSubcases(Workflower.java:5317)
        at sailpoint.api.Workflower.advanceStep(Workflower.java:5108)
        at sailpoint.api.Workflower.advance(Workflower.java:4510)
        at sailpoint.api.Workflower.startCase(Workflower.java:3091)
        at sailpoint.api.Workflower.launchSubcase(Workflower.java:5424)
        at sailpoint.api.Workflower.launchSubcases(Workflower.java:5317)
        at sailpoint.api.Workflower.advanceStep(Workflower.java:5108)
        at sailpoint.api.Workflower.advance(Workflower.java:4510)
        at sailpoint.api.Workflower.assimilate(Workflower.java:4160)
        at sailpoint.api.Workflower.handleWorkItem(Workflower.java:7638)
        at sailpoint.api.Workflower.process(Workflower.java:1824)
        at sailpoint.api.Workflower.process(Workflower.java:1847)
        at sailpoint.api.WorkflowSession.advance(WorkflowSession.java:473)
        at sailpoint.service.WorkflowSessionService.advance(WorkflowSessionService.java:105)
        at sailpoint.service.form.FormService.next(FormService.java:164)
        at sailpoint.service.form.FormService.submit(FormService.java:109)
        at sailpoint.rest.ui.form.BaseFormResource.submit(BaseFormResource.java:130)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
        at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.rest.jaxrs.MethodOverrideFilter.doFilter(MethodOverrideFilter.java:90)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.rest.RestCsrfValidationFilter.doFilter(RestCsrfValidationFilter.java:69)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.rest.AuthenticationFilter.doFilter(AuthenticationFilter.java:100)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.web.SailPointContextRequestFilter.doFilter(SailPointContextRequestFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.web.SailPointPollingRequestFilter.doFilter(SailPointPollingRequestFilter.java:109)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at sailpoint.web.ResponseHeaderFilter.doFilter(ResponseHeaderFilter.java:63)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:201)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:544)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:364)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:616)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1629)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketException: Network is unreachable (connect failed)
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
        at java.net.Socket.connect(Socket.java:606)
        at java.net.Socket.connect(Socket.java:555)
        at java.net.Socket.<init>(Socket.java:451)
        at java.net.Socket.<init>(Socket.java:228)
        at sailpoint.connector.RPCService.execute(RPCService.java:412)
        ... 113 more

Wednesday, September 22, 2021

SailPoint Identity IQ JDBC Aggregation: A common mistake

 A common mistake that I have seen being made is how the aggregation query is written. 

Let's say there are three tables:

  1. User
  2. Groups
  3. Membership
The names are exactly what is contained in the tables, User table contains the user data, Groups table contains the group data, Membership table contains the membership data.

Pay attention to both the queries, both will return the result and mostly pass the unit testing. The issue is that if a user is not part of any groups, they would not appear in the result set of query1

Incorrect Query
SELECT User.*, Membership.groupName 
FROM User, Membership 
WHERE User.Id = Membership.UserId;

Correct Query
SELECT User.*, Membership.groupName
FROM User
LEFT JOIN Membership 
ON User.Id = Membership.UserId;

Hope it helps !!

Monday, September 20, 2021

SailPoint IIQ: Delete WorkItems assigned to a User

  • Query the 'spt_work_item' table. Pay attention to 'id' column(used for deleting the workitem) and 'owner' column (used to identifying the owner
  • Use the console utility to delete the workitem
  • Navigate to <tomcat>/webapps/iiq/WEB-INF/bin/
  • Execute ./iiq console
  • delete workitem ff8080817bffde5f017c029a820700ab (where id is the one you queried from database)
  • If multiple ids have to be deleted, you can create a file with content like:
delete workitem ff8080813eb1de6f013eb3d811f10081
delete workitem ff8080813eb1de6f013eb3d82b6b0095
delete workitem ff8080813eb1de6f013eb3d83b1000a9
delete workitem ff8080813eb1de6f013eb3d846b900bd
delete workitem ff8080813eb1de6f013eb3d855cb00d1

  •  Within IIQ console: source deleWorkItem.txt

          Sunday, September 19, 2021

          Search for text within files in linux

           find ./ -name '*.txt' | xargs grep yourtext


          ./: root path to search

          -name: file name

          SailPoint IdentityIQ : Initialize LCM Module

          > Shutdown tomcat
          > cd apache_home/webapps/iiq/WEB-INF/bin
          > ./iiq console
          > import init-lcm.xml
          > quit console
          > Restart tomcat

          Start mySQL on Linux

           Use one of the following options depending on your environment

          service mysql start
          service mysql stop
          service mysql restart

          service mysqld start 
          service mysqld stop 
          service mysqld restart

          /etc/init.d/mysqld start 
          /etc/init.d/mysqld stop 

          /etc/init.d/mysqld restart 

          Create Database Scheme for Your Custom Application via SQL File

          For many activities like developing a web application, creating data lake or creating trusted/target system for learning IAM, a custom Database schema is required.

          There is always an option to use tools (like SQL developer) or execute one off commands. This works well but the only issue is that we have to set these databases up so frequently that it would be nice to have a template which can be used everytime.

          For this template, we simply need to create a .sql file and store it. Every time a new database has to be created, this can be leveraged. You will still have to update the table names etc.

          This exercise will also help you understand, how to share your database creation details with fellow developers or even how the IAM tools like SailPoint IIQ or Oracle Identity Manager (RCU) shares the same with us.

          I have used a MySQl server but it will work on all RDBMS with minor changes.

          Create a .sql file and use the below structure:

          /*

          SQL file to create a custom database

          -- Date: 2021-19-09 08:15

          */


          CREATE DATABASE customapp;

          SET GLOBAL validate_password_policy=LOW;

          GRANT ALL PRIVILEGES ON customapp.*

              TO 'appUser' IDENTIFIED BY 'admin@12345';

          GRANT ALL PRIVILEGES ON customapp.*

              TO 'appUser'@'%' IDENTIFIED BY 'admin@12345';

          GRANT ALL PRIVILEGES ON customapp.*

              TO 'appUser'@'localhost' IDENTIFIED BY 'admin@12345';


          USE customapp;


          CREATE TABLE `UserTable` (

            `dbID` varchar(45) NOT NULL,

            `empID` varchar(45) DEFAULT NULL,

            `userName` varchar(45) DEFAULT NULL,

            `Inactive` varchar(45) DEFAULT NULL,

            `lastlogin` date DEFAULT NULL,

            PRIMARY KEY (`dbID`)

          );


          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('112','1a2c3a','RichardJackson','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('113','1a2c3b','MariaWhite','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('114','1a2c3c','CharlesHarris','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('115','1a2c3d','SusanMartin','TRUE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('156','1a2c3a4a','LarryMorgan','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('159','1a2c3a4d','MelissaBailey','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('160','1a2c3a4e','FrankRivera','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('161','1a2c3b4a','BrendaCooper','TRUE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('162','1a2c3b4b','ScottRichardson','FALSE','2009-04-04');

          INSERT INTO `financeuser` (`dbID`,`empID`,`userName`,`Inactive`,`lastlogin`) VALUES ('163','1a2c3b4c','AmyCox','FALSE','2009-04-04');


          Now login into database:

          > mysql -u root -p

          > source fileName.sql

          The sql file can be shared and the devs will be able to create the schema in their sandboxes.

          Hope this helps !!!




          Saturday, June 26, 2021

          SQL Developer: MY SQL Connection Error - The server time zone value 'CDT' is unrecognized

          Status : Failure -Test failed: The server time zone value 'CDT' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support 



          Add the following string after the port number

          /?serverTimezone=CDT#


          You can change 'CDT' in the string to the timezone that you recieved in the error.

          Wednesday, June 9, 2021

          SailPoint IIQDA Import Error: org.apache.http.conn.ConnectTimeoutException

           


          This error is due to incorrect URL in XXX.target.properties file.

          The URL should exactly like: %%ECLIPSE_URL%%=http\://192.168.61.102\:8080/identityiq

          Replace with your IP and Host

          Sunday, June 6, 2021

          SailPoint IdentityIQ: Hide 'Add New Entitlement' button from 'Entitlement Catalog'


          •  This post lists the steps to hide the 'Add New Entitlement' button from 'Entitlement Catalog'


          • Navigate to SAILPOINT_HOME/scripts/sailpoint/web/define

          e.g. /u01/sailpoint/tomcat/apache-tomcat-8.5.65/webapps/identityiq/scripts/sailpoint/web/define

          • Open file 'accountGroupGrid.js' and comment the line "toolbar.push(SailPoint.Define.Grid.Group.getNewGroupButton());" 

          • Save file and restart server


          Explore this file and also other js files at this location for similar UI customization.

          Friday, May 7, 2021

          Disable firewall on OEL 7

          The firewall on Oracle Linux 7 system is enabled by default. 

          Fedora 18 introduced firewalld as a replacement for the previous iptables service. Since RHEL7 and Oracle Linux 7 are based on Fedora 19, the switch from iptables service to firewalld is now part of the Enterprise Linux distributions.

          Use the following two commands to check the status and them stop the firewall

          systemctl status firewalld

          service firewalld stop



          Thursday, May 6, 2021

          SailPoint IdentityIQ: Type of Rules

          Creation Rule: 
          Identity creation rules are used to set attributes on new Identity objects when they are created.  New identities may be created during the aggregation of application accounts, or optionally created after pass-through authentication.

          One common operation is to change the name property of the identity when the default application name is complex (such as a directory DN).

          Another common operation is to assign a set of initial capabilities based on the attributes pulled from the application account.

          Use Case: Generate user email, set password

          Customization Rule:

          This rule is configured on the application and is called after the connector has build a ResourceObject from the native application data.

          Initially designed for non-rule based connectors to add SPPrivileged flag to an object, but could be used to do any transformations.

          Use Case: Set IIQDisable flag to set account status


          <WIP>

          Sunday, May 2, 2021

          HOST XXX.XXX.XX.X is not allowed to connect to this MySQL server

          I created an OEL VM and installed a My SQL server. For ease of access, I installed SQL developer on my local windows 10 machine.

          After installing the my sql driver in SQL developer and trying to connect to the DB, I got the following error:


          My SQL Server was not configured to receive any external request


          Granted the permissions


          Problem Resolved




          Mouse Pointer Stuck Inside VM VirtualBox - Change Host Key

          If you using VirtualBox and your mouse pointer is stuck inside the guest's(VM) window. This is by design. When you are using the VM, the keyboard and mouse input go there. If you want to switch this to host, a specific key can be configured, called as "Host Key" (great name)

          Default Host Key

          Windows: right Ctrl - Press right Ctrl on Windows to unstuck your mouse pointer

          macOS: left Cmd

          You can also change this key to any other key in VirtualBox settings:





          Look into Guest Addition to get rid of this dependency




          Tuesday, March 9, 2021

          SailPoint IdentityIQ - Knowledge Assessment & Interview Questions - All Levels

          This post will be a work in progress and plans to be a comprehensive guide for self assessment and interview questions of IIQ  

          Level: Beginner to Advanced

          • What is IGA
          • What is IIQ?
          • What is IIQs latest version?
          • What is an identity?
          • What is an identity cube?
          • What is provisioning?
          • What is aggregation?
          • What does 'Refresh Entitlement Correlation' task do?
          • What does 'Identity Refresh' task do?
          • What is the meaning of option 'Refresh assigned, detected roles and promote additional entitlements' in 'Identity Refresh' Task?
          • What is the meaning of option 'Provision assignments' in 'Identity Refresh' Task?
          • What is the meaning of option 'Disable deprovisioning of deassigned roles' in 'Identity Refresh' Task?
          • What is the meaning of option 'Refresh role metadata for each identity' in 'Identity Refresh' Task?
          • What is the meaning of option 'Process Events' in 'Identity Refresh' Task?
          • How do you rename the attribute 'User Name' to a custom value, say 'Corporate ID'?
          WEB-INF/classes/sailpoint/web/messages/iiqCustom.properties 
          att_user_name=Corporate ID

          • How is attribute 'User Name' populated?
          • How to add a column on 'Identity Warehouse' page?
          • How to extend the identity schema?
          • What are capabilities?
          • What are workgroups?
          • How the change the spadmin's default password?
          • How many types of policies can be created in IIQ?
          • What is a Role SOD Policy?
          • What is an Entitlement SOD Policy?
          • What is an Activity Policy?
          • What is an Account Policy?
          • What is a Risk Policy?
          • What is an Advanced Policy?
          • Describe IIQs risk framework
          • What are extended attributes?
          • What are certifications?
          • How do you schedule a certification?
          • What are certification events?
          • What is a 'Manager' certification?
          • What is a 'Application Owner' certification?
          • What is a 'Entitlement Owner' certification?
          • What is a 'Advanced' certification?
          • What is a 'Role Membership' certification?
          • What is a 'Role Composition' certification?
          • What is a 'Account Group Permission' certification?
          • What is a 'Account Group Membership' certification?
          • Explain IIQ Reporting capabilities.
          • What are tasks?
          Acts on object, scheduled
          • What are business processes?
          Acts on object, event driven
          • What are Rules?
          Beanshell logic, hooks to modify system behavior
          • <Insert>
          • <Insert>


          <work in progress>


          Friday, January 29, 2021

          SailPoint IIQ - URL to download IdentityIQ Deployment Accelerator

          The IdentityIQ Deployment Accelerator is a plug-in for the free and popular Eclipse IDE that provides several features designed to make configuring and managing IdentityIQ easier.

          Download URL -  https://sailpoint.github.io/epiiq/


          Monday, January 25, 2021

          SailPoint IIQ - Script to generate certification from a workflow

          import java.util.List;

          import java.util.ArrayList;

          import sailpoint.object.Identity;

          import sailpoint.api.CertificationScheduler;

          import sailpoint.object.CertificationSchedule;

          import sailpoint.object.CertificationDefinition;

          import sailpoint.object.TaskSchedule;

          import sailpoint.object.Certification;

          import sailpoint.api.Correlator; 

          import sailpoint.task.CertificationExecutor.CertifierSelectionType;


          //

          // requestor = user who made the request

          // identity = user to be certified

          //

            

          Identity requestor = context.getObject(Identity.class, launcher);  

          System.out.println("Change requested by " + requestor.getName()); 

          Identity identity = context.getObject(Identity.class, event.getIdentityName());

          System.out.println("Building certification for " + identity.getName());


          //

          // Identities to certify: 

          //


          List identities = new ArrayList();

          identities.add(identity.getName());


          //

          // Certification Group Owner

          //


          Identity certGroupOwner = context.getObjectByName(Identity.class, "spadmin");


          //

          // Get department user is moving to

          //

          String department = event.getObject().getAttribute("department");


          // 

          // Set sertifier based on department

          //

          Correlator correlator = new Correlator(context); 

          Identity certifier = null;


          if ( department != null && department.equals("IT Management") ) {   

             certifier = correlator.findIdentityByAttribute("name", "Mary.Johnson"); 

          } else {

             certifier = correlator.findIdentityByAttribute("name", "spadmin"); 

          }

          System.out.println("Certification will be done by " + certifier.getName());


          //

          // Schedule Certification

          //

          // Create new Scheduler object

          // 


          CertificationScheduler scheduler = new CertificationScheduler(context);


          //

          // Create schedule and set to run now...

          //

          CertificationSchedule schedule = scheduler.initializeScheduleBean(requestor, Certification.Type.Identity);

          schedule.setRunNow(true);


          //

          // Configure Certification Definition

          //


          CertificationDefinition definition = schedule.getDefinition();

          definition.setCertifierSelectionType(CertificationDefinition.CertifierSelectionType.Manual);

          definition.setProcessRevokesImmediately(true);


          definition.setNameTemplate("Department Transfer for " + identity.getDisplayName() + ": assigned to " + certifier.getDisplayName());

          definition.setShortNameTemplate("Dept xfer for " + identity.getDisplayName());

          definition.setName("Department Transfer : " + identity.getDisplayName() + " [" + new Date().toString() + "]");

          definition.setIdentitiesToCertify(identities);

          definition.setCertifierName(certifier.getName());

          definition.setCertificationOwner(certGroupOwner);

          definition.setCertificationNameTemplate("Department Transfer: " + identity.getDisplayName());


          //

          // Schedule task to run, passing in schedule (which has certficiaton defintion attached)

          //


          TaskSchedule taskSchedule = scheduler.saveSchedule(schedule, false);

          Wednesday, January 20, 2021

          SailPoint IIQ - Role Request Flow - Account v/s No-Account

           

          When a business role is requested:

          • Add the requested business role to the Identity Cube.

          • Determine from the business role being requested what IT roles are required by this role. 

          • From the IT role, determine what entitlements are needed.

          • Does the user have an application account for the application? If yes, provision the entitlement to grant the user the appropriate access that was requested. If no, expand the request to also request an account to be created.

          SailPoint IIQ - Provisioning Rule Example - JDBC Application

          import java.util.Date;

          import java.sql.Connection;

          import java.sql.DriverManager;

          import java.sql.PreparedStatement;

          import java.sql.Statement;

          import java.sql.SQLException;

          import java.sql.ResultSet;

          import java.sql.Types;

          import java.util.List;

          import sailpoint.api.SailPointContext;

          import sailpoint.connector.JDBCConnector;

          import sailpoint.object.Application;

          import sailpoint.object.ProvisioningPlan;

          import sailpoint.object.ProvisioningPlan.AccountRequest;

          import sailpoint.object.ProvisioningPlan.AttributeRequest;

          import sailpoint.object.ProvisioningPlan.PermissionRequest;

          import sailpoint.object.ProvisioningResult;

          import sailpoint.object.Schema;

          import sailpoint.tools.xml.XMLObjectFactory;

          import org.apache.commons.logging.LogFactory;

          import org.apache.commons.logging.Log;

          import sailpoint.tools.Util;


          //

          // Internal method for grabbing an Attribute Request Value.

          //

          public Object getAttributeRequestValue(AccountRequest acctReq, String attribute) {

              if ( acctReq != null ) {

             AttributeRequest attrReq = acctReq.getAttributeRequest(attribute);

                if ( attrReq != null ) {

                  return attrReq.getValue();

                }

              }

              return null;

              }


          //

          // JDBC Provisioning Rule Body

          //

          // We will handle these cases right now: 

          // 

          // Account Request Create

          // Account Request Modify

          // Account Request Delete

          // Account Lock/Unlock

          // Account Enable/Disable

          //

          Date now = new Date();


          System.out.println("\n\n\n\n\n");

          System.out.println("****************************************");

          System.out.println("Entering Provisioning Rule for PRISM");

          System.out.println(" Current Time =  " + now.toString());

          System.out.println("****************************************");



          //

          // The ProvisioningResult is the return object for this type of rule. We'll create it here and then populate it later

          //


          ProvisioningResult result = new ProvisioningResult();



          //

          // Check if the plan is null or not, if not null, process it... 

          //


          if ( plan != null ) {


          System.out.println("*** \n The Provisioning Plan being passed in = \n***\n" + plan.toXml() + "\n****************************************");


          List accounts = plan.getAccountRequests();

          // 

          //  Get all Account Requests out of the plan

          // 


          if ( ( accounts != null ) && ( accounts.size() > 0 ) ) {

          //

          // If the plan contains one or more account requests, we'll iterate through them

          //

          for ( AccountRequest account : accounts ) {

          try {

          // 

          // All of the account operations will reside in a try block in case we have any errors, we can mark the provisioningresult as "Failed" if we have an issue.

          //


          if (AccountRequest.Operation.Create.equals(account.getOperation())) {


          //

          // CREATE Operation

          //

          System.out.println("Account Request Operation = Create");


          PreparedStatement statement = connection.prepareStatement("insert into users (login,first,last,groups,status,locked) values (?,?,?,?,?,?)");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.setString(2, getAttributeRequestValue(account, "first"));

          statement.setString(3, getAttributeRequestValue(account, "last"));

          statement.setString(5, getAttributeRequestValue(account, "status"));

          statement.setString(6, getAttributeRequestValue(account, "locked"));

          //

          // Grab the role from the request. If it's a single role, it'll be a string, add it to 

          // the statement, other wise if it's a List, convert to CSV and add it to the statement

          //

          AttributeRequest attrReq = account.getAttributeRequest("groups");

          if (attrReq != null) {

          if (attrReq.getValue() instanceof String) {

          statement.setString(4, (String) attrReq.getValue());

          } else if (attrReq.getValue() instanceof List) {

          String listOfRoles = Util.listToCsv((List) attrReq.getValue());

          statement.setString(4, listOfRoles);

          }

          } else {

                                                                         statement.setString(4,"");

                                                   }


          System.out.println("Preparing to execute: " + statement);

          statement.executeUpdate();

          //

          // Sucessful Create, so mark result as COMMITTED

          //

          result.setStatus(ProvisioningResult.STATUS_COMMITTED);


          } else if (AccountRequest.Operation.Modify.equals(account.getOperation())) {

          //

          // MODIFY Operation

          // 

          //

          // We have a modify, this one is trickier, as we can have "Add" and "Remove" 

          // operations and each can be a single string value or a list

          //


          System.out.println("Account Request Operation = Modify");


          //

          // Determine what the current roles are first... 

          //


          Statement curr_stmt = connection.createStatement();

          ResultSet rs = curr_stmt .executeQuery("select * from users where login = '" + account.getNativeIdentity() + "'");


          //

          //  Check result set. Should only be one row since login is a unique key for the table

          //

          List current_roles = null;

          String roles = "";


          while (rs.next()) {

             roles = roles + "," + rs.getString("groups");

          current_roles = Util.csvToList(roles,true);

          if (current_roles == null) {

          System.out.println("We have a null current_roles list... change it to an empty list for subsequent processing.");

          current_roles = new ArrayList();

          }


          System.out.println("Current Roles for User = " + Util.listToCsv(current_roles));


          //

          // Get all Attribute Requests and pull out just the role ones. 

          //

          List remove_roles = new ArrayList();

          List add_roles = new ArrayList(); 

          //

          // Get all attribute requests and then we will filter for those related to the roles column

          //

          List mod_attr_requests = account.getAttributeRequests();

          if (mod_attr_requests != null) {

          for (AttributeRequest req : mod_attr_requests ) {

          if (req.getName().equals("groups")) {

             if (ProvisioningPlan.Operation.Remove.equals(req.getOperation())) {

          // Process Removes First

          if (req.getValue() instanceof String) {

            remove_roles = Util.csvToList(req.getValue());

          } else if (req.getValue() instanceof List) {

            remove_roles = req.getValue();                

          }

          } else if (ProvisioningPlan.Operation.Add.equals(req.getOperation())) {

          // Process Adds Second

          if (req.getValue() instanceof String) {

             add_roles = Util.csvToList(req.getValue());

          } else if (req.getValue() instanceof List) {

            add_roles = req.getValue();                     

          }


             } 

          }

          }

          //

          //  We now have a calculated list of the roles we are adding, the roles we are removing, and the current roles for the user.

          //

          System.out.println("Add Roles = " + Util.listToCsv(add_roles));

          System.out.println("Remove Roles = " + Util.listToCsv(remove_roles));



          //

          // If we have roles to remove, remove them

          //

          if (!remove_roles.isEmpty()) {

          System.out.println("About to remove roles: " + remove_roles.toString() + "from the current_roles = " + current_roles.toString());

          current_roles.removeAll(remove_roles);

          }

          //

          // If we have roles to add, check if they are there and add them as we iterate through

          //

          if (!add_roles.isEmpty()) {

          System.out.println("About to add roles: " + add_roles.toString() + " to the current_roles = " + current_roles.toString());

          for (Object item: add_roles) {

          if (!current_roles.contains(item)) {

             current_roles.add(item);

          }

          }

          }

          //

          //  Print out the list of roles being provisioned after processing "add" and "remove" operations

          //

          System.out.println("Updating the roles for:" + (String) account.getNativeIdentity() + " Current Roles after adding/removing = " + Util.listToCsv(current_roles)); 


          //

          // Process update SQL operation

          //


          PreparedStatement statement = connection.prepareStatement("update users set groups = ? where login = ?");

          statement.setString(2, (String) account.getNativeIdentity());

          statement.setString(1,Util.listToCsv(current_roles)); 

          statement.executeUpdate();


          // Add these in the future.

          // statement.setString ( 2,

          // getAttributeRequestValue(account,"first") );

          // statement.setString ( 3,

          // getAttributeRequestValue(account,"last") );

          // statement.setString ( 4,

          // getAttributeRequestValue(account,"groups") );

          // statement.setString ( 5,

          // getAttributeRequestValue(account,"status") );


          result.setStatus(ProvisioningResult.STATUS_COMMITTED);


          } else if (AccountRequest.Operation.Delete.equals(account.getOperation())) {

          //

          // DELETE Operation

          // 



          System.out.println("Account Request Operation = Delete");

          PreparedStatement statement = connection.prepareStatement("delete from users where login = ?");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.executeUpdate();


          result.setStatus(ProvisioningResult.STATUS_COMMITTED);


          } else if (AccountRequest.Operation.Disable.equals(account.getOperation())) {


          System.out.println("Account Request Operation = Disable");

          PreparedStatement statement = connection.prepareStatement("update users set status = 'I' where login = ?");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.executeUpdate();

          result.setStatus(ProvisioningResult.STATUS_COMMITTED);


          } else if (AccountRequest.Operation.Enable.equals(account.getOperation())) {


          System.out.println("Account Request Operation = Enable");

          PreparedStatement statement = connection.prepareStatement("update users set status = 'A' where login = ?");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.executeUpdate();

          result.setStatus(ProvisioningResult.STATUS_COMMITTED);



          } else if (AccountRequest.Operation.Lock.equals(account.getOperation())) {


          System.out.println("Account Request Operation = Lock");

          PreparedStatement statement = connection.prepareStatement("update users set locked = 'Y' where login = ?");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.executeUpdate();

          result.setStatus(ProvisioningResult.STATUS_COMMITTED);



          } else if (AccountRequest.Operation.Unlock.equals(account.getOperation())) {


          System.out.println("Account Request Operation = Unlock");

          PreparedStatement statement = connection.prepareStatement("update users set locked = 'N' where login = ?");

          statement.setString(1, (String) account.getNativeIdentity());

          statement.executeUpdate();

          result.setStatus(ProvisioningResult.STATUS_COMMITTED);


          } else {


          // Unknown operation!

          System.out.println("Unknown operation ["

          + account.getOperation() + "]!");

          }


          } catch (SQLException e) {

                                  System.out.println("Error: " + e);

                                  result.setStatus(ProvisioningResult.STATUS_FAILED);

                                  result.addError(e);

          }    // account request loop

          }     // if account requests exist

          }   // if plan not null



          System.out.println("****************************************");

          System.out.println("****************************************");

          System.out.println("Exiting Provisioning Rule for PRISM. \n  Result=  \n" + result.toXml(false));

          System.out.println("****************************************");

          System.out.println("****************************************");

          System.out.println("\n\n\n\n\n");

          return result;