Keep Provisioning Logic out of the Provisioning Code

Early on in my MIIS project I had a consultant in to give me some pointers. He showed me how to create two functions ShouldObjectExist and ReadyForCreation at the top of my MVExtensions, and use them to control provisioning.

Private Function ShouldObjectExist(ByVal mventry As MVEntry) As Boolean
        << Evaluate mventry to determine if CS object should exist >>
End Function

Private Function ReadyForCreation(ByVal mventry As MVEntry) As Boolean
        << Check all required attributes are populated in the metaverse to allow creation of CS object >>
End

The Provision Sub will then use these functions to determine the appropriate action:

Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision
        Dim ObjectShouldExist as ShouldObjectExist(mventry)
        If csObj Is Nothing AndAlso ObjectShouldExist AndAlso ReadyForCreation(mventry) Then
               CreateObject(mventry)
       ElseIf Not csObj Is Nothing AndAlso Not ObjectShouldExist Then

              csObj.Deprovision()
      End If

End Sub

Before long, however, I came to the conclusion that provisioning code is not the place for provisioning logic. Some reasons:

  1. The rules on who gets access to what are determined by business drivers, which have a habit of changing. Who wants to have to recompile code every time the boss changes their mind?
  2. Burying the rules in compiled code goes against my broad goal to reduce Fear and Loathing of IdM by making the system visible.
  3. If you change your code you’re going to have to run a Full Sync (on your test server of course) to find out whether you’re about to inadvertently delete half your user population. Depending on the number of objects in your system, this could take some time.

Luckily for me my source data was coming from SQL, and I was already using a view to aggragate the required fields. It was a simple enough matter to add calculated fields to this view that encapsulated all the provisioning logic.

I introduced a series of fields all named in<Something> that could either be “Yes” or “No”. To illustrate, here is the part of the view that determines who gets to be in Active Directory:

CASE
      WHEN Status = ‘Remove’ THEN ‘No’
      WHEN NOT Mailhost = ‘Exchange’ THEN ‘No’
      WHEN Role IN (‘Staff’,‘Student’,‘Contractor’) THEN ‘Yes’
      ELSE ‘No’
END AS inAD,

The logic element of the provisioning code then becomes beautifully simple:

Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision
       If csObj Is Nothing AndAlso mventry(“inAD”).Value = “Yes” Then
               CreateObject(mventry)
      ElseIf Not csObj Is Nothing AndAlso mventry(“inAD”).Value = “No” Then

              csObj.Deprovision()
     End If

End Sub

And now, when the rules change, all I need to do is change the view in SQL. A quick

SELECT COUNT (*) FROM <View> WHERE inAD = ‘Yes’

before and after the view change will tell me whether I’m about to make a horrible mistake. And best of all – the code doesn’t need to be touched!