none
Error updating single group object attribute using FIMAutomation script RRS feed

  • Question

  • Greetings and salutations.

    I am attempting to alter an existing Powershell script that we have for creating groups in FIM that pulls groups from Active Directory and creates them in FIM.  We target a single OU.

    What I attempting to do should be very straight forward, but obviously not because here I am! All I want to do is update the FIM group object(s) organizationalUnit attribute with a new value. To finish that thought to help you understand what it all does; the group will then be moved to that new OU later in the script.

    The function I created is a piecemeal of an existing function that adds members to a group in FIM. It's very similar code to what you find in this Technet article https://technet.microsoft.com/en-us/library/ff720152(v=ws.10).aspx

    Here is the function I wrote to accomplish the organizationalUnit attribute update:

    function UpdateFIM_SetNewOU ($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter, $PropList, $FIMPortalCredentials, $ResourceManagementURI)
    {
    	Try
    	{
    		Connect-QADService -Service $LocalDC -Credential $ADCredentials
    		
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList	| 
    		Select-Object $PropList |
    		Foreach-Object {
    			If($debug){Write-Host $_.sAMAccountName}
    
    			$GroupAccountName = $_.sAMAccountName
    			$OU = $NewGroupOUDN
    			
    			If($debug){Write-Host "`r`n$(Get-Date): Group Name: $GroupAccountName" -foregroundcolor white -backgroundcolor darkred}
    			If($debug){Write-Host "$(Get-Date): New Group OU: $OU"}
    			Add-Content $ResultFile "`r`n$(Get-Date): Group Name: $GroupAccountName" 
    			Add-Content $ResultFile "$(Get-Date): New Group OU: $OU"
    			
    			#Get the group object from the FIM Portal.
    			$ImportObject = $null
    			$ImportObject = QueryResource -filter "/Group[AccountName=""$GroupAccountName""]" -uri $ResourceManagementURI -Credential $FIMPortalCredentials 
    			
    			if($ImportObject)
    			{
    				#Initialize variables for modifying a FIM Portal object.
    				$ModifyImportObject = $null
    				$ModifyImportObject = ModifyImportObject -TargetIdentifier $ImportObject.ResourceManagementObject.ObjectIdentifier -ObjectType "Group"
    				if($ModifyImportObject)
    				{
    					#Set organizationalUnit attribute in modified import object
    					SetSingleValue $ModifyImportObject "organizationalUnit" $OU
    					$UpdateObject = $null
    				  	$UpdateObject = (,$ModifyImportObject)
    				  	$UpdateObject | Import-FIMConfig -uri $ResourceManagementURI -Credential $FIMPortalCredentials
    				}
    			}
    		}
    
    		Disconnect-QADService
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."
    		$ReturnValue = $true
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    		$ReturnValue = $false
    	}
    }

    Here is the error I receive at the point where it pipes UpdateObject to the Import-FIMConfig cmdlet.

    SourceObjectIdentifier : urn:uuid:d55e4f2e-912d-45ca-a677-7efb16b9f7b5
    TargetObjectIdentifier : urn:uuid:d55e4f2e-912d-45ca-a677-7efb16b9f7b5
    ObjectType             : Group
    State                  : Put
    Changes                : {organizationalUnit}
    AnchorPairs            : 
    
    Import-FIMConfig : Failure when making web service call.
    
    SourceObjectID = urn:uuid:d55e4f2e-912d-45ca-a677-7efb16b9f7b5
    Error = System.InvalidOperationException: Operation is not valid due to the current state of the object.
       at Microsoft.ResourceManagement.WebServices.Client.AttributeContainerHelper`1.GetAttribute(String attributeName)
       at Microsoft.ResourceManagement.Automation.ImportConfig.ConvertTypedAttributeValue(String objectType, String attributeNam
    e, String value)
       at Microsoft.ResourceManagement.Automation.ImportConfig.UnifiedClientPut(List`1 changeList, UniqueIdentifier objectIdenti
    fier, String objectType, CultureInfo locale)
       at Microsoft.ResourceManagement.Automation.ImportConfig.ProcessLocaleBucket(String objectIdentifier, String objectType, D
    ictionary`2 localeBucket)
       at Microsoft.ResourceManagement.Automation.ImportConfig.Put(String objectIdentifier, String objectType, List`1 changeList
    )
       at Microsoft.ResourceManagement.Automation.ImportConfig.EndProcessing()
    At C:\MnDOT\Scheduled Tasks\Copy AD groups to FIM -Task.ps1:485 char:43
    +                 $ModifyImportObject | Import-FIMConfig <<<<  -uri $ResourceManagementURI -Credential $FIMPortalCredentials
        + CategoryInfo          : InvalidOperation: (:) [Import-FIMConfig], InvalidOperationException
        + FullyQualifiedErrorId : ImportConfig,Microsoft.ResourceManagement.Automation.ImportConfig
    

    When I do a Fuji apple to Granny Smith apple comparison of the existing group membership update function to this one, the objects all look to be identical in nature, with obviously different attributes and values being used.  I don't see how this is not working, and I am about ready to quit and become a gardener.

    Cheers,

    Jesse B.

    P.S. I can upload the full script if necessary.

    Wednesday, September 23, 2015 8:31 PM

