What Model will you choose ?
How many Users do you have ?
10-100 : Keep it simple.100-5000 : Low enough to scale in single instances.
5000+ : You need to scale to several instances.
Do you have several environments (Citrix Farms, huge departments with dedicated IT teams, several AD Domains) ?
No : Perfect, one to fit all is easier.
Yes : Consider volume or qtree per SILO.
Yes : Consider volume or qtree per SILO.
Now the KnowHow
classify your user into "use cases"
Instead of managing a quote for every user create qtrees for "Use Cases" and put a separate quota on it, instead of setting quotas you (better a 1st level agent) just copy the profile to another qtree. The homefolder search path feature will lead the user to the qtree where his profile is.
Unfortunatly most Citrix / Windows / FSLogic policy voodoo don't like the %USERNAME% variable as name for a share, but if you use a static share name Windows will say 2 users accessing the same UNC Path of a file will cause a lock, the trick to avoid this is to share recursivly the folder where the Folder %USERNAME% by adding /.. to the path ending with %w - %w/.. .
function Set-ProfileFolderRoot {
param(
[Parameter(Mandatory = $True, Position = 1)]
[ValidateScript( { $DirInfo = [System.IO.DirectoryInfo]"$_"; $DirInfo.Exists -and ($DirInfo.Mode -match '^d') -and ($DirInfo.FullName -ne $DirInfo.Root) })]
[String]$ShareRootPath,
[Parameter(Position = 2)][String[]]$ProfileRoot,
[Parameter()][String]$AdminNTGroup = "DOMAIN\StorageAdmins"
)
If (-not $PSBoundParameters['ProfileRoot']) {
$RootACL = [System.Security.AccessControl.DirectorySecurity]::new()
$RootACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-5-32-544",2032127,3,0,0))
$RootACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.NTAccount]$AdminNTGroup,2032127,3,0,0))
$RootACL.AddAccessRule( [System.Security.Principal.SecurityIdentifier]"S-1-1-0",131241,0,0,0)
$RootACL.SetAccessRuleProtection(1, 0)
[System.IO.Directory]::SetAccessControl($ShareRootPath, $RootACL)
$ProfileRoot = ([System.IO.DirectoryInfo]$ShareRootPath).GetDirectories().Name
}
else {
$ProfileRoot.Where( { -not $([System.IO.DirectoryInfo]"$($ShareRootPath.TrimEnd('\'))\$_").Exists }) | ForEach-Object {
[System.IO.Directory]::CreateDirectory("$($ShareRootPath.TrimEnd('\'))\$_")
}
}
$ProfileRoot.ForEach( {
$ProfileACL = [System.Security.AccessControl.DirectorySecurity]::new()
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-5-32-544",2032127,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.NTAccount]$AdminNTGroup,2032127,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-3-0",197055,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-1-0",131245,0,0,0))
$ProfileACL.SetAccessRuleProtection(1, 0)
[System.IO.Directory]::SetAccessControl("$($ShareRootPath.TrimEnd('\'))\$_", $ProfileACL)
} )
}
Use DFS-N to stay flexible and prevent pit fights about responsibilities
You don't want to coordinate with several departments changing paths in all their tools and policies, DFS-N will avoid you ALOT trouble and add some "benefit".
The Problem with the search-pattern based share is that SOMEONE has to create the profile folder first before the share will even work for the user - but if creator != user the creator has to prepare the ACLs on the folder too.
Just misuse DFS-N failover for the onboarding process. You build up a "low quota" search path - where every new user will start, just create a nonbrowseable welcome$ share on this path and define it as secondary target for the DFS-N Path. A fresh user trying to access the \\fileserver\home\ share will fallback to \fileserver\welcome$ and create his folder there, next time he access the DFS-N link the search paths will return the qtree with the lowest quota and succeed.
But be aware that if someone still use the classic Users and Computers Active Directory MMC the Path will created in his "Use Case" qtree and will has him as owner.
Keep control over the structure (special folders / trashcans / language chaos)
TBD : Reg Keys for "Well-known Folders" and Recycle Bin - desktop.ini voodoo
MONITOR everything - really EVERYTHING
TBD : REST-API Links
Setting self managing ACLs
This little function will set the right ACLs on all search pattern paths you define earlier.
function Set-ProfileFolderRoot {
param(
[Parameter(Mandatory = $True, Position = 1)]
[ValidateScript( { $DirInfo = [System.IO.DirectoryInfo]"$_"; $DirInfo.Exists -and ($DirInfo.Mode -match '^d') -and ($DirInfo.FullName -ne $DirInfo.Root) })]
[String]$ShareRootPath,
[Parameter(Position = 2)][String[]]$ProfileRoot,
[Parameter()][String]$AdminNTGroup = "DOMAIN\StorageAdmins"
)
If (-not $PSBoundParameters['ProfileRoot']) {
$RootACL = [System.Security.AccessControl.DirectorySecurity]::new()
$RootACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-5-32-544",2032127,3,0,0))
$RootACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.NTAccount]$AdminNTGroup,2032127,3,0,0))
$RootACL.AddAccessRule( [System.Security.Principal.SecurityIdentifier]"S-1-1-0",131241,0,0,0)
$RootACL.SetAccessRuleProtection(1, 0)
[System.IO.Directory]::SetAccessControl($ShareRootPath, $RootACL)
$ProfileRoot = ([System.IO.DirectoryInfo]$ShareRootPath).GetDirectories().Name
}
else {
$ProfileRoot.Where( { -not $([System.IO.DirectoryInfo]"$($ShareRootPath.TrimEnd('\'))\$_").Exists }) | ForEach-Object {
[System.IO.Directory]::CreateDirectory("$($ShareRootPath.TrimEnd('\'))\$_")
}
}
$ProfileRoot.ForEach( {
$ProfileACL = [System.Security.AccessControl.DirectorySecurity]::new()
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-5-32-544",2032127,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.NTAccount]$AdminNTGroup,2032127,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-3-0",197055,3,0,0))
$ProfileACL.AddAccessRule([System.Security.AccessControl.FileSystemAccessRule]::new([System.Security.Principal.SecurityIdentifier]"S-1-1-0",131245,0,0,0))
$ProfileACL.SetAccessRuleProtection(1, 0)
[System.IO.Directory]::SetAccessControl("$($ShareRootPath.TrimEnd('\'))\$_", $ProfileACL)
} )
}
Keine Kommentare:
Kommentar veröffentlichen