You are on page 1of 11

   

SailPoint  Best  Practices  –  Certification   Generation  on  large  deployments  
Nick  Wellinghoff    

Purpose  
The  certification  generation  phase  of  a  project  is  often  the  first  time  the  business  will  see  the  results  of   months  of  effort.    It  is  important  this  process  operates  smoothly  and  can  recover  from  errors.    During   small  deployments  this  is  less  of  a  concern  as  the  certification  generation  can  simply  be  deleted  and   started  again.  However,  on  large  deployments  where  just  the  generation  of  the  certifications  may  take   multiple  days  given  certain  data  conditions,  it  is  important  to  have  more  control  over  the  process.  This   document  will  outline  an  approach  that  will  give  the  user  the  ability  to  optimize  generation   performance,  distribute  system  load  and  recover  gracefully  from  errors.      

..........................................................................................................................................  4   Define  the  GenerateCerts  Task  Executor  .......  9   Example  implementation  of  GenerateCerts  TaskExecutor  ......................................  7   Appendix  ........................................................................................................................  6   Scenario  One:  Generate  manager  certifications  while  controlling  user  load  on  the  web  server  cluster...  6   Scenario  Two:  Customer  desires  faster  certification  generation  performance..................  3   Scripting  the  certification  generation  process  .............................................................................................................................................................................................................................  9           Page 2 of 11   .............................   ....................................................  5   Leveraging  the  GenerateCerts  TaskExecutor  ...........................................  6   Scenario  Three:  The  certification  generation  task  fails  in  production  ......................................................................................................................................................  3   Define  a  certification  manager  task  .....  1   Target  audience  .............................  3   Create  CertificationDefinition  templates...............................................................................................................  ......................................     Best  Practices   Table  of  Contents   Purpose  ......................  4   Custom  Task  Definition  ........................................................................................................................................................................................

 This  will  prevent  the  software  from   traversing  the  management  chain  and  generating  child  certifications.   • • • • • •   Clients  that  have  a  management  hierarchy  that  includes  1.    Also.  include  a  rule  or  select  the   proper  applications.     A  template  CertificationDefinition  will  be  created  which  will  serve  as  a  base  for  all  certifications  of  the   same  type.000  +  members.  This  section  will  cover  how  to  do  this  for  a   theoretical  worldwide  manager  certification  run.     Best  Practices   Target  audience     Deployments  that  have  the  following  characteristics  are  the  target  for  this  document.   Scripting  the  certification  generation  process   To  achieve  the  stated  goals  the  certification  configuration  and  execution  will  be  changed  from  a  UI  and   user  driven  process  to  a  programmatically  driven  process.   Projects  that  have  tight  timelines  and  certification  generation  needs  to  be  accelerated  or  errors   need  to  be  resolved  with  a  higher  degree  of  granularity  than  normal.   Clients  that  have  complex  certification  parameters  where  the  possibility  of  human  error  is  high.  users  usually  select  a  manager  high  in  the  hierarchy  and  allow  the  software  to   traverse  the  management  chain  and  generate  child  certifications.   Clients  that  desire  a  finer  level  of  granularity  for  error  reporting.   The  hardware  architecture  is  not  capable  of  handling  the  use  case  of  all  users  who  have  open   certifications  logging  on  and  using  the  system  at  the  same  time.  simply  create  a  manager  certification  in  the  UI  but  in  the  advanced   screen  check  the  “For  the  specified  managers  only”  radio  button.  This  will  provide  the  flexibility  to  break  up  the  certification  generation  process  into  many   atomic  subtasks  allowing  for  parallel  execution  and  fine  grain  error  recovery.000.      To  create  the  template.       Page 3 of 11     .       Create  CertificationDefinition  Templates   Normally  when  the  UI  is  used  to  create  a  certification  the  end  result  is  a  CertificationDefinition  which  is   saved  and  associated  with  a  TaskSchedule.    The  suggested  scripting  process  is   going  to  disable  this  functionality  and  define  unique  CertificationDefinition  and  TaskSchedule  objects  for   every  certifier.   Clients  generating  any  certification  type  where  the  number  of  instances  exceeds  1.    But  the  same  principles  may  be  applied  to  any   certification  type.    If  a  person  is  relied  on  to  perform  this  task  in  production.  the   process  can  be  prone  to  errors  as  users  often  forget  to  check  an  option.

 but  common  groupings  are  covered  in  a  later  section.       Define  a  Certification  Manager  Task   Custom  Task  Definition   There  are  a  number  of  ways  to  input  which  managers    are  going  to  certify  but  for  this  example  a   TaskDefintion  will  be  defined  that  will  take  a  population  as  a  parameter.  If  the  customer  has  a  small  infrastructure  it  might  be  wise   to  make  the  population  a  list  of  managers  interleaved  by  geographical  location.</Prompt> </Argument> </Inputs> <Returns> <Argument name="result" type="string"> <Prompt>Result</Prompt> </Argument> </Returns> </Signature> </TaskDefinition>   Page 4 of 11     .   Schedule  it  so  it  will  never  execute  by  setting  the  schedule  to  a  time  far  into  the  future.  It  is  probable.  This  is  a  simple  approach  that   serves  as  an  example.  save  the  configuration  with  a  name  that  indicates  it’s  a  template.dtd" "sailpoint.  Go  to  the  debug  page  (http://hostname:port/iiq/debug)  and  locate  the  CertificationDefinition   just  created.  The   population  should  be  a  set  of  managers  that  have  been  divided  by  criteria  that  fulfills  the  desired   behavior  of  the  certification  generation  task.0' encoding='UTF-8'?> <!DOCTYPE TaskDefinition PUBLIC "sailpoint.  This  will  be  the   template.  Inspect  the  options  in  the  XML  and  confirm  that  the  settings  are  correct.  more  sophisticated  input  mechanisms  will  be  needed.dtd"> <TaskDefinition executor="sailpoint.GenerateCerts" name="Data Load" resultAction="Delete" type="Generic"> <Description>Schedule certs for population</Description> <Signature> <Inputs> <Argument name="population" required="true" type="string"> <Prompt>Input the population of managers to generate certifications for.     Example  TaskDefintion     <?xml version='1.services.     Best  Practices   When  all  options  are  set  correctly.  The  exercise  of  determining  the  populations  of  managers  to   provide  as  input  is  left  to  the  reader.task.  then  a  simple  split  of  the  total  manager  population  divided  by  how  many  task   executor  threads  would  work  nicely.  If  generation  run  time   performance  is  the  goal.

    Best  Practices   Define  the  GenerateCerts  Task  Executor   This  task  executor  will  be  responsible  for  taking  the  list  of  managers  to  certify  and  generating   CertificationDefintions.   Output  logging  information  about  which  manager  is  about  to  be  processed.  It  will  also  log  its  activity  so  the  process  can   be  resumed  in  the  event  of  a  failure.   For  every  manager  in  the  list  construct  a  clone  of  the  CertificationDefintion  template  referred  to   in  the  earlier  section.  In  this  example  the  name  of  the  manager  is   concatenated  with  the  template  name.   o Set  the  “certifier”  attribute  to  the  name  of  the  manager  in  the  current  iteration.   Create  a  new  TaskSchedule     o Set  the  name  to  be  equal  to  the  CertificationDefintion  clone  name.   o Set  the  launcher  to  “spadmin”   o Set  the  “executor”  argument  to  “Certification  Manager”   o Set  the  “resultName”  argument  to  be  equal  to  the  CertificationDefintion  clone  name.     Save  the  CertificationDefintion  object  in  the  context  and  commit.   Block  until  the  task  returns  or  times  out.   o Enforce  the  “certificationType”  is  equal  to  the  desired  type.   Set  custom  parameters  on  the  clone     o Change  the  name  to  a  unique  value.     The  general  flow  of  the  program  is  as  follows:   • • • Parse  the  list  of  managers  and  verify  they  are  actually  managers.   • • • • • • •   A  reference  implementation  of  the  GenerateCerts  Task  is  provided  in  the  appendix.  TaskSchedules  and  launching  them.   o Enforce  the  “subordinateCertificationEnabled”  attribute  is  set  to  “false”  to  ensure  only   certifications  for  the  specified  manager  are  generated.  In  this  case  “Manager”.               Page 5 of 11   .   Define  a  TaskManager  instance  and  run  the  defined  schedule.   Continue.   Parse  tasks  results  for  errors  and  warnings  and  write  to  log.

 The  number  of   phases  or  partitions  should  be  subdivided  by  as  many  units  as  the  total  certification  window  allows.    An  alternative   method  for  large  certification  runs  is  to  phase  certifications  by  some  parameter  that  provides  natural   load  control.  notifications  are   sent  out  for  the  entire  management  hierarchy  as  the  process  traverses  the  list  of  managers.  If  the  customer  has  a  robust   server  infrastructure  the  certifications  can  be  generated  in  parallel.    The  usual   result  of  this  is  everyone  gets  notifications  to  logon  and  do  their  certifications  at  once.  after  the  spike  passes  this  infrastructure  sits  underutilized.  However.  The  duration  varies  dependent  on  the  organization’s  unique  characteristics.    To   accomplish  this  simply  define  a  partition  size  using  the  number  of  available  task  execution  threads  and   the  total  number  of  managers.  There  should  be  a  peak  right  when  certifications  notices  are   delivered  and  acted  upon.     Best  Practices   Leveraging  the  GenerateCerts  TaskExecutor   Now  that  the  script  is  defined  generating  manager  certifications  across  instances  can  be  performed.  if  the  customer’s  organization  is  global.  This  creates  an   unusually  high  volume  of  user  load  when  the  server  is  already  busy  generating  new  certifications.  In   addition.         Scenario  Two:  Customer  Desires  Faster  Certification  Generation   Performance   Because  the  TaskExecutor  relies  on  a  separate  CertificationDefintion  for  each  and  every  manager.  server  load  is  monitored.  launch  the  next  partition  of  interleaved  manager  population.    That  way  all  the  managers  will  not  login  and  do  work  at  the  same   time  because  while  one  group  is  working  the  other  is  sleeping.  the  largest  unit  of  failure  is  now  restricted  to  one  manager.  there   are  no  dependences  on  any  past  unit  of  work  for  a  future  unit  of  work.  the  population  of  managers  can  be   interleaved  by  geographic  location.   Typically.  This  type  of  setup  is  also  desirable  in   test  scenarios  where  the  entire  certification  run  needs  to  be  tested  in  shorter  time  frames.    If  the  server  has  a  large  number  of  physical  CPU  cores  this  number  can  be   adjusted    to  match  infrastructure.  customers  attempt  to  solve  this  by  adding  more  nodes  to  the  UI  server  cluster  to  handle  the   incoming  requests.    By  default  each  “batch  server”  instance  of  Sailpoint  can  execute  five   threads  concurrently.         Page 6 of 11   .   Often  this  situation  in  noticed  after  it’s  too  late  and  the  business  is  already  logging  and  doing  work.    Or  in   separated  deployments  (UI  servers  and  batch  servers)  the  UI  servers  simply  become  overloaded  with   users  logging  on  to  the  system.    After  the  first  partition  of  certifications  is   generated.     Scenario  One:  Generate  Manager  Certifications  while  Controlling  User   Load  on  the  Web  Server  Cluster   With  the  default  functionality  of  utilizing  the  serial  method  of  generating  certifications.   After  this  peak  dies  down.      User’s  frustration  escalates  as  server  response  time  and  usability  drops.    For  example.

250  users.class">org.quartz.    Open  the  file  and  look  for  the  following  lines.  it  has   been  separated  for  clarity.threadCount”  to  the  desired  amount  of  threads.      The  simplest  implementation  of  this  is  just  to   read  the  log  after  a  failure  and  tweak  the  populations  and  re-­‐execute  the  task.    The  partition  can  now  be  calculated   by  dividing  the  total  number  of  managers  by  the  cluster  wide  thread  pool  size.jar  found  in  the  WEB-­‐ INF/lib  directory  and  copy  the  file  iiqBeans.scheduling.xml  to  the  WEB-­‐INF/classes  directory.simpl.    A  more  sophisticated     Page 7 of 11   .threadPool.this avoids the need for a quartz.quartz.properties file --> <property name="quartzProperties"> <props> <prop key="org.  provide  benefit.springframework.threadPool.    Simply  making  this   number  bigger  may.  Optionally.    Now  take  that  number  and  multiply  by   how  many  batch  server  or  default  server  nodes  that  are  available.quartz.  To  be  on  the  safe  side  it  should  not  be  more  than   double  the  number  of  physical  CPU  cores  on  the  actual  server.    The  implementation  team  does  not   know  where  to  resume  the  process  as  it’s  not  clear  where  in  the  management  hierarchy  the  process  was   when  it  failed.quartz.SimpleThreadPool</prop> <prop key="org.   <bean id="scheduler" class="org.quartz.SchedulerFactoryBean"> <!-.       Ex.  The  process  can  now  be   resumed  with  no  impact  to  the  “successful”  population.    The  task  may  launch  all  40  instances  of  GenerateCerts  executor  at  the   same  time.   If  the  implementation  is  using  a  population  as  an  input  parameter  like  in  the  example-­‐each  population   should  have  a  size  of  1.    If  the  customer  relied  on  executing  one  large   CertificationDefintion  for  the  entire  organization  this  failure  is  catastrophic.         Scenario  Three:  The  Certification  Generation  Task  Fails  in  Production   While  this  is  not  a  unique  scenario  as  error  recovery  should  be  incorporated  into  scenario  1  and  2.    50.  the  GenerateCerts  task  can  be  scripted  to  handle  multiple  populations.250.     During  the  generation  of  the  certification  bad  data  is  encountered.  This  file  will  now   override  the  provided  file.  Users  are  already  logging  on   to  the  system  to  perform  work  on  certifications  that  were  sent.threadCount">5</prop> <prop key="org.threadPool.quartz.threadPriority">5</prop> Change  the  “org.     Substantial  performance  gains  will  result  from  using  this  method.threadPool.     Using  the  GenerateCerts  task  this  type  of  failure  can  be  avoided  because  the  task  has  separated  the   work  into  smaller  units  and  logged  the  success  and  failure  of  each  unit.  or  may  not.     Best  Practices   To  edit  the  number  of  concurrent  Quartz  scheduler  threads  expand  the  identityiq.000  managers  /  40  threads  available  =  a  partition  size  of  1.  the  server  goes  down  or  some   unexpected  situation  occurs  and  the  generation  task  fails.

    Best  Practices   approach  is  to  write  a  success  or  failure  marker  to  a  table  during  execution  and  when  the  GenerateCerts   task  is  executed  again  it  can  skip  successful  members  of  the  population.           Page 8 of 11   .

  import  java.api.tools.xml.AbstractTaskExecutor.Message.      *  User:  nwellinghoff    *  Date:  10/27/11      *  Time:  4:16  PM   */     public  class  GenerateCerts  extends  AbstractTaskExecutor{     execute(SailPointContext  sailPointContext.tools.getCurrentContext().class.                    //  If  you  have  multiple  nodes  to  execute  on  you  can  split  this  list  and  execute  multiple  instances  of  the  rule  per  list                      String[]     managerList  =  csvManagerList.xml.     import  sailpoint.").task.setIsSubordinateCertificationEnabled.                  //4.ArrayList.List.  Attributes<String.XMLReferenceResolver.                    CertificationDefinition  templateCertDef  =  context.                  SailPointContext  context  =  SailPointFactory.getObject(CertificationDefinition.     Best  Practices   Appendix   Example  implementation  of  GenerateCerts  TaskExecutor     package  sailpoint.     import  sailpoint.       /**      *  Created  by  IntelliJ  IDEA.                      //Put  name  of  your  template  def  here.   import  sailpoint."Manager  Certification  Template").util.split(".put("subordinateCertificationEnabled".tools.   import  sailpoint.getAttributes().*.                        //5.Randy.  TaskResult  taskResult.          public  void   Object>  stringObjectAttributes)  throws  Exception  {                                      String  csvManagerList   =  "Andrea.Knight".util.XMLObjectFactory.services.object.       import  sailpoint.       Page 9 of 11   .task.*.Hudson.0p11  version                    //templateCertDef.  //  put  your  comma  separated  list  of  manager  ids  here.  TaskSchedule  taskSchedule.                      int  errors  =  0.         import  java.     import  sailpoint.1  version     //                templateCertDef.false).

                                 ts.                                    TaskSchedule  ts  =  new  TaskSchedule().println("Could  not  find  Identity  with  name  "  +  managerId)."Manager  Certification  Schedule  for  "  +  certifier.getInstance().                          //This                          //4.certifier.       Best  Practices     i  =  0.setName("Manager   Certification  S chedule  for  "  +  certifier.0p11   version.put("certifier".getId()).setArgument("resultName".println("Generating   certification  for  manager  "  +  certifier.                                    ts.                          try  {                                    System.0p11  version                            newCertDef.out.                            Identity  certifier  =  null.println("################################################################").                                    ts.getName()).                                    //5.  i  <  managerList.put("certificationType".  newCertDef.                                        System.setName("Manager  Certification  for  "  +  certifier.out.                                      //enforce   that  this  cert  is  a  manager  cert  not  a  globalmanager  cert                                    newCertDef.getName())."Certification  Manager").                                  context.getObjectByName(Identity.                                  if(certifier  ==  null){                                            System.getName()).                                    context.commitTransaction().managerId).cloneWithoutId(templateCertDef.                                    certifier   =  context.                                  ts.getName()).put("subordinateCertificationEnabled"."Manager").   Page 10 of 11     .getName()).                                  //newCertDef.                                  ts.(XMLReferenceResolver)context).length.setArgument("certificationDefinitionId".class.setCertifierName(certifier.setArgument("executor".println(newCertDef.         flag  will  only  generate  a  cert  for  the  manager  in  question.                                  newCertDef.                                  }                                    System."false").                                  newCertDef.                                            break.                              //make  a  copy  of  the  template                            CertificationDefinition   newCertDef  =  (CertificationDefinition)   XMLObjectFactory.out.getAttributes().                                      context.saveObject(newCertDef).getName()).attach(newCertDef).setLauncher("spadmin").getAttributes().  i++)  {                  for  (int                          String  managerId  =  managerList[i].1  version.                                      //Now   create  a  CertificationSchedule  for  this  def.                                    //4.getName()).out.getAttributes().

                                         for  (Message  m  :  tr.").printStackTrace().printStackTrace().getErrors()  !=  null)  {                                            System.     Best  Practices                                  System.getMessage()).                                  System.                                          }                                    }                                    if  (tr.println("Error  "  +  m.")..decache().                                          terminator.out.out.  1800).  Resuming  operation  on  list.println("################################################################").                                    System.getMessage()).                                    System.                          }                    }                  System..getName()).println(newCertDef.println("Finished  with  "  +  errors  +  "  errors.out..println("With  Schedule.out.                                    System.                                  }  catch  (Exception  e)  {                                          e.                                    TaskResult  tr  =  tm.getId()+  ".toXml()).   Page 11 of 11          }     .out.getName()  +  "  with  system  id  of  "  +   certifier.println(ts.println("FAILURE  :  Certification  generation  failed  on  id  "  +  certifier.TaskManager  tm  =  n ew  TaskManager(context).out.runNow(ts).println("Error   while  launching  cert  "  +  ts.deleteObject(newCertDef).awaitTask(ts.out..                                          context.println("Warn  while  launching  cert  "  +  ts.getWarnings()   !=  null)  {                                          System.println("warn  "  +  m.                                      if  (tr.println("Launching  certification.  Change  this  timeout  to  the  max                                  //This                                  //cert  generation  time  plus  20%.getWarnings())  {                                                  System.out.out.out.                                  tm.").                                  e.                                            for  (Message  m  :  tr.                                          }                                  }                              }  catch  (Exception  e)  {                                  errors++.         will  return  when  the  cert  run  is  finished  OR  the  timeout  occurs.").out.println("Cleaning  u p  generated  objects.toXml()).                                  }                                  System.                                  try  {                                          Terminator  terminator  =  new  Terminator(context)..getName())..  If  error  count  is  >  0  check  output  for  src").                            }                          finally  {                                  System.out.  Time  is  in  seconds.getErrors())  {                                                    System.