# #### Make-Home.ps1 ###### # Charlie Brooks, HBCS Ltd. <# .SYNOPSIS Make home folders for Microsoft Active Directory users. .DESCRIPTION Create a home folder for a specified user. Optionally, update the homeDirectory and homeDrive attributes of the user object in Active Directory. If no folderPath or folderName are specified, Active Directory will be queried for the homeDirectory attribute of the user; if Active Directory holds no such attribute, default values will be used and an informative message will be written to the error stream. .PARAMETER userID The Active Directory name (sAMAccountName, uid) of a valid domain user. .PARAMETER homePath The full path to the folder that will contain the specified user's home folder. .PARAMETER homeName The folder name. It should generally be identical to the user's name, or other processes may fail. .PARAMETER driveLetter When -ADupdate is specified, the driveLetter argument must contain a single alphabetic character, which will be used to populate or overwrite the homeDrive attribute of the user in Active Directory. .PARAMETER ADupdate If the user already exists in Active Directory, the homeDrive and homeDirectory attributes will be updated. .INPUTS None. You cannot pipe objects to Make-Home.ps1, although it would be a nice feature. .OUTPUTS Make-Home.ps1 does not generate output unless errors occur. .EXAMPLE Make-Home.ps1 smithjo Create home folder for user smithjo. Active Directory will be queried for the appropriate location; if the user object in AD does not have a homeDirectory attribute, one will be composed from hardcoded default values. .EXAMPLE Make-Home.ps1 -userID smithjo -homePath "\\example.org\fileroot\homeshare\homefolder\" Create home folder \\example.org\fileroot\homeshare\homefolder\smithjo with appropriate access controls. .EXAMPLE Make-Home.ps1 -userID smithjo -homePath "\\example.org\fileroot\homeshare\homefolder\" -homeName "JohnSmith" Create home folder \\example.org\fileroot\homeshare\homefolder\JohnSmith with appropriate access controls. This use is not recommended as many programs and scripts will expect home folders to be named for the user. .EXAMPLE Make-Home.ps1 -userID smithjo -driveLetter H -ADupdate Create home folder for user smithjo. Active Directory will be queried for the appropriate location; if the user object in AD does not have a homeDirectory attribute, one will be composed from hardcoded default values. If the home folder is successfully created, the homeDirectory and homeDrive attributes will be updated in AD. .NOTES AUTHOR: Charlie Brooks, HBCS VERSION: 0.1 LASTEDIT: 2013-08-14 #> # do fancy CmdletBinding() parameter specification [CmdletBinding()] Param( [Parameter(Mandatory=$True)][string]$userID, [Parameter(Mandatory=$False)][string]$homePath, [Parameter(Mandatory=$False)][string]$homeName, [Parameter(Mandatory=$False)][string]$driveLetter, [Parameter(Mandatory=$False)][switch]$ADupdate ) # per-domain fixed values $defaultDomain = "EXAMPLE" $defaultPath = "\\example.org\fileroot\homeshare\homefolder\" $defaultFolder = $userID + "test" $defaultDriveLetter = "H:" #Note COLON IS stupidly REQUIRED # extract various user attributes from Active Directory # this throws a terminating error if the user isn't in AD Import-Module activeDirectory $homeData = Get-ADuser -Identity $userID -Properties homeDrive,homeDirectory if ($homeData.homeDirectory) { $ADpath = split-path $homeData.homeDirectory -Parent $ADname = split-path $homeData.homeDirectory -Leaf } if ($homeData.homeDrive) { if (!($ADupdate) -and !($homeData.homeDrive -match "\:$")) { Write-Output "Invalid homeDrive attribute in AD, missing final colon character" } } # supply argument defaults where and when they are needed if (-NOT $homePath) { if (-NOT $ADpath) { Write-Output "No homeDirectory attribute in AD, using default path $defaultPath" $homePath = $defaultPath } else { $homePath = $ADpath } } if (-NOT $homeName) { if (-NOT $ADname) { Write-Output "No homeDirectory attribute in AD, using default folder name $defaultFolder" $homeName = $defaultFolder } else { $homeName = $ADname } } if (-NOT $driveLetter) { if (-NOT $homeData.homeDrive) { $driveLetter=$defaultDriveLetter } else { $driveLetter=$homeData.homeDrive } } # validate arguments (yes I know there are fancier ways) if ($driveLetter.Substring($driveLetter.Length-1,$driveLetter.Length) -ne ":") { $driveLetter += ":" } if (-NOT $driveLetter -match "^[a-z]:$") { Throw "$driveLetter is not a valid drive specification!" } if (-NOT (Test-Path -Path $homePath -PathType "Container")) { Throw "$($homePath) is not a valid folder!" } # it is wiser to test for known good than to place your trust in a test for # all possible bad characters, but that is not the Microsoft way. $BadFileChars = [io.path]::GetInvalidFileNamechars() + " " if ($homeName -match $BadFileChars) { Throw "Illegal character in file name: '$($matches[0])' " } if (Test-Path "$homePath\$homeName") { Throw "$homePath$homeName already exists" } # create the new folder $NewFolder = New-Item -Path $homePath -Name $homeName -ItemType "Directory" # define Access Control Rule type, rights, inheritance and propagation $Rights = [System.Security.AccessControl.FileSystemRights]"FullControl,Modify,ReadAndExecute,ListDirectory,Read,Write" $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $objType =[System.Security.AccessControl.AccessControlType]"Allow" # define a user object to which this rule will apply $objUser = New-Object System.Security.Principal.NTAccount "$myDomain\$userID" # load rule and user into an Access Control Entry object $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule($objUser, $Rights, $InheritanceFlag, $PropagationFlag, $objType) # Get existing Access Control List $ACL = Get-Acl -Path $NewFolder # Add new ACE to existing ACL $ACL.AddAccessRule($objACE) # reload modified ACL into folder metadata Set-ACL -Path $NewFolder.FullName -AclObject $ACL # if (ADupdate) { # $homeDirectory=$homePath+$homeName # Set-ADuser $userID –HomeDrive $driveLetter –HomeDirectory $HomeDirectory # }