Search the Community
Showing results for tags 'powershell quest'.
-
I've pieced together a powershell script based on the Quest cmdlets that will provision users, set attributes, add to groups, create a home folder, share the home folder, set security on the home folder. I created this in a virtual environment with one DC and had no issues, when running on the new production environment I will get intermittent errors when adding a user to a security group or when setting the file security. The problems always relate to the username being invalid, but if I slow down the process by inserting 5 second delays at various points will always seems to work. I initially presumed this was down to the AD user object not existing in time to be used later in the script but i've add loops to wait until the user exists and the loop are never triggered (therefore the user must exist at that point in the script). If I rerun the import the users that the script errors on are not the same every time, the only thing I can think of is that part of the script is working with the primary DC, the next part is connecting to the backup DC (or vice versa). If this is the case is there anywhere to force a particular DC when using the Quest cmdlets? Or does anyone know of any other reason why a delay of a few seconds is enough to make the script run properly. Any help appreciated. Morgan Function New-SecurityDescriptor ( $ACEs = (throw “Missing one or more Trustees”), [string] $ComputerName = “.”) { #Create SeCDesc object $SecDesc = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_SecurityDescriptor”).CreateInstance() #Check if input is an array or not. if ($ACEs -is [system.Array]) { #Add Each ACE from the ACE array foreach ($ACE in $ACEs ) { $SecDesc.DACL += $ACE.psobject.baseobject } } else { #Add the ACE $SecDesc.DACL = $ACEs } #Return the security Descriptor return $SecDesc } Function New-ACE ( [string] $Name = (throw “Please provide user/group name for trustee”), [string] $Domain = (throw “Please provide Domain name for trustee”), [string] $Permission = “Read”, [string] $ComputerName = “.”, [switch] $Group = $false) { #Create the Trusteee Object $Trustee = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_Trustee”).CreateInstance() #Check for Special cases Everyone and Authenticated Users) switch ($Name.ToUpper()) { “EVERYONE” { $Trustee.Domain = $Null $Trustee.Name = “EVERYONE” $Trustee.SID = @(1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0) } “AUTHENTICATED USERS” { $Trustee.Domain = “NT AUTHORITY” $Trustee.Name = “Authenticated Users” $Trustee.SID = @(1, 1, 0, 0, 0, 0, 0, 5, 11, 0, 0, 0) } default { #Search for the user or group, depending on the -Group switch if (!$group) { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Account.Name=’$Name’,Domain=’$Domain’” } else { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Group.Name=’$Name’,Domain=’$Domain’” } #Get the SID for the found account. $accountSID = [WMI] “\\$ComputerName\root\cimv2:Win32_SID.SID=’$($account.sid)’” #Setup Trusteee object $Trustee.Domain = $Domain $Trustee.Name = $Name $Trustee.SID = $accountSID.BinaryRepresentation } } #Create ACE (Access Control List) object. $ACE = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_ACE”).CreateInstance() #Select the AccessMask depending on the -Permission parameter switch ($Permission) { “Read” { $ACE.AccessMask = 1179817 } “Change” { $ACE.AccessMask = 1245631 } “Full” { $ACE.AccessMask = 2032127 } default { throw “$Permission is not a supported permission value. Possible values are ‘Read’,'Change’,'Full’” } } #Setup the rest of the ACE. $ACE.AceFlags = 3 $ACE.AceType = 0 $ACE.Trustee = $Trustee #Return the ACE return $ACE } Function New-Share ( [string] $FolderPath = (throw “Please provide the share folder path (FolderPath)”), [string] $ShareName = (throw “Please provide the Share Name”), $ACEs, [string] $Description = “”, [string] $ComputerName = “.”, $MaxUsers = $null, $Password = $null) { #Start the Text for the message. $text = “$ShareName ($FolderPath): ” #Package the SecurityDescriptor via the New-SecurityDescriptor Function. $SecDesc = New-SecurityDescriptor $ACEs #Create the share via WMI, get the return code and create the return message. $Share = [WMICLASS] “\\$ComputerName\Root\Cimv2:Win32_Share” $result = $Share.Create($FolderPath, $ShareName, 0, $MaxUsers, $Description, $Password, $SecDesc) switch ($result.ReturnValue) { 0 {$text += “has been success fully created” } 2 {$text += “Error 2: Access Denied” } 8 {$text += “Error 8: Unknown Failure” } 9 {$text += “Error 9: Invalid Name”} 10 {$text += “Error 10: Invalid Level” } 21 {$text += “Error 21: Invalid Parameter” } 22 {$text += “Error 22 : Duplicate Share”} 23 {$text += “Error 23: Redirected Path” } 24 {$text += “Error 24: Unknown Device or Directory” } 25 {$text += “Error 25: Net Name Not Found” } } #Create Custom return object and Add results $return = New-Object System.Object $return | Add-Member -type NoteProperty -name ReturnCode -value $result.ReturnValue $return | Add-Member -type NoteProperty -name Message -value $text #Return result object $return } Function ProvisionInputCSV { Param ([string]$filename) $users = Import-CSV $filename foreach ($user in $users) { $ht = @{'givenName'=$user."First Name"; 'sn'= $user."Last Name"; 'displayName'= $user."First Name" + " " + $user."Last Name"; 'email'= $user."email"; 'password'= $user.Password; 'samAccountName'= $user."Logon Name"; 'OU'= $user."OU"; 'HomeServer' = $user."HomeServer"; 'HomeServerDrive' = $user."HomeServerDrive"; 'HomeServerPath' = $user."HomeServerPath"; 'HomeDrive'= $user."HomeDrive"; 'NetBIOS'= $user."NetBIOS"; 'FQDN'= $user."FQDN Ext."; 'ProfilePath'= $user."Profile"; 'TsProfilePath'= $user."TSProfile"; 'Staff'= $user."Staff"; 'Access Write Student Folders' = $user."Access Write Student Folders"; 'Access Read Student Folders' = $user."Access Read Student Folders"; 'Sept07'= $user."Sept07" } Write-Output $ht } } Function Provision { PROCESS { CreateUser $_ CreateHomeFolder $_ SetFileSecurity $_ AddToGroup $_ } } Function CreateUser { Param($userinfo) $homedirectory= "\\" + $userinfo['HomeServer'] + "\" + $userinfo['samAccountName'] + "$" $userprincipalname= $userinfo['samAccountName'] + "@" + $userinfo['NetBIOS'] + "." + $userinfo['FQDN'] $OU= $userinfo['OU'] + ",DC=" + $userinfo['NetBIOS'] + ",DC=" + $userinfo['FQDN'] $HomeDrive= $userinfo['HomeDrive'] + ":" New-QADUser -UserPrincipalName $userprincipalname –samAccountName $userinfo['samAccountName'] –ParentContainer $OU –FirstName $userinfo['givenName'] –LastName $userinfo['sn'] –Name ($userinfo['givenName'] + ' ' + $userinfo['sn']) –displayName ($userinfo['givenName'] + ' ' + $userinfo['sn']) -email $userinfo['email'] –userPassword $userinfo['password'] -HomeDrive $HomeDrive -HomeDirectory $homedirectory -ProfilePath $userinfo['ProfilePath'] | Enable-QADUser $u = get-qaduser -samaccountname $userinfo['samAccountName'] $u.TsProfilePath = $userinfo['TsProfilePath'] $u.CommitChanges() Start-Sleep -s 5 } Function CreateHomeFolder { Param($userinfo) $folder= $userinfo['samAccountName'] $completepath= "\\" + $userinfo['HomeServer'] + "\" + $userinfo['HomeServerDrive'] + "$\" + $userinfo['HomeServerPath'] + "\" + $folder $server= $userinfo['HomeServer'] new-item $completepath -itemType Directory Start-Sleep -s 5 $completepath= $userinfo['HomeServerDrive'] + ":\" + $userinfo['HomeServerPath'] + "\" + $folder #Create Share Permission $ACE = @(New-ACE -Name “Authenticated Users” -Domain “NT AUTHORITY” -Permission “Full” -Group) #Create the share $result = New-Share -FolderPath “$completepath" -ShareName "$folder$" -ACEs $ACE -Description “$folder” -Computer “$server” #Output result message from new-share Write-Output $result.Message } Function SetFileSecurity { Param($userinfo) $folder = "\\" + $userinfo['HomeServer'] + "\" + $userinfo['HomeServerDrive'] + "$\" + $userinfo['HomeServerPath'] + "\" + $userinfo['samAccountName'] $inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit" $propagation = [system.security.accesscontrol.PropagationFlags]"None" $acl = Get-Acl $folder #This removes existing permissions #$acl.SetAccessRuleProtection($true,$false) $username= $userinfo['samAccountName'] $netbios= $userinfo['NetBIOS'] Start-Sleep -s 5 $loopvar= Get-QADUser -samaccountname $username While ($loopvar -eq $null) { Write-Output "User Doesn't Exist Yet" Start-Sleep -s 5 $loopvar= Get-QADUser -samaccountname $username } $accessrule = New-Object system.security.AccessControl.FileSystemAccessRule("$netbios\$username", "Modify", $inherit, $propagation, "Allow") $acl.AddAccessRule($accessrule) #$accessrule = New-Object system.security.AccessControl.FileSystemAccessRule("$netbios\Domain Admins", "FullControl", $inherit, $propagation, "Allow") #$acl.AddAccessRule($accessrule) #$accessrule = New-Object system.security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", $inherit, $propagation, "Allow") #$acl.AddAccessRule($accessrule) #$accessrule = New-Object system.security.AccessControl.FileSystemAccessRule("$netbios\Administrator", "FullControl", $inherit, $propagation, "Allow") #$acl.AddAccessRule($accessrule) set-acl -aclobject $acl $folder } Function AddToGroup { Param($userinfo) #Start-Sleep -s 2 $username= $userinfo['samAccountName'] $loopvar= Get-QADUser -samaccountname $username While ($loopvar -eq $null) { Write-Output "User Doesn't Exist Yet" Start-Sleep -s 5 $loopvar= Get-QADUser -samaccountname $username } $groups = 'Staff','Access Read Student Folders','Access Write Student Folders','Sept07' Foreach ($group in $groups) { If ([int]$userinfo[$group]) { $currentgroup= $userinfo['NetBIOS'] + "\"+ $group $username= $userinfo['NetBIOS'] + "\" + $userinfo['samAccountName'] Add-QADGroupMember -identity $currentgroup -member ($username)} } } ProvisionInputCSV C:\Scripts\import.csv | Provision