Answers

  • Whelp, scripting 101 is slapping me in the face once again. ALways remember to check the case of your variables...

    The <insert any attribute here> attribute is case sensitive.

    Wrong:

    SetSingleValue $ModifyImportObject "organizationalUnit" $OU

    Correct:

    SetSingleValue $ModifyImportObject "OrganizationalUnit" $OU

    Enjoy.


    Jesse Beauclaire =============================================================


    Thursday, October 8, 2015 7:07 PM

All replies

  • Hi,

    this error often occurs in following cases:

    1. Attribute value violates the expression set in schema on that attribute.

    2. missing Domain Attribute, which is when you create groups in UI automaticly set.

    /Peter


    Peter Stapf - ExpertCircle GmbH - My blog: JustIDM.wordpress.com

    Thursday, September 24, 2015 7:33 AM
  • Thanks for the reply Peter.  I have actually received some assistance from a Microsoft FIM PFE that asked the simple question of what the attribute type is. DOH!! I don't know why I didn't think of that. I'm waiting to receive a response to my question, but in the meantime...

    The existing known good function for adding group members is a reference(DN) type atttribute, whereas the organizationalUnit attribute I am attempting to write in the new function is a string value.

    The million dollar question is... how do you define the attribute type?

    Here's a screen capture of the $UpdateObject properties prior to being piped to Import-FIMConfig.

    UpdateObject Variable 1

    Cheers,

    Jesse B



    Thursday, September 24, 2015 12:34 PM
  • Hi Jesse,

    I think you will have only to option.

    1. define organziationalUnit as a string attribute on goup objects and simple set the OU name on that.

    or.

    2. create a reference object for OU on group objects, but then you need to have OU as an object type in portal and must import all ou's to portal.

    It depends on your need why you would like to have OU on groups, just a information then only a string might be good.

    or do you need data of OUs to manage groups it would be better to use references.

    /Peter


    Peter Stapf - ExpertCircle GmbH - My blog: JustIDM.wordpress.com

    Thursday, September 24, 2015 12:46 PM
  • Forgive me for I am not the Grand Master of FIM, lots of learning to do still.  We have used a consultant to build out our environment who has been a great resource, but is off contract at this point. I know enough to maintain the system, and make minor enhancements, and also know enough to be dangerous.

    I believe that we require the OU attribute in the group object for renaming the group in order to build out the DN of the group. You can't update CN or Name AD attributes directly, so the DN must be used and requires knowing the OU of the object.

    Here is what I am trying to make the script accomplish... Any recommendations/changes are appreciated.

    1. Function: UpdateFIM_AddADGroups
      Creates new group(s) in FIM from the groups located in the FIM To Be Managed OU.
    2. Function: UpdateFIM_AddMembersToGroup
      Populates the members of the group, including any groups as members. (I understand that they will need to also exist in FIM in order to add them to a group)
    3. Function: UpdateFIM_SetNewOU (new function, not working)
      Update the OU attribute on the new group objects of where the group will be located after the next step. If I fail to update the OU attribute with the new value the attribute still holds the old FIM To Be Managed OU information. This would break a rename of the group in the FIM portal.
    4. Function: UpdateAD_MoveProcessedGroups
      Move group(s) in AD from FIM To Be Managed OU to the FIM Managed OU.

    Wish I could change the font size there! it's so tiny!


    Jesse Beauclaire =============================================================



    Thursday, September 24, 2015 1:21 PM
  • Ok, I think we should first check what attribute type you have in portal.

    You can check this by having a look into the Portal Schema (under Administration).

    Check unter bindings which attribute type has a binding to group and then check the type of that.

    Does the existing groups also have a DN of the OU in that attribute ?

    /Peter


    Peter Stapf - ExpertCircle GmbH - My blog: JustIDM.wordpress.com

    Thursday, September 24, 2015 2:10 PM
  • The organizationalUnit attribute is bound to the Group object and is of type Indexed String.

    Yes, the groups have the organizationalUnit attribute populated during creation of the group from the script and also has the attribute synchronized from AD when the group is created in the FIM Portal. (AD-->MV--FIM)



    Jesse Beauclaire =============================================================

    Thursday, September 24, 2015 2:27 PM
  • Hi,

    there should not be a problem write that text DN into that string attribute.

    Is there maybe a expression on that attribute (See validation tab of attribute type in schema) ?


    Peter Stapf - ExpertCircle GmbH - My blog: JustIDM.wordpress.com

    Thursday, September 24, 2015 3:21 PM
  • No expression. Wide open.


    Jesse Beauclaire =============================================================

    Thursday, September 24, 2015 3:32 PM
  • Hi,

    then I assume it is something with the script maybe the value is not really a string even if it seems so from the pictures abover.

    I checked that in my demo lab and setting a string attribute a value of a DN is not a problem.
    Can you manually try to set a fixed string DN on a test group for example, just to find a issue in your script.

    Anyone else a idea ?

    /Peter


    Peter Stapf - ExpertCircle GmbH - My blog: JustIDM.wordpress.com

    Thursday, September 24, 2015 5:47 PM
  • I have already attempted to declare the $OU variable as a string.

    [string]$OU = $NewGroupOUDN


    Manually updating the organizationalUnit attribute in the FIM portal works just fine, no issues.

    Would you like me to post the complete script?


    Jesse Beauclaire =============================================================

    Thursday, September 24, 2015 6:09 PM
  • Here's the full script...

    #Declare variables for reading from Active Directory.
    Set-Variable -Name LocalDC -Value "contoso.com"
    Set-Variable -Name SearchRootUser -Value "DC=contoso,DC=com"
    Set-Variable -Name SearchRootGrp -Value "OU=FIM To Be Managed,OU=Groups,DC=contoso,DC=com"
    Set-Variable -Name NewGroupOUDN -Value "OU=FIM Managed,OU=Groups,DC=contoso,DC=com"
    Set-Variable -Name Domain -Value "AD"
    
    #Set $debug to $True to see output to screen within ISE, $False if running as task
    Set-Variable -Name Debug -Value $true
    
    #Declare variables for report files.
    $ApplicationFilePath = Split-Path $script:MyInvocation.MyCommand.Path
    sl $ApplicationFilePath
    
    #Declare variables for updating the FIM Portal.
    $CredentialsFilePath = $ApplicationFilePath + "\CREDS"
    
    #populate variables for logging
    $ResultFile = "$ApplicationFilePath\CopyGroupResults.txt"
    $AllADGroupsFile = "$ApplicationFilePath\AllADGroups.csv"
    $GroupsNotInFIMFile = "$ApplicationFilePath\GroupsNotInFIM.txt"
    $GroupsAddedToFIMFile = "$ApplicationFilePath\GroupsAddedToFIM.txt"
    $GroupMembersAddedToFIMFile = "$ApplicationFilePath\GroupMembersAddedToFIM.txt"
    $GroupMembersNotInFIMFile = "$ApplicationFilePath\GroupMembersNotInFIM.txt"
    
    #Declare variables for exception handling.
    $ErrorsFile = "$ApplicationFilePath\CopyGroupErrors.txt"
    
    #Declare variables for connecting to the FIM Powershell cmdlets.
    set-variable -name ResourceManagementURI -value "http://localhost:5725/resourcemanagementservice"
    
    ##################################################################################
    #
    #	Fim Services BASE Function Calls
    #
    ##################################################################################
    
    function QueryResource
    {
        PARAM($Filter, $URI, $Credentials)
        END
        {
            $resources = Export-FIMConfig -OnlyBaseResources -CustomConfig $Filter -Uri $URI -Credential $Credentials 
            $resources
        }
    }
    
    function CreateImportChange
    {
        PARAM($AttributeName, $AttributeValue, $Operation)
        END
        {
            $importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange 
            $importChange.Operation = $Operation
            $importChange.AttributeName = $AttributeName
            $importChange.AttributeValue = $AttributeValue
            $importChange.FullyResolved = 1
            $importChange.Locale = "Invariant"
            $importChange
        }
    }
    
    function ModifyImportObject
    {
        PARAM([string]$TargetIdentifier, $ObjectType = "Resource")
        END
        {
            $importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject 
            $importObject.ObjectType = $ObjectType
            $importObject.TargetObjectIdentifier = $TargetIdentifier
            $importObject.SourceObjectIdentifier = $TargetIdentifier
            $importObject.State = 1 # Put
            $importObject
        }
    }
    
    function AddImportChangeToImportObject
    {
        PARAM($ImportChange, $ImportObject)
        END
        {
            if ($ImportObject.Changes -eq $null)
            {
                $ImportObject.Changes = (,$ImportChange)
            }
            else
            {
                $ImportObject.Changes += $ImportChange
            }
        }
    }
    
    function CreateObject
    {
        PARAM($objectType)
        END
        {
           $newObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
           $newObject.ObjectType = $objectType
           $newObject.SourceObjectIdentifier = [System.Guid]::NewGuid().ToString()
           $newObject
         } 
    }
    
    # Operations
    # 0 = Add
    # 1 = Replace
    # 2 = Delete
    function SetSingleValue
    {
        PARAM($ImportObject, $AttributeName, $NewAttributeValue, $FullyResolved=1)
    	#PARAM($ImportObject, $AttributeName, $NewAttributeValue, $FullyResolved=1)
        END
        {
            $ImportChange = CreateImportChange -AttributeName $AttributeName -AttributeValue $NewAttributeValue -Operation 1
            $ImportChange.FullyResolved = $FullyResolved
            AddImportChangeToImportObject $ImportChange $ImportObject 
        }
    }
    
    function AddMultiValue
    {
        PARAM($ImportObject, $AttributeName, $NewAttributeValue, $FullyResolved=1)
        END
        {
            $ImportChange = CreateImportChange -AttributeName $AttributeName -AttributeValue $NewAttributeValue -Operation 0
            $ImportChange.FullyResolved = $FullyResolved
            AddImportChangeToImportObject $ImportChange $ImportObject
        }
    }
    
    function RemoveMultiValue
    {
        PARAM($ImportObject, $AttributeName, $NewAttributeValue, $FullyResolved=1)
        END
        {
            $ImportChange = CreateImportChange -AttributeName $AttributeName -AttributeValue $NewAttributeValue -Operation 2
            $ImportChange.FullyResolved = $FullyResolved
            AddImportChangeToImportObject $ImportChange $ImportObject
        }
    }
    
    function GetAttributeValue($exportObject,[string] $name) 
    {
        $attribute = $exportObject.ResourceManagementObject.ResourceManagementAttributes | 
            Where-Object {$_.AttributeName -eq $name}
        
    	if ($attribute -ne $null -and $attribute.Value) 
    	{
            $attribute.Value
        }
    }
    
    ##################################################################################
    #
    #	Fim Services Function Calls
    #
    ##################################################################################
    
    #Use this version of the Function to import complete OUs using the LDAPFilter variable at the bottom of script... I think.
    function UpdateFIM_AddADGroups($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter, $PropList, $FIMPortalCredentials, $ResourceManagementURI)
    {
    	$GroupsProcessed = 0
    	$GroupsExist = 0
    	$GroupsAdded = 0
    	$GroupSkipped = 0 
    
    	Try
    	{
    		Connect-QADService -Service $LocalDC -Credential $ADCredentials
    	
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList	|	Select-Object $PropList  |
    		Foreach-Object	{
    			$GroupAccountName = $_.sAMAccountName
    			$DN = $_.dn
    			$DisplayName = $_.name
    			$Dom = $_.Domain.Name
    			$AccountName = $_.sAMAccountName
    			$GroupType = $_.groupType.ToString()
    			$GroupScope = $_.groupScope
    			$Email = $_.mail
    			$GroupMembers = $_.member
    			$Description = $_.Description
    			$Info = $_.Info
    			$OU = $_.ParentContainerDN
    					
    			If($debug){Write-Host "`r`n$(Get-Date): Group Name: $GroupAccountName" -foregroundcolor white -backgroundcolor darkred}
    			If($debug){Write-Host "$(Get-Date): Group DN: $DN"}
    			Add-Content $ResultFile "`r`n$(Get-Date): Group Name: $GroupAccountName" 
    			Add-Content $ResultFile "$(Get-Date): Group DN: $DN"
    		
    			if (!($DN.contains("CN=Builtin")))
    			{		
    				$ExportObject = $null
    				$ExportObject = QueryResource -filter "/Group[AccountName=""$AccountName""]" -uri $ResourceManagementURI -Credential $FIMPortalCredentials 
    			
    				if($ExportObject)
    				{
    					++$GroupsProcessed
    					++$GroupsExist
    					If($debug){Write-Host "$(Get-Date): GROUP ALREADY EXISTS: The group $DisplayName already exists in FIM."}
    					Add-Content $ResultFile "$(Get-Date): GROUP ALREADY EXISTS: The group $DisplayName already exists in FIM."									
    				}
    				else
    				{
    					$NewGroup = CreateObject -objectType "Group"
    			
    					SetSingleValue $NewGroup "DisplayName" $DisplayName
    					SetSingleValue $NewGroup "Domain" "AD"
    					SetSingleValue $NewGroup "AccountName"  $AccountName
    					SetSingleValue $NewGroup "MembershipLocked"  "False"
    					SetSingleValue $NewGroup "MembershipAddWorkflow"  "Owner Approval"
    					SetSingleValue $NewGroup "Email" $Email
    					SetSingleValue $NewGroup "Scope" $GroupScope
    					SetSingleValue $NewGroup "Description" $Description 
    					SetSingleValue $NewGroup "Info" $Info 
    					SetSingleValue $NewGroup "GroupValidationStatus" "Validated"
    					SetSingleValue $NewGroup "OrganizationalUnit" $OU
    				
    					if ($GroupType -eq "Distribution")
    					{
    						SetSingleValue $NewGroup "Type" $GroupType
    					}
    					elseif ($GroupType -eq "Security" -and $Email -eq $null) 
    					{
    						SetSingleValue $NewGroup "Type" "Security"
    					}
    					else
    					{
    						#All Office 365 security groups are mail-enabled security groups.
    						SetSingleValue $NewGroup "Type" "MailEnabledSecurity"					
    					}
    				
    					#Set the owner to the FIM Portal admin account.
    					AddMultiValue  $NewGroup "Owner" "1dc8397b-68e0-4b88-b44f-83d695ddfb3b"
    			
    					#Set the displayed owner to the FIM Portal admin account.
    					SetSingleValue $NewGroup "DisplayedOwner" "1dc8397b-68e0-4b88-b44f-83d695ddfb3b"
    				
    					$NewGroup | Import-FIMConfig -uri $ResourceManagementURI -Credential $FIMPortalCredentials
    				
    					if($NewGroup -ne $null)
        	    		{
    						++$GroupsProcessed
    						++$GroupsAdded						
    						If($debug){write-host "$(Get-Date): $AccountName was added to FIM."}
    						Add-Content $ResultFile "$(Get-Date): $AccountName was added to FIM."
    					}
    					else
    		  			{
    						++$GroupSkipped
    						++$GroupsProcessed
    						If($debug){write-host "$(Get-Date): $AccountName was not added to FIM."}
    						Add-Content $ResultFile "$(Get-Date): $AccountName was not added to FIM."
    						Add-Content $ErrorsFile "$(Get-Date): $AccountName was not added to FIM."
    						Add-Content $GroupsNotInFIMFile "$GroupAccountName"						
    		  			}				
    				}
    			}
    			
    			If($debug){write-host "Groups Processed: $GroupsProcessed Groups Added: $GroupsAdded Groups Exsit: $GroupsExist Groups Skipped: $GroupSkipped"}
    			Add-Content $ResultFile "Groups Processed: $GroupsProcessed Groups Added: $GroupsAdded Groups Exsit: $GroupsExist Groups Skipped: $GroupSkipped"
    		}	
    		
    		Disconnect-QADService
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."
    		$ReturnValue = $true
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    		$ReturnValue = $false
    	}
    }
    
    
    function UpdateFIM_AddMembersToGroup($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter, $PropList, $FIMPortalCredentials, $ResourceManagementURI)
    {
    	$GroupsProcessed = 0
    	$GroupsUpdated = 0
    	
    	Try
    	{
    		Connect-QADService -Service $LocalDC -Credential $ADCredentials
    
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList	|	Select-Object $PropList  |
    		Foreach-Object	{
    			$GroupAccountName = $_.sAMAccountName			
    			$GroupMembers = $_.member
    			
    			If($debug){Write-Host "`r`n$(Get-Date): Group Name: $GroupAccountName" -foregroundcolor white -backgroundcolor darkred}
    			Add-Content $ResultFile "`r`n$(Get-Date): Group Name: $GroupAccountName" 
    			
    			#Get the group object from the FIM Portal.
    			$ImportObject = $null
    			$ImportObject = QueryResource -filter "/Group[AccountName=""$GroupAccountName""]" -uri $ResourceManagementURI -Credential $FIMPortalCredentials 
    			
    			if($ImportObject)
    			{
    			   if($GroupMembers)
    			   {
    					#Initialize variables for group procesing.
    					$GroupMemberCount = 0
    					$GroupMemberAdd = 0
    					$GroupMemberNotFoundInFIM = 0
    					
    					$GroupMemberCount = $GroupMembers.Count
    					If($debug){write-host "$(Get-Date): Total members: $GroupMemberCount"}
    					Add-Content $ResultFile "$(Get-Date): Total members: $GroupMemberCount"
    				
    					#Initialize variables for modifying a FIM Portal object.
    					$ModifyImportObject = $null
    					$ModifyImportObject = ModifyImportObject -TargetIdentifier $ImportObject.ResourceManagementObject.ObjectIdentifier -ObjectType "Group"
    			
    					foreach ($GroupMember in $GroupMembers)
    					{
    					
    						#Initialize variables for finding the group in the FIM Portal.
    						$GroupMemberObject = $null
    					
    						#Check if the member is an AD user.
    						$MemberAccountName = ADUser_GetAccountName $ADCredentials $LocalDC $SearchRootUser "(&(objectclass=user)(distinguishedName=$GroupMember))"
    						
    						if ($MemberAccountName -eq $null)
    						{
    							#Check if the member is an AD group.
    							$MemberAccountName = ADGroup_GetAccountName $ADCredentials $LocalDC $SearchRootUser "(&(objectclass=group)(distinguishedName=$GroupMember))"
    							
    							if ($MemberAccountName -ne $null)
    							{
    								#Validate the group exists in the FIM Portal.					
    								$GroupMemberObject = QueryResource -filter "/*[AccountName=""$MemberAccountName""]" -uri $ResourceManagementURI  -Credential $FIMPortalCredentials								 					
    							}						
    						}
    						else
    						{
    							#Validate the user exists in the FIM Portal.					
    							$GroupMemberObject = QueryResource -filter "/*[AccountName=""$MemberAccountName""]" -uri $ResourceManagementURI  -Credential $FIMPortalCredentials								 					
    						}
    											
    						if ($GroupMemberObject -eq $null)
    						{
    							$GroupMemberNotFoundInFIM++
    							If($debug){write-host "$(Get-Date): GROUP MEMBER NOT FOUND IN FIM: $GroupMember"}
    							Add-Content $ResultFile "$(Get-Date): GROUP MEMBER NOT FOUND IN FIM: $GroupMember"
    							Add-Content $GroupMembersNotInFIMFile "`n$GroupAccountName|$GroupMember"
    							Add-Content $ErrorsFile  "`n$(Get-Date): $GroupMember not found in FIM. Unable to add to group $GroupAccountName"							
    						}
    						else
    						{
    							$GroupMemberAdd++
    							$GroupMemberObjectID = $GroupMemberObject.ResourceManagementObject.ObjectIdentifier -replace "urn:uuid:",""
    							AddMultiValue $ModifyImportObject "ExplicitMember" $GroupMemberObjectID
    							If($debug){write-host "$(Get-Date): $GroupMember was added to the members in group $GroupAccountName"}
    							Add-Content $ResultFile  "`n$(Get-Date): $GroupMember Was added to the members in group $GroupAccountName"
    							Add-Content $GroupMembersAddedToFIMFile  "`n$GroupAccountName|$GroupMember"							
    						}	
    						
    						if (($GroupMemberAdd % 50) -eq 0)
    						{
    							#This was added because the script was not completing for groups larger than 1000.  
    							$UpdateObject = $null
    							$UpdateObject = (,$ModifyImportObject)
    							$UpdateObject | Import-FIMConfig -uri $ResourceManagementURI -Credential $FIMPortalCredentials
    															
    							#Re-initialize variables for modifying a FIM Portal object.
    							$ModifyImportObject = $null
    							$ModifyImportObject = ModifyImportObject -TargetIdentifier $ImportObject.ResourceManagementObject.ObjectIdentifier -ObjectType "Group"
    						
    							if($UpdateObject -eq $null)
    							{
    								If($debug){write-host  "$(Get-Date): Members add batch $GroupMemberAdd was not committed."}
    								Add-Content $ErrorsFile "$(Get-Date): Members add batch $GroupMemberAdd was not committed."						
    							}
    						}
    					}
    				
    				   $UpdateObject = $null
    				   $UpdateObject = (,$ModifyImportObject)
    				   $UpdateObject | Import-FIMConfig -uri $ResourceManagementURI -Credential $FIMPortalCredentials
    				
    					if($UpdateObject -ne $null)
    					{
    						++$GroupsProcessed
    						++$GroupsUpdated
    						If($debug){write-host  "$(Get-Date): The group $GroupAccountName was updated in FIM."}
    						Add-Content $ResultFile "$(Get-Date): The group $GroupAccountName was updated in FIM."						
    					}
    					else
    					{
    						++$GroupsProcessed
    						If($debug){write-host  "$(Get-Date): The group $GroupAccountName was not updated in FIM."}
    						Add-Content $ErrorsFile "$(Get-Date): The group $GroupAccountName was not updated in FIM."												
    					}				
    				}
    				else
    				{
    					If($debug){write-host  "$(Get-Date): No members in group $GroupAccountName"}
    					Add-Content $ResultFile  "$(Get-Date): No members in group $GroupAccountName"
    				}
    	
    				If($debug){write-host  "$(Get-Date): Members added to FIM: $GroupMemberAdd Members not in FIM: $GroupMemberNotFoundInFIM"}
    				Add-Content $ResultFile "$(Get-Date): Members added to FIM: $GroupMemberAdd Members not in FIM: $GroupMemberNotFoundInFIM"
    				If($debug){write-host  "$(Get-Date): Groups Processed: $GroupsProcessed Groups Updated: $GroupsUpdated"}
    				Add-Content $ResultFile "$(Get-Date): Groups Processed: $GroupsProcessed Groups Updated: $GroupsUpdated"
    
    			}
    			else
    			{
    				++$GroupsProcessed
    				If($debug){write-host "$(Get-Date): GROUP NOT FOUND IN FIM"}
    				Add-Content $ResultFile "$(Get-Date): GROUP NOT FOUND IN FIM"
    				If($debug){write-host "$(Get-Date): Groups Processed: $GroupsProcessed Groups Updated: $GroupsUpdated"}
    				Add-Content $ResultFile "$(Get-Date): Groups Processed: $GroupsProcessed Groups Updated: $GroupsUpdated"
    			}
    		}	
    	
    		
    		Disconnect-QADService
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."
    		$ReturnValue = $true
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    		$ReturnValue = $false
    	}
    }
    
    
    function UpdateFIM_SetNewOU ($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter, $PropList, $FIMPortalCredentials, $ResourceManagementURI)
    {
    	Try
    	{
    		Connect-QADService -Service $LocalDC -Credential $ADCredentials
    		
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList	| 
    		Select-Object $PropList |
    		Foreach-Object {
    			If($debug){Write-Host $_.sAMAccountName}
    
    			$GroupAccountName = $_.sAMAccountName
    			$OU = $NewGroupOUDN
    			
    			If($debug){Write-Host "`r`n$(Get-Date): Group Name: $GroupAccountName" -foregroundcolor white -backgroundcolor darkred}
    			If($debug){Write-Host "$(Get-Date): New Group OU: $OU"}
    			Add-Content $ResultFile "`r`n$(Get-Date): Group Name: $GroupAccountName" 
    			Add-Content $ResultFile "$(Get-Date): New Group OU: $OU"
    			
    			#Get the group object from the FIM Portal.
    			$ImportObject = $null
    			$ImportObject = QueryResource -filter "/Group[AccountName=""$GroupAccountName""]" -uri $ResourceManagementURI -Credential $FIMPortalCredentials 
    			
    			if($ImportObject)
    			{
    				#Initialize variables for modifying a FIM Portal object.
    				$ModifyImportObject = $null
    				$ModifyImportObject = ModifyImportObject -TargetIdentifier $ImportObject.ResourceManagementObject.ObjectIdentifier -ObjectType "Group"
    				if($ModifyImportObject)
    				{
    					#Set organizationalUnit attribute in modified import object
    					SetSingleValue $ModifyImportObject "organizationalUnit" $OU
    					#SetSingleValue $ModifyImportObject "description" $OU
    					$UpdateObject = $null
    				  	$UpdateObject = (,$ModifyImportObject)
    				  	$UpdateObject | Import-FIMConfig -uri $ResourceManagementURI -Credential $FIMPortalCredentials
    				}
    			}
    		}
    
    		Disconnect-QADService
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."
    		$ReturnValue = $true
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    		$ReturnValue = $false
    	}
    }
    
    
    ##################################################################################
    #
    #	Active Directory Calls
    #
    ##################################################################################
    
    function ADUser_GetAccountName ($ADCredentials, $LocalDC, $SearchRootUser, $LDAPFilter)
    {
    	Try
    	{
    		$PropList = "SamAccountName"
    		Get-QADUser -SizeLimit 0 -SearchRoot $SearchRootUser -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList |  Select-Object $PropList  |
    		Foreach-Object	{
    		
    			return $_.SamAccountName
    			
    		}	
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."		
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    	}		
    }
    
    function ADGroup_GetAccountName ($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter)
    {
    	Try
    	{
    		$PropList = "SamAccountName"
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList |  Select-Object $PropList  |
    		Foreach-Object	{
    		
    			return $_.SamAccountName
    			
    		}	
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."
    		$ReturnValue = $true
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    		$ReturnValue = $false
    	}		
    }
    
    
    #Move groups into new OU after they've been assimilated into FIM.
    function UpdateAD_MoveGroups ($ADCredentials, $LocalDC, $SearchRootGrp, $LDAPFilter, $PropList, $FIMPortalCredentials, $ResourceManagementURI)
    {
    
    	Try 
    	{
    		Connect-QADService -Service $LocalDC -Credential $ADCredentials
    
    		Get-QADGroup -SizeLimit 0 -SearchRoot $SearchRootGrp -LdapFilter $LDAPFilter -SearchScope Subtree -IncludedProperties $PropList	| Select-Object $PropList |
    		Foreach-Object {
    			$GroupAccountName = $_.sAMAccountName
    			
    			If($debug){Write-Host "`r`n$(Get-Date): Moving Group Name: $GroupAccountName" -foregroundcolor white -backgroundcolor darkred}
    			Add-Content $ResultFile "`r`n$(Get-Date): Moving Group Name: $GroupAccountName"
    			If($debug){Write-Host "`r`n$(Get-Date): Source OU: $GroupAccountName.ParentContainerDN" -foregroundcolor white -backgroundcolor darkred}
    			Add-Content $ResultFile "`r`n$(Get-Date): Source OU: $GroupAccountName.ParentContainerDN"
    			If($debug){Write-Host "`r`n$(Get-Date): Target OU: $NewGroupOUDN" -foregroundcolor white -backgroundcolor darkred}
    			Add-Content $ResultFile "`r`n$(Get-Date): Target OU: $NewGroupOUDN"
    			
    			#Get the group object from the FIM Portal.
    			$ImportObject = $null
    			$ImportObject = QueryResource -filter "/Group[AccountName=""$GroupAccountName""]" -uri $ResourceManagementURI -Credential $FIMPortalCredentials 
    			
    			if($ImportObject)
    			{
    				Move-QADObject ($Domain + "\" + $GroupAccountName) -NewParentContainer $NewGroupOUDN | Out-Null
    			}
    			else
    			{
    				If($debug){write-host "$(Get-Date): GROUP NOT FOUND IN FIM, ABORTING"}
    				Add-Content $ResultFile "$(Get-Date): GROUP NOT FOUND IN FIM, ABORTING"
    				Break
    			}
    		}
    	}
    	Catch [System.ArgumentException]
    	{
    		#Potential bug with Import-FIMConfig.  The FIM Portal request completes without any errors.
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was updated in FIM."		
    	}
    	Catch [Microsoft.ResourceManagement.WebServices.Exceptions.UnwillingToPerformException]
    	{
    		Add-Content $ResultFile "`n$(Get-Date) The object $ObjectID was not updated in FIM."
    	}
    
    }
    
    
    #----------------------------------------------------------------------------------------------------------
    #Main
    #----------------------------------------------------------------------------------------------------------
    
    ##################################################################################
    #
    #	Initialize
    #
    ##################################################################################
    
    Clear-Host	
    $Error.Clear()
    $gf = Get-Item $ResultFile
    
    if ($gf -eq $null)
    {
    	#Remove-Item $ResultFile
    	New-Item $ResultFile -type file
    	$gf = Get-Item $ResultFile
    
    }
    	
    $ProcessStartTime = $(Get-Date)
    Add-Content $ResultFile "****** Job started @ $ProcessStartTime ******"
    If($debug){Write-Host "`n$(Get-Date) Job started @ $ProcessStartTime."}
    
    ##################################################################################
    #
    #	Load Snap-ins
    #
    ##################################################################################
    
    if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {add-pssnapin FIMAutomation}
    
    if(@(get-pssnapin | where-object {$_.Name -eq "Quest.Activeroles.ADManagement"} ).count -eq 0) {add-pssnapin Quest.Activeroles.ADManagement}
    
    $ReqVersion = [version]"1.2.2.1254"
    $QadVersion = (Get-PSSnapin Quest.ActiveRoles.ADManagement).Version
    
    if($QadVersion -lt $ReqVersion)
    {
        throw "Quest AD cmdlets version '$ReqVersion' is required. Please download the latest version"
    }
    
    ##################################################################################
    #
    #	Get Credentials
    #
    ##################################################################################
    
    #Initialize credentials for accessing the FIM Portal.
    $FIMPortalAdmin = "AD\FIMAdmin"	
    $PasswordFilePath = "$CredentialsFilePath\FIMAdmin.txt"
    $Password = ConvertTo-SecureString (Get-Content $PasswordFilePath)
    $FIMPortalCredentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $FIMPortalAdmin, $Password	
    $Password = $null
    
    #Initialize credentials for accessing Active Directory.
    $FIMADMA = "AD\FIMADMA"	
    $PasswordFilePath = "$CredentialsFilePath\FIMADMA.txt"
    $Password = ConvertTo-SecureString (Get-Content $PasswordFilePath)
    $ADCredentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $FIMADMA, $Password	
    $Password = $null
    
    ##################################################################################
    #
    #	Get Active Directory Objects
    #
    ##################################################################################
    
    #Define the attributes to return.
    $PropList = "dn", "name","sAMAccountName","groupType","groupScope","mail","member","Description","Info","ParentContainerDN"
    
    #Define the LDAP filter.
    $LDAPFilter = "(&(objectclass=group)(cn=*))"
    #$LDAPFilter = "(&(objectclass=group)(cn=MRL LIMS USERS))"
    
    #Call these functions for importing ALL groups from the $LDAPFilter variable.
    UpdateFIM_AddADGroups 		$ADCredentials $LocalDC $SearchRootGrp $LDAPFilter $PropList $FIMPortalCredentials $ResourceManagementURI
    UpdateFIM_AddMembersToGroup $ADCredentials $LocalDC $SearchRootGrp $LDAPFilter $PropList $FIMPortalCredentials $ResourceManagementURI
    UpdateFIM_SetNewOU			$ADCredentials $LocalDC $SearchRootGrp $LDAPFilter $PropList $FIMPortalCredentials $ResourceManagementURI
    UpdateAD_MoveGroups 		$ADCredentials $LocalDC $SearchRootGrp $LDAPFilter $PropList $FIMPortalCredentials $ResourceManagementURI
    
    Add-Content $ResultFile "`n$(Get-Date) PS Errors generated during Run."
    
    foreach ($msg in $Error)
    {
    	Add-Content $ResultFile "`n$(Get-Date) ++++++++++++++"
    	Add-Content $ResultFile "`n$(Get-Date) $msg"
    	Add-Content $ResultFile "`n$(Get-Date) ++++++++++++++"
    }
    $RunEndTime = $(Get-Date)
    $TotalProcTime = ($RunEndTime - $ProcessStartTime).TotalMinutes
    Add-Content $ResultFile "`n$(Get-Date) Processing Time: $TotalProcTime."
    If($debug){Write-Host "`n$(Get-Date)  Job finished @ $RunEndTime."}
    Add-Content $ResultFile "****** Job finished @ $RunEndTime ******"
    


    Jesse Beauclaire =============================================================

    Thursday, September 24, 2015 6:17 PM
  • bump... anyone?

    Jesse Beauclaire =============================================================

    Wednesday, September 30, 2015 5:18 PM
  • Whelp, scripting 101 is slapping me in the face once again. ALways remember to check the case of your variables...

    The <insert any attribute here> attribute is case sensitive.

    Wrong:

    SetSingleValue $ModifyImportObject "organizationalUnit" $OU

    Correct:

    SetSingleValue $ModifyImportObject "OrganizationalUnit" $OU

    Enjoy.


    Jesse Beauclaire =============================================================


    Thursday, October 8, 2015 7:07 PM