{"id":1320,"date":"2011-03-09T07:55:20","date_gmt":"2011-03-09T07:55:20","guid":{"rendered":"https:\/\/www.wapshere.com\/missmiis\/?p=1320"},"modified":"2011-06-30T14:14:01","modified_gmt":"2011-06-30T14:14:01","slug":"a-script-to-create-sets-and-mprs-from-templates","status":"publish","type":"post","link":"https:\/\/www.wapshere.com\/missmiis\/a-script-to-create-sets-and-mprs-from-templates","title":{"rendered":"A script to create Sets and MPRs from Templates"},"content":{"rendered":"<p>Here&#8217;s a new script thet I&#8217;m pretty pleased with myself about!<\/p>\n<p>To make the most of the delegation flexibility in the FIM Portal, and to target your workflows correctly, you can find yourself creating a lot of Sets and MPRs. A <em>lot<\/em>. You also might find that many of them are very similar, with only the Requestor and Target Sets differing in predictable ways. This script should help with that.<\/p>\n<p><!--more--><\/p>\n<h3>The Idea<\/h3>\n<p>In my environment I have\u00c2\u00a0groups of users and groups of people who adminster those users. I&#8217;m\u00c2\u00a0using a lot of union sets\u00c2\u00a0that limit the applicable actions, with corresponding numbers of MPRs\u00c2\u00a0to tie it all together. I want each group of users\/admins to be set up in exactly the same way, and I want to be able to update the config in the future with minimum fuss.<\/p>\n<p>So what I&#8217;ve done is to\u00c2\u00a0create a bunch of Sets and MPRs that all start with the word &#8220;TEMPLATE&#8221;. I&#8217;ve then written a script that will replicate these to versions that start with\u00c2\u00a0some other word, eg., &#8220;PARIS&#8221;, at the same time sorting out all the references, so that &#8220;TEMPLATE Users&#8221; becomes &#8220;PARIS Users&#8221; etc.<\/p>\n<p>Later I can\u00c2\u00a0modify the TEMPLATE objects and re-run the script, updating the PARIS objects to match whatever additions and changes have been made.<\/p>\n<h3>The Templates<\/h3>\n<p>In Sets, I have my basic &#8220;Users&#8221; and &#8220;IT Admins&#8221;, and then I have various union sets which will limit available actions to the right circumstances. (I think the union sets are better than explicitly listing rules each time because then if, for example, my definition of what makes a &#8220;Resigned User&#8221; changes I only have to modify it in one place.)<\/p>\n<p>So it looks a bit like this:<\/p>\n<table border=\"1\">\n<tbody>\n<tr>\n<td><strong>Set Name<\/strong><\/td>\n<td><strong>Member Selection<\/strong><\/td>\n<td><strong>Comments<\/strong><\/td>\n<p>\u00c2\u00a0<\/tr>\n<tr>\n<td>TEMPLATE Users<\/td>\n<td>All users where Department = &#8220;TEMPLATE&#8221;<\/td>\n<td>The rule here doesn&#8217;t really mater, You will replace it with your real rule in the generated Users set. After that the script explicitly ignores this set.<\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE IT Admins<\/td>\n<td>Manually populated set<\/td>\n<td>If you want to do rules-based IT Admin sets as well then you will need to modify the script to also explicitly ignore them after creation.<\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE Active Users<\/td>\n<td>ResourceID in &#8220;TEMPLATE Users&#8221; and ResourceID in &#8220;Active Users&#8221;<\/td>\n<td>Use to permit actions only relevant to Active Users in this Users set.<\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE Resigned Users<\/td>\n<td>ResourceID in &#8220;TEMPLATE Users&#8221; and ResourceID in &#8220;Resigned Users&#8221;<\/td>\n<td>Use to permit actions only relevant to Resigned Users in this Users set.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Next I create varous MPRs, using the TEMPLATE Sets, and selecting my Workflows. Some examples:<\/p>\n<table border=\"1\">\n<tbody>\n<tr>\n<td><strong>MPR Name<\/strong><\/td>\n<td><strong>Sets<\/strong><\/td>\n<td><strong>Function<\/strong><\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE IT Admins can read extra details about TEMPLATE Users<\/td>\n<td>Reqestor: &#8220;TEMPLATE IT Admins&#8221;<br \/>\nTarget: &#8220;TEMPLATE Users&#8221;<\/td>\n<td>Grants read rights to extra attributes an IT Admin needs to see about the users they administer.<\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE IT Admins can modify TEMPLATE Active Users<\/td>\n<td>Reqestor: &#8220;TEMPLATE IT Admins&#8221;<br \/>\nTarget: &#8220;TEMPLATE Active Users&#8221;<\/td>\n<td>Grants modify permission to attributes only relevant to Active users, and potentially triggers Workflow activities.<\/td>\n<\/tr>\n<tr>\n<td>TEMPLATE IT Admins can delete TEMPLATE Resigned Users<\/td>\n<td>Reqestor: &#8220;TEMPLATE IT Admins&#8221;<br \/>\nTarget: &#8220;TEMPLATE Resigned Users&#8221;<\/td>\n<td>All an IT Admin to triger the workflows that will clean up accounts for people who&#8217;ve left.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Remember these are just examples &#8211; your template Sets and MPRs will be different, though be aware my script has made an assumption about the existence of a &#8220;TEMPLATE Users&#8221; group, and you may need to modify that if you don&#8217;t have one.<\/p>\n<h3>Bugs\/Features<\/h3>\n<p>The main point to be aware of with this script is that you may need to run it twice, particularly the first time you create a new group of Sets and MPRs. This is because dependencies will probably exist on Sets being created in the same operation. You could manually create the dependecy Sets first, but it&#8217;s probably easiest to just run the script twice.<\/p>\n<p>This script does not delete Sets and MPRs &#8211; it only adds and modifies. So if you delete one of your TEMPLATE Sets and re-run the script you will find that the Sets that were generated off that TEMPLATE Set before will still be there. However deleting objects in the Portal is nowhere near as arduous as creating them, so I&#8217;d rather avoid scripted deletes.<\/p>\n<h3>And here it is<\/h3>\n<div><\/div>\n<p><code><\/p>\n<pre>PARAM($tag,$FIMServer=\"localhost\")\r\n\r\n# Create-DefaultPolicy.ps1\r\n#\r\n# Written by Carol Wapshere\r\n# https:\/\/www.wapshere.com\/missmiis\/a-script-to-create-sets-and-mprs-from-templates\r\n#\r\n# Usage: Create-DefaultPolicy.ps1 -FIMServer \"myserver.mydomain.net\" -tag \"MyDesc\"\r\n#\r\n# This will search for all Sets and MPRs starting with the word \"TEMPLATE\" and attempt to create new objects\r\n# with all instances of \"TEMPLATE\" changed to \"MyDesc\", including references.\r\n#\r\n# The script may need to be run twice when creating new objects that are depended on by other objects.\r\n#\r\n\r\n#----------------------------------------------------------------------------------------------------------\r\n Function SetAttribute\r\n {\r\n    Param($object, $attributeName, $attributeValue, $isMultiValued=$false)\r\n    End\r\n    {\r\n        $importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange\r\n        if ($isMultiValued) {$importChange.Operation = 0}\r\n        else {$importChange.Operation = 1}\r\n        $importChange.AttributeName = $attributeName\r\n        $importChange.AttributeValue = $attributeValue\r\n        $importChange.FullyResolved = 1\r\n        $importChange.Locale = \"Invariant\"\r\n        If ($object.Changes -eq $null) {$object.Changes = (,$importChange)}\r\n        Else {$object.Changes += $importChange}\r\n    }\r\n}\r\n#----------------------------------------------------------------------------------------------------------\r\n Function CreateObject\r\n {\r\n    Param($objectType)\r\n    End\r\n    {\r\n       $newObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject\r\n       $newObject.ObjectType = $objectType\r\n       $newObject.SourceObjectIdentifier = [System.Guid]::NewGuid().ToString()\r\n       $newObject\r\n    }\r\n }\r\n#----------------------------------------------------------------------------------------------------------\r\n Function UpdateObject\r\n {\r\n    Param($objectType, $objectID)\r\n    End\r\n    {\r\n       $updObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject\r\n       $updObject.ObjectType = $objectType\r\n       $updObject.SourceObjectIdentifier = $objectID\r\n       $updObject.TargetObjectIdentifier = $objectID\r\n       $updObject.State = [Microsoft.ResourceManagement.Automation.ObjectModel.ImportState]::Put\r\n       $updObject\r\n    }\r\n }\r\n#----------------------------------------------------------------------------------------------------------\r\nFunction CorrectedSet\r\n{\r\n    Param($objectID)\r\n    End\r\n    {\r\n      $returnID = $objectID\r\n\r\n      if ($SetIDs.Contains($objectID))\r\n      {\r\n        $objectName = $SetIDs.Get_Item($objectID)\r\n\r\n        if ($objectName.Contains(\"TEMPLATE\"))\r\n        {\r\n          $returnName = $objectName -replace \"TEMPLATE\",$tag\r\n          if ($SetNames.Contains($returnName))\r\n          {\r\n            $returnID = $SetNames.Get_Item($returnName)\r\n            write-host \"    Replacing Set '$objectName' with '$returnName'\"\r\n          }\r\n          else\r\n          {\r\n            $query = \"\/Set[DisplayName ='\" + $returnName + \"']\"\r\n            write-host \"Searching for new Set $returnName...\"\r\n            if ($objSet = Export-FIMConfig -uri $URI -customConfig $query)\r\n            {\r\n              write-host \"    Found $returnName\"\r\n              $returnID = $objSet.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ObjectID'}\r\n              $SetIDs.Add($returnID.Value,$returnName)\r\n              $SetNames.Add($returnName,$returnID.Value)\r\n            }\r\n          }\r\n        }\r\n      }\r\n      $returnID\r\n    }\r\n}\r\n#----------------------------------------------------------------------------------------------------------\r\nFunction AddSetValues\r\n{\r\n    Param($newSet,$oldSet,$templateSet)\r\n    End\r\n    {\r\n      $templateDescription = $templateSet.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Description'}\r\n      $oldDescription = $oldSet.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Description'}\r\n      if ($templateDescription) {$newDescriptionValue = $templateDescription.Value -replace \"TEMPLATE\",$tag}\r\n      if ($newDescriptionValue -ne $oldDescription.Value) {SetAttribute -object $newSet -attributeName  \"Description\" -attributeValue $newDescriptionValue}\r\n\r\n      $templateFilter = $templateSet.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Filter'}\r\n      $oldFilter = $oldSet.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Filter'}\r\n      if ($templateFilter) {$newFilterValue = $templateFilter.Value.Replace('TEMPLATE',$tag)}\r\n      if ($newFilterValue -ne \"\" -and $newFilterValue.Contains(\"Set[ObjectID\") )\r\n      {\r\n        $regex = [regex]\"Set\\[ObjectID = '[\\w-]*'\\]\/ComputedMember\"\r\n        $matches = $regex.Matches($newFilterValue)\r\n        foreach ($match in $matches)\r\n        {\r\n          $objectID = $match.Value -replace \"Set\\[ObjectID = '\", \"\"\r\n          $objectID = $objectID  -replace(\"'\\]\/ComputedMember\",\"\")\r\n          $SetID = CorrectedSet -objectType \"Set\" -objectID \"urn:uuid:$objectID\"\r\n          $SetID = $SetID -replace \"urn:uuid:\",\"\"\r\n          $newFilterValue = $newFilterValue -replace $objectID, $SetID\r\n        }\r\n      }\r\n      if ($newFilterValue -ne $oldSetFilter.Value) {SetAttribute -object $newSet -attributeName  \"Filter\" -attributeValue $newFilterValue}\r\n\r\n      $newSet\r\n    }\r\n }\r\n#----------------------------------------------------------------------------------------------------------\r\nFunction AddMPRValues\r\n{\r\n    Param($newMPR,$oldMPR,$templateMPR)\r\n    End\r\n    {\r\n      $templateActionParameter = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionParameter'}\r\n      $oldActionParameter = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionParameter'}\r\n      foreach ($attribName in $templateActionParameter.Values)\r\n      {if ($oldActionParameter.Values -notcontains $attribName) {\r\n        write-host \"  Adding ActionParameter $attribName\"\r\n        SetAttribute -object $newMPR -attributeName  \"ActionParameter\" -attributeValue $attribName -isMultiValued $true\r\n      }}\r\n\r\n      $templateActionType = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionType'}\r\n      $oldActionType = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionType'}\r\n      foreach ($action in $templateActionType.Values)\r\n      {if ($oldActionType.Values -notcontains $action) {\r\n        write-host \"  Adding ActionType $action\"\r\n        SetAttribute -object $newMPR -attributeName  \"ActionType\" -attributeValue $action -isMultiValued $true\r\n      }}\r\n\r\n      $templateDescription = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Description'}\r\n      $oldDescription = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'Description'}\r\n      if ($templateDescription) {$newDescriptionValue = $templateDescription.Value -replace \"TEMPLATE\",$tag}\r\n      if ($oldDescription.Value -ne $newDescriptionValue)\r\n      {\r\n        write-host \"  Adding Description '$newDescription'\"\r\n        SetAttribute -object $newMPR -attributeName  \"Description\" -attributeValue $newDescriptionValue\r\n      }\r\n\r\n      $templateAuthenticationWorkflowDefinition = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'AuthenticationWorkflowDefinition'}\r\n      $oldAuthenticationWorkflowDefinition = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'AuthenticationWorkflowDefinition'}\r\n      foreach ($authn in $templateAuthenticationWorkflowDefinition.Values) \r\n      {if ($oldAuthenticationWorkflowDefinition -notcontains $authn) {\r\n        write-host \"  Adding AuthenticationWorkflowDefinition\" $authn\r\n        SetAttribute -object $newMPR -attributeName  \"AuthenticationWorkflowDefinition\" -attributeValue $authn -isMultiValued $true\r\n      }}\r\n\r\n      $templateAuthorizationWorkflowDefinition = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'AuthorizationWorkflowDefinition'}\r\n      $oldAuthorizationWorkflowDefinition = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'AuthorizationWorkflowDefinition'}\r\n      foreach ($authz in $templateAuthorizationWorkflowDefinition.Values) \r\n      {if ($oldAuthorizationWorkflowDefinition -notcontains $authz) {\r\n        write-host \"  Adding AuthorizationWorkflowDefinition\" $authz\r\n        SetAttribute -object $newMPR -attributeName  \"AuthorizationWorkflowDefinition\" -attributeValue $authz -isMultiValued $true\r\n      }}\r\n\r\n      $templateActionWorkflowDefinition = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionWorkflowDefinition'}\r\n      $oldActionWorkflowDefinition = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ActionWorkflowDefinition'}\r\n      foreach ($action in $templateActionWorkflowDefinition.Values)\r\n      {if ($oldActionWorkflowDefinition -notcontains $action) {\r\n        write-host \"  Adding ActionWorkflowDefinition\" $action\r\n        SetAttribute -object $newMPR -attributeName  \"ActionWorkflowDefinition\" -attributeValue $action -isMultiValued $true\r\n      }}\r\n\r\n      $templateGrantRight = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'GrantRight'}\r\n      $oldGrantRight = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'GrantRight'}\r\n      if ($oldGrantRight.Value -ne $templateGrantRight.Value)\r\n      {\r\n        write-host \"  Adding GrantRight\" $templateGrantRight.Value\r\n        SetAttribute -object $newMPR -attributeName  \"GrantRight\" -attributeValue $templateGrantRight.Value\r\n      }\r\n\r\n      $templateManagementPolicyRuleType = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ManagementPolicyRuleType'}\r\n      $oldManagementPolicyRuleType = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ManagementPolicyRuleType'}\r\n      if ($oldManagementPolicyRuleType.Value -ne $templateManagementPolicyRuleType.Value)\r\n      {\r\n        write-host \"  Adding MPRType\" $templateManagementPolicyRuleType.Value\r\n        SetAttribute -object $newMPR -attributeName  \"ManagementPolicyRuleType\" -attributeValue $templateManagementPolicyRuleType.Value\r\n      }\r\n\r\n      $templatePrincipalSet = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'PrincipalSet'}\r\n      $oldPrincipalSet = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'PrincipalSet'}\r\n      if ($templatePrincipalSet.Value)\r\n      {\r\n        $SetID = \"\"\r\n        $SetID = CorrectedSet -objectID $templatePrincipalSet.Value\r\n        if ($SetID -ne $oldPrincipalSet.Value) {write-host \"  Adding PrincipalSet\"; SetAttribute -object $newMPR -attributeName  \"PrincipalSet\" -attributeValue $SetID}\r\n      }\r\n\r\n      $templateResourceCurrentSet = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ResourceCurrentSet'}\r\n      $oldResourceCurrentSet = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ResourceCurrentSet'}\r\n      if ($templateResourceCurrentSet)\r\n      {\r\n        $SetID = \"\"\r\n        $SetID = CorrectedSet -objectID $templateResourceCurrentSet.Value\r\n        if ($SetID -ne $oldResourceCurrentSet.Value) {write-host \"  Adding ResourceCurrentSet\"; SetAttribute -object $newMPR -attributeName  \"ResourceCurrentSet\" -attributeValue $SetID}\r\n      }\r\n\r\n      $templateResourceFinalSet = $templateMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ResourceFinalSet'}\r\n      $oldResourceFinalSet = $oldMPR.ResourceManagementObject.ResourceManagementAttributes | where {$_.AttributeName -eq 'ResourceFinalSet'}\r\n      if ($templateResourceFinalSet)\r\n      {\r\n        $SetID = \"\"\r\n        $SetID = CorrectedSet -objectID $templateResourceFinalSet.Value\r\n        if ($SetID -ne $oldResourceFinalSet.Value) {write-host \"  Adding ResourceFinalSet\"; SetAttribute -object $newMPR -attributeName  \"ResourceFinalSet\" -attributeValue $SetID}\r\n      }\r\n\r\n      $newMPR\r\n    }\r\n}\r\n#----------------------------------------------------------------------------------------------------------\r\n\r\n##  MAIN\r\n\r\nif(@(get-pssnapin | where-object {$_.Name -eq \"FIMAutomation\"} ).count -eq 0) {add-pssnapin FIMAutomation}\r\n\r\n$URI = \"http:\/\/\" + $FIMServer + \":5725\/ResourceManagementService\"\r\n\r\n##  Enumerate existing Sets and MPRs\r\n\r\n$FIMPolicyObjects = export-fimconfig -uri $URI -customconfig ('\/Set','\/ManagementPolicyRule')\r\n\r\n$TemplateSets = @{}\r\n$TagSets = @{}\r\n$TemplateMPRs = @{}\r\n$TagMPRs = @{}\r\n$SetIDs = @{}\r\n$SetNames = @{}\r\n$MPRIDs = @{}\r\n$MPRNames = @{}\r\n\r\nwrite-host \"Enumerating objects:\"\r\n\r\nforeach ($fimobject in $FIMPolicyObjects)\r\n{\r\n  $attributes = $fimobject.ResourceManagementObject.ResourceManagementAttributes\r\n\r\n  if ($attributes | where {$_.AttributeName -eq 'ObjectType' -and $_.Value -eq 'Set'})\r\n  {\r\n    $objectID = $attributes | where {$_.AttributeName -eq 'ObjectID'}\r\n    $displayName = $attributes | where {$_.AttributeName -eq 'DisplayName'}\r\n    if ($objectID.Value -and $displayName.Value)\r\n    {\r\n      #write-host \"  Set: \" $displayName.Value\r\n      $SetIDs.Add($objectID.Value,$displayName.Value)\r\n      $SetNames.Add($displayName.Value,$objectID.Value)\r\n      if ($displayName.Value.StartsWith('TEMPLATE')) {$TemplateSets.Add($displayName.Value, $fimobject)}\r\n      if ($displayName.Value.StartsWith($tag)) {$TagSets.Add($displayName.Value, $fimobject)}\r\n    }\r\n  }\r\n\r\n  if ($attributes | where {$_.AttributeName -eq 'ObjectType' -and $_.Value -eq 'ManagementPolicyRule'})\r\n  {\r\n    $objectID = $attributes | where {$_.AttributeName -eq 'ObjectID'}\r\n    $displayName = $attributes | where {$_.AttributeName -eq 'DisplayName'}\r\n    if ($objectID.Value -and $displayName.Value)\r\n    {\r\n      #write-host \"  MPR: \" $displayName.Value\r\n      $MPRIDs.Add($objectID.Value,$displayName.Value)\r\n      $MPRNames.Add($displayName.Value,$objectID.Value)\r\n      if ($displayName.Value.StartsWith('TEMPLATE')) {$TemplateMPRs.Add($displayName.Value, $fimobject)}\r\n      if ($displayName.Value.StartsWith($tag)) {$TagMPRs.Add($displayName.Value, $fimobject)}\r\n    }\r\n  }\r\n}\r\nwrite-host\r\n\r\n## Process Sets\r\n## The \"Tag Users\" set is only created, not modified.\r\n\r\nforeach ($setName in $TemplateSets.Keys)\r\n{\r\n  write-host\r\n  $tagDisplayName = $setName.Replace('TEMPLATE',$tag)\r\n\r\n  if ($TagSets.Contains($tagDisplayName))\r\n  {\r\n    write-host \"Checking Set $tagDisplayName for updates...\"\r\n    $SetID = $SetNames.Get_Item($tagDisplayName)\r\n    $SetID = $SetID -replace \"urn:uuid:\",\"\"\r\n    $newSet = UpdateObject  -objectType \"Set\" -objectID $SetID\r\n    if ($setName -ne \"TEMPLATE Users\")\r\n      {$newSet = AddSetValues -newSet $newSet -oldSet $TagSets.Get_Item($tagDisplayName) -templateSet $TemplateSets.Get_Item($setName)}\r\n  }\r\n  else\r\n  {\r\n    write-host \"Adding Set $tagDisplayName...\"\r\n    $newSet = CreateObject -objectType \"Set\"\r\n    SetAttribute -object $newSet -attributeName  \"DisplayName\" -attributeValue $tagDisplayName\r\n    $newSet = AddSetValues -newSet $newSet -oldSet $newSet -templateSet $TemplateSets.Get_Item($setName)\r\n  }\r\n\r\n  if ($newSet.Changes.Count -gt 0)\r\n  {\r\n    $newSet.Changes\r\n    $newSet | Import-FIMConfig -uri $URI\r\n  } else {write-host \"No changes to import.\"}\r\n}\r\n\r\n## Process MPRs\r\n\r\nforeach ($MPRName in $TemplateMPRs.Keys)\r\n{\r\n  write-host\r\n  $tagDisplayName = $MPRName.Replace('TEMPLATE',$tag)\r\n\r\n  if ($TagMPRs.Contains($tagDisplayName))\r\n  {\r\n    write-host \"Updating MPR $tagDisplayName\"\r\n    $MPRID = $MPRNames.Get_Item($tagDisplayName)\r\n    $MPRID = $MPRID -replace \"urn:uuid:\",\"\"\r\n    $newMPR = UpdateObject  -objectType \"ManagementPolicyRule\" -objectID $MPRID\r\n    $newMPR = AddMPRValues -newMPR $newMPR -oldMPR $TagMPRs.Get_Item($tagDisplayName) -templateMPR $TemplateMPRs.Get_Item($MPRName)\r\n  }\r\n  else\r\n  {\r\n    write-host \"Adding MPR $tagDisplayName\"\r\n    $newMPR = CreateObject -objectType \"ManagementPolicyRule\"\r\n    SetAttribute -object $newMPR -attributeName  \"DisplayName\" -attributeValue $tagDisplayName\r\n    $newMPR = AddMPRValues -newMPR $newMPR -oldMPR $newMPR -templateMPR $TemplateMPRs.Get_Item($MPRName)\r\n}\r\n\r\n  $newMPR.Changes\r\n\r\n  if ($newMPR.Changes.Count -gt 0)\r\n  {\r\n    write-host \"Importing changes.\"\r\n    $newMPR | Import-FIMConfig -uri $URI\r\n  } else {write-host \"No changes to import.\"}\r\n\r\n}<\/pre>\n<p>\u00c2\u00a0<\/p>\n<p><\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a new script thet I&#8217;m pretty pleased with myself about! To make the most of the delegation flexibility in the FIM Portal, and to target your workflows correctly, you can find yourself creating a lot of Sets and MPRs. A lot. You also might find that many of them are very similar, with only&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","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":[42,23,54],"tags":[],"class_list":["post-1320","post","type-post","status-publish","format-standard","hentry","category-fim-2010","category-powershell","category-sets"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pkp1o-li","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/1320","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=1320"}],"version-history":[{"count":18,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/1320\/revisions"}],"predecessor-version":[{"id":1494,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/1320\/revisions\/1494"}],"wp:attachment":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/media?parent=1320"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/categories?post=1320"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/tags?post=1320"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}