Provision a Home Directory for new Accounts


UPDATED 1/26/2016

The Below Workflow is made possible with the use of an installed Custom Workflow Activity, you could download and install one via the following options:

  1. The MIMWAL (Custom Workflow Activity Library)
  2. By contacting a Microsoft Business Support Specialist
  3. Other 3rd party Custom Workflow Activities (i have not tested  this activity with all available custom workflow activities so it is strongly recommended to test)
  4. You could create one using Visual Studio, The following Blog maybe useful in providing information on how to accomplish this “How to: Create a Custom Activity Library

 

The Below workflow will only work with the target Domain Controller on Server 2008 R2 or earlier, I Have updated this workflow to work with a Target Domain Controller of Server 2012 R2 which can be found at (WAL) – Workflow Example – Create Home Directory

Below is a PowerShell workflow and Script that can be used to create and attach a Home Directory for a new user that was recently created in AD. This PowerShell script would be attached to a PowerShell Workflow that would be triggered after the User account has been created in AD. This could be achieved by using setting the MPR to trigger the workflow when the Object Sid is updated for a user in the FIM Portal. Considering the Object Sid should never change and the Object Sid comes from AD this would be a good indicator that the User account does exist in AD. You may also wish to add a function that tells the PowerShell script which DC it is to run the script against. Finally it is important that the FIMService has the necessary permissions in AD.

In the Below Workflow you could set values for Parameters to pass to the Power Shell Script, In this example I Pass variables to be used to set the Home Directory Path and the Drive letter to be set on the user account.

 

 

##Passes Variables from workflow
#Comment out for Manual testing

Param($SamName,$HomeDir,$DriveLet)

if(-not(Get-Module -name ActiveDirectory))
    {
        Import-Module ActiveDirectory
    }
##Set Variables
$Domain =$(Get-ADDomain).name
$DomainDNS = $(Get-ADDomain).DNSRoot
$Spacer=” “

##Uncomment for Manual Testing
#$SamName = “amarsiglia”
#$homedir = “\\Portal\home\”+$samName
#$DriveLet= “H”
###

if ($homedir)
    {
#Create Home Directory
        mkdir $homedir
#Assign Access Rights
        $account=$Domain+”\”+$SamName
        $rights=[System.Security.AccessControl.FileSystemRights]::FullControl
        $inheritance=[System.Security.AccessControl.InheritanceFlags]”ContainerInherit,ObjectInherit”
        $propagation=[System.Security.AccessControl.PropagationFlags]::None
        $allowdeny=[System.Security.AccessControl.AccessControlType]::Allow
        $dirACE=New-Object System.Security.AccessControl.FileSystemAccessRule ($account,$rights,$inheritance,$propagation,$allowdeny)
        $dirACL=Get-Acl $homedir
        $dirACL.AddAccessRule($dirACE)
        Set-Acl $homedir $dirACL
#Assign AD Attributes
Set-ADUser -Identity $SamName -Replace @{homeDirectory=$homedir;homeDrive=$DriveLet} -Confirm:$false
    }
Return “Success”

 

## http://blogs.msdn.com/connector_space ##

Comments (3)

  1. Carmel Abela says:

    I figured it out.

    The Activity is "Run a powershell script" with "Include in Workflow Definition"

    After trying many things, passing the Param both before the Invoke command and also inside the script block and moving the -ArgumentList to the end of the script block did the trick. Trial and error!

    Thanks!

    Carmel

    #this works:

    Param($AccountName)

    $SecureStringAsPlainText = "01000000d08c9ddf0115d1118c7a00c04fc297eb010000001f01449bc779d54da444eec37e4d29b40000000002000000000003660000c000000010000000c1361fa1bade65094f893daa240aa2680000000004800000a00000001000000018f0799080dd1a9b5c19fb4da553cdd8300000001a3bce43f1aaadeabb8e726e54182c98a0e3f9f7b46a7efc7888f5082a086d795be5994d5d3d9b634d1a44530a45ea3414000000901f5d494f633a46b6d3af2abca8f7004d6e28c3"

    $pass = $SecureStringAsPlainText | ConvertTo-SecureString

    $creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "domainhqsvc-adma",$pass

    $session = New-PSSession -ComputerName "us01-fim01.domain.com" -Credential $creds -Authentication Credssp

    Invoke-Command -Session $session -ScriptBlock {

    Param($AccountName)

    If (@(Get-Module | Where-Object {$_.Name -eq "ActiveDirectory"}).count -eq 0) {Import-module "ActiveDirectory"}

    $AccountName = "pcval-camela"

    $logfile = "c:tempADGroupAssignment_{0}.log" -f $(Get-Date -f "yyyyMMdd")

    $error.Clear() | Out-Null

    #Logging Function——————————-

    function OutputLog([string]$logmsg)

    {

    $logmsg | out-File -FilePath $Logfile -Append

    }

    #————————————————

    Try{

    $Office = (Get-ADUser $AccountName -Properties PhysicalDeliveryOfficeName).physicalDeliveryOfficeName

    }

    Catch [Exception]

    {

    $dt = (Get-Date -f "yyyy-MM-dd HH:mm:ss tt")

    OutputLog ($dt+": User with sAMAccountName "+$AccountName+" not found in domain.com")

    }

    Try{

    $UserTemplate = Get-ADUser -SearchBase "OU=User Templates,OU=Disabled Accounts,DC=domain,DC=gov" -Filter {Description -like $Office}

    }

    Catch [Exception] {}

    If ($UserTemplate -ne $NULL -and $error.Count -eq 0)

    {

    ForEach ($Group in (Get-ADUser $UserTemplate -Properties MemberOf).MemberOf)

    {

    Try{

    Add-ADGroupMember -Identity $group $AccountName -ErrorAction SilentlyContinue

    }

    Catch [Exception]{}

    }

    }

    Else

    {

    $dt = (Get-Date -f "yyyy-MM-dd HH:mm:ss tt")

    OutputLog ($dt+": Template with description "+$Office+" not found in OU=User Templates,OU=Disabled Accounts,DC=domain,DC=gov")

    }

    } -ArgumentList $AccountName

    Remove-PSSession $session

    Return $true  #to make FIM WAL happy

  2. Carmel, what PS Workflow Activity are you using? what does your workflow like? can you provide the log or even the workflow design?

  3. Carmel Abela says:

    Andrew Masse helped me do (start to do) something very similar but for some reason the Param doesn’t seem to be passing to the script.  When I test by setting the Variable manually it works fine but when I comment it out and rely on the Param, it doesn’t work.  Where do I look to troubleshoot this?  Any ideas? Maybe it’s because of the “Invoke-Command –Session” command?

    Param($AccountName)

    $SecureStringAsPlainText = "01000000d08c9ddf0115d1118c7a00c04fc297eb010000001f01449bc779d54da444eec37e4d29b40000000002001111100003660000c000000010000000c1361fa1bade65094f893daa240aa2680000000004800000a00000001000000018f0799080dd1a9b5c19fb4da553cdd8300000001a3bce43f1aaadeabb8e726e54182c98a0e3f9f7b46a7efc7888f5082a086d795be5994d5d3d9b634d1a44530a45ea3414000000901f5d494f633a46b6d3af2abca8f7004d6e28c3"

    $pass = $SecureStringAsPlainText | ConvertTo-SecureString

    $creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "domainhqsvc-adma",$pass

    $session = New-PSSession -ComputerName "usXX-fim01.domain.com" -Credential $creds -Authentication Credssp

    Invoke-Command -Session $session -ScriptBlock {

    If (@(Get-Module | Where-Object {$_.Name -eq "ActiveDirectory"}).count -eq 0) {Import-module "ActiveDirectory"}

    #$AccountName = "pcval-camela"

    $logfile = "c:tempADGroupAssignment_{0}.log" -f $(Get-Date -f "yyyyMMdd")

    $error.Clear() | Out-Null

    #Logging Function——————————-

    function OutputLog([string]$logmsg)

    {

    $logmsg | out-File -FilePath $Logfile -Append

    }

    #————————————————

    Try{

    $Office = (Get-ADUser $AccountName -Properties PhysicalDeliveryOfficeName).physicalDeliveryOfficeName

    }

    Catch [Exception]

    {

    $dt = (Get-Date -f "yyyy-MM-dd HH:mm:ss tt")

    OutputLog ($dt+": User with sAMAccountName "+$AccountName+" not found in PeaceCorps.gov")

    }

    Try{

    $UserTemplate = Get-ADUser -SearchBase "OU=User Templates,OU=Disabled Accounts,DC=domain,DC=com" -Filter {Description -like $Office}

    }

    Catch [Exception] {}

    If ($UserTemplate -ne $NULL -and $error.Count -eq 0)

    {

    ForEach ($Group in (Get-ADUser $UserTemplate -Properties MemberOf).MemberOf)

    {

    Try{

    Add-ADGroupMember -Identity $group $AccountName -ErrorAction SilentlyContinue

    }

    Catch [Exception]{}

    }

    }

    Else

    {

    $dt = (Get-Date -f "yyyy-MM-dd HH:mm:ss tt")

    OutputLog ($dt+": Template with description "+$Office+" not found in OU=User Templates,OU=Disabled Accounts,DC=domain,DC=com")

    }

    }

    Remove-PSSession $session

    Return $true  #to make FIM WAL happy

Skip to main content