{"id":7,"date":"2007-05-23T10:52:42","date_gmt":"2007-05-23T10:52:42","guid":{"rendered":"https:\/\/www.wapshere.com\/missmiis\/?p=7"},"modified":"2023-01-09T07:34:48","modified_gmt":"2023-01-09T07:34:48","slug":"keeping-provisioning-logic-out-of-the-provisioning-code","status":"publish","type":"post","link":"https:\/\/www.wapshere.com\/missmiis\/keeping-provisioning-logic-out-of-the-provisioning-code","title":{"rendered":"Keep Provisioning Logic out of the Provisioning Code"},"content":{"rendered":"<p>Early on in my MIIS project I had a consultant in to give me some pointers. He showed me how to create two functions <em>ShouldObjectExist<\/em> and <em>ReadyForCreation<\/em> at the top of my <a href=\"https:\/\/www.wapshere.com\/missmiis\/?page_id=8#mvextension\">MVExtensions<\/a>, and use them to control provisioning.<\/p>\n<blockquote><p><span style=\"color: #0000ff; font-size: xx-small;\">Private Function<\/span><span style=\"font-size: xx-small;\"> ShouldObjectExist(<\/span><span style=\"color: #0000ff; font-size: xx-small;\">ByVal<\/span><span style=\"font-size: xx-small;\"> mventry <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span><span style=\"font-size: xx-small;\"> MVEntry<\/span><span style=\"font-size: xx-small;\">) <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Boolean<\/span><br \/>\n<span style=\"font-size: xx-small;\"><em>\u00a0&lt;&lt; Evaluate mventry to determine if CS object should exist &gt;&gt;<\/em><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">End<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Function<\/span><\/span><\/p>\n<p><span style=\"color: #0000ff; font-size: xx-small;\">Private Function<\/span><span style=\"color: #000000; font-size: xx-small;\"> ReadyForCreation(<\/span><span style=\"color: #0000ff; font-size: xx-small;\">ByVal<\/span><span style=\"color: #000000; font-size: xx-small;\"> mventry <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span><span style=\"color: #000000; font-size: xx-small;\"> MVEntry<\/span><span style=\"color: #000000; font-size: xx-small;\">) <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Boolean<\/span> <span style=\"font-size: xx-small;\"><span style=\"font-size: xx-small;\"><span style=\"font-size: xx-small;\"><br \/>\n<span style=\"font-size: xx-small;\"><em>\u00a0 &lt;&lt; Check all required attributes are populated in the metaverse to allow creation of CS object &gt;&gt;<\/em><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">End <\/span><\/span><\/span><\/span><\/span><\/p><\/blockquote>\n<p>The Provision Sub will then use these functions to determine the appropriate action:<\/p>\n<blockquote><p><span style=\"color: #000000; font-size: xx-small;\">Public <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Sub<\/span><span style=\"color: #000000; font-size: xx-small;\"> Provision(<\/span><span style=\"color: #0000ff; font-size: xx-small;\">ByVal<\/span><span style=\"color: #000000; font-size: xx-small;\"> mventry <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span><span style=\"color: #000000; font-size: xx-small;\"> MVEntry) <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Implements<\/span><span style=\"font-size: xx-small;\"><span style=\"color: #000000;\"> IMVSynchronization.Provision<\/span><\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0Dim<\/span><span style=\"color: #000000; font-size: xx-small;\"> ObjectShouldExist <\/span><span style=\"color: #0000ff; font-size: xx-small;\">as<\/span><span style=\"font-size: xx-small;\"><span style=\"color: #000000;\"> ShouldObjectExist(mventry)<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 If<\/span><span style=\"font-size: xx-small;\"> csObj <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Is<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Nothing<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">AndAlso<\/span><span style=\"font-size: xx-small;\"> ObjectShouldExist <\/span><span style=\"color: #0000ff; font-size: xx-small;\">AndAlso<\/span><span style=\"font-size: xx-small;\"> ReadyForCreation(mventry) <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Then <\/span><br \/>\n<\/span><span style=\"font-size: xx-small;\">\u00a0 \u00a0CreateObject(mventry)<br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 ElseIf<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Not<\/span><span style=\"font-size: xx-small;\"> csObj <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Is<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Nothing<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">AndAlso<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Not<\/span><span style=\"font-size: xx-small;\"> ObjectShouldExist <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Then<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\">\u00a0 \u00a0csObj.Deprovision()<br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 End<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">If<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">End<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Sub<\/span><\/span><\/p><\/blockquote>\n<p>Before long, however, I came to the conclusion that <a href=\"https:\/\/www.wapshere.com\/missmiis\/?page_id=8#provisioningcode\">provisioning code<\/a> is not the place for provisioning logic. Some reasons:<\/p>\n<ol>\n<li>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?<\/li>\n<li>Burying the rules in compiled code goes against my broad goal to reduce Fear and Loathing of IdM by <a href=\"https:\/\/www.wapshere.com\/missmiis\/?p=4\" target=\"_blank\" rel=\"noopener noreferrer\">making the system visible<\/a>.<\/li>\n<li>If you change your code you&#8217;re going to have to run a Full Sync (on your test server of course) to find out whether you&#8217;re about to inadvertently delete half your user population. Depending on the number of objects in your system, this could take some time.<\/li>\n<\/ol>\n<p>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.<\/p>\n<p>I introduced a series of fields all named <em>in&lt;Something&gt;<\/em> that could either be &#8220;Yes&#8221; or &#8220;No&#8221;. To illustrate, here is the part of the view that determines who gets to be in Active Directory:<\/p>\n<blockquote><p><span style=\"color: #ff00cc; font-size: xx-small;\">CASE<\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 WHEN<\/span><span style=\"font-size: xx-small;\"> Status = <\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Remove&#8217;<\/span><span style=\"font-size: xx-small;\"> THEN <\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;No&#8217;<\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 WHEN<\/span><span style=\"font-size: xx-small;\"> NOT Mailhost = <\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Exchange&#8217;<\/span><span style=\"font-size: xx-small;\"> THEN <\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;No&#8217;<\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 WHEN<\/span><span style=\"font-size: xx-small;\"> Role IN (<\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Staff&#8217;<\/span>,<span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Student&#8217;<\/span>,<span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Contractor&#8217;<\/span><span style=\"font-size: xx-small;\">) THEN <\/span><span style=\"color: #ff0000; font-size: xx-small;\">&#8216;Yes&#8217;<\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 ELSE<\/span> <span style=\"color: #ff0000; font-size: xx-small;\">&#8216;No&#8217;<\/span><br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">END AS<\/span><span style=\"font-size: xx-small;\"> inAD,<\/span><\/p><\/blockquote>\n<p>The logic element of the provisioning code then becomes beautifully simple:<\/p>\n<blockquote><p><span style=\"color: #000000; font-size: xx-small;\">Public <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Sub<\/span><span style=\"color: #000000; font-size: xx-small;\"> Provision(<\/span><span style=\"color: #0000ff; font-size: xx-small;\">ByVal<\/span><span style=\"color: #000000; font-size: xx-small;\"> mventry <\/span><span style=\"color: #0000ff; font-size: xx-small;\">As<\/span><span style=\"color: #000000; font-size: xx-small;\"> MVEntry) <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Implements<\/span><span style=\"font-size: xx-small;\"><span style=\"color: #000000;\"> IMVSynchronization.Provision<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 If<\/span><span style=\"font-size: xx-small;\"> csObj <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Is<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Nothing<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">AndAlso<\/span><span style=\"font-size: xx-small;\"> mventry(&#8220;inAD&#8221;).Value = &#8220;Yes&#8221;<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Then<\/span><br \/>\n<\/span><span style=\"font-size: xx-small;\">\u00a0 CreateObject(mventry)<br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 ElseIf<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Not<\/span><span style=\"font-size: xx-small;\"> csObj <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Is<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Nothing<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">AndAlso<\/span> <span style=\"font-size: xx-small;\">mventry(&#8220;inAD&#8221;).Value = &#8220;No&#8221; <\/span><span style=\"color: #0000ff; font-size: xx-small;\">Then<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\">\u00a0 csObj.Deprovision()<br \/>\n<span style=\"color: #0000ff; font-size: xx-small;\">\u00a0 End<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">If<\/span><\/span><br \/>\n<span style=\"font-size: xx-small;\"><span style=\"color: #0000ff; font-size: xx-small;\">End<\/span> <span style=\"color: #0000ff; font-size: xx-small;\">Sub<\/span><\/span><\/p><\/blockquote>\n<p>And now, when the rules change, all I need to do is change the view in SQL. A quick<\/p>\n<blockquote><p><span style=\"font-size: xx-small;\">SELECT COUNT (*) FROM <em>&lt;View&gt;<\/em> WHERE inAD = &#8216;Yes&#8217;<\/span><\/p><\/blockquote>\n<p>before and after the view change will tell me whether I&#8217;m about to make a horrible mistake. And best of all &#8211; the code doesn&#8217;t need to be touched!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 \u00a0&lt;&lt; Evaluate mventry to determine if CS object&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[34,28,3,5,30],"tags":[],"class_list":["post-7","post","type-post","status-publish","format-standard","hentry","category-ilm2007","category-miis2003","category-philosophising","category-sql","category-vbnet"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pkp1o-7","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/comments?post=7"}],"version-history":[{"count":4,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/7\/revisions"}],"predecessor-version":[{"id":3327,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/7\/revisions\/3327"}],"wp:attachment":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/media?parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/categories?post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/tags?post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}