Default all users to local Windows profiles

This commit is contained in:
2026-09-18 12:06:15 -06:00
parent 01e0ee5ac4
commit 106be26e7c
11 changed files with 442 additions and 167 deletions
+5 -1
View File
@@ -18,7 +18,8 @@ param(
[string]$VpnClientAddressPoolPrefix = '172.30.0.0/24',
[string[]]$PublicEnrollmentSourceAddressPrefixes = @(),
[string]$AdministratorSourceAddressPrefix = '',
[bool]$DeployUserRoaming = $true,
[bool]$DeployUserRoaming = $false,
[switch]$AcknowledgeUserRoamingRisks,
[ValidatePattern('^$|^[a-z0-9]{3,24}$')]
[string]$UserRoamingStorageAccountName = '',
[ValidatePattern('^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])$')]
@@ -47,6 +48,9 @@ if (-not $AdministratorPassword) {
if ($DeployUserRoaming -and -not $DeployVpnGateway) {
throw 'Azure user roaming requires the P2S gateway deployed by this template so clients can reach the private Azure Files endpoint. Use -DeployUserRoaming $false with direct public enrollment.'
}
if ($DeployUserRoaming -and -not $AcknowledgeUserRoamingRisks) {
throw 'User roaming is disabled by default. To provision it, also pass -AcknowledgeUserRoamingRisks after reviewing the sign-in, sign-out, storage-availability, stale-cache, and recovery risks in docs/user-roaming.md.'
}
foreach ($shareName in @($FsLogixProfilesShareName, $RedirectedFoldersShareName)) {
if ($shareName.Contains('--')) {
throw "Azure Files share names cannot contain consecutive hyphens: $shareName"
+210
View File
@@ -0,0 +1,210 @@
#Requires -Version 5.1
[CmdletBinding(SupportsShouldProcess)]
param(
[string]$DomainController = $env:COMPUTERNAME,
[string]$StudentOuName = 'Alumnos',
[string]$ProfessorOuName = 'Docentes',
[string]$AdministrativeOuName = 'Administrativos',
[string]$LaboratoryOuName = 'Laboratorio',
[string]$StudentGroupName = 'SGU-Alumnos',
[string]$ProfessorGroupName = 'SGU-Docentes',
[string]$AdministrativeGroupName = 'SGU-Administrativos',
[string]$StudentGpoName = 'SGU - AL redirected folders',
[string]$StaffGpoName = 'SGU - AD-DO FSLogix profiles',
[string]$FsLogixDeploymentGpoName = 'SGU - FSLogix client deployment',
[switch]$PreserveLegacyUserMappings
)
$ErrorActionPreference = 'Stop'
function Assert-Administrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw 'Run this script from an elevated Windows PowerShell 5.1 session on the SGU domain controller.'
}
}
function Set-SguPolicyValue {
param(
[Parameter(Mandatory)][string]$GpoName,
[Parameter(Mandatory)][string]$DomainName,
[Parameter(Mandatory)][string]$Server,
[Parameter(Mandatory)][string]$Key,
[Parameter(Mandatory)][string]$ValueName,
[Parameter(Mandatory)][ValidateSet('DWord','String','ExpandString')][string]$Type,
[Parameter(Mandatory)]$Value
)
if ($PSCmdlet.ShouldProcess("$GpoName :: $Key\\$ValueName", "Set rollback value $Value")) {
Remove-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName "**del.$ValueName" -ErrorAction SilentlyContinue | Out-Null
Set-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName $ValueName -Type $Type -Value $Value | Out-Null
}
}
function Remove-SguPolicyValue {
param(
[Parameter(Mandatory)][string]$GpoName,
[Parameter(Mandatory)][string]$DomainName,
[Parameter(Mandatory)][string]$Server,
[Parameter(Mandatory)][string]$Key,
[Parameter(Mandatory)][string]$ValueName
)
if ($PSCmdlet.ShouldProcess("$GpoName :: $Key\\$ValueName", 'Remove roaming value')) {
Remove-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName $ValueName -ErrorAction SilentlyContinue | Out-Null
Set-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName "**del.$ValueName" -Type String -Value '' | Out-Null
}
}
Assert-Administrator
Import-Module ActiveDirectory -ErrorAction Stop
Import-Module GroupPolicy -ErrorAction Stop
$domain = Get-ADDomain -Server $DomainController
$domainName = $domain.DNSRoot
$domainDn = $domain.DistinguishedName
$laboratoryOuDn = "OU=$LaboratoryOuName,$domainDn"
$usersOuDn = "OU=Usuarios-SGU,$domainDn"
$studentOuDn = "OU=$StudentOuName,$usersOuDn"
$professorOuDn = "OU=$ProfessorOuName,$usersOuDn"
$administrativeOuDn = "OU=$AdministrativeOuName,$usersOuDn"
foreach ($ou in $laboratoryOuDn,$studentOuDn,$professorOuDn,$administrativeOuDn) {
Get-ADOrganizationalUnit -Identity $ou -Server $DomainController -ErrorAction Stop | Out-Null
}
$staffGpo = Get-GPO -Name $StaffGpoName -Domain $domainName -Server $DomainController `
-ErrorAction SilentlyContinue
if (-not $staffGpo -and $PSCmdlet.ShouldProcess($StaffGpoName, 'Create local-profile enforcement GPO')) {
$staffGpo = New-GPO -Name $StaffGpoName -Domain $domainName -Server $DomainController
}
if (-not $staffGpo) {
throw "The GPO '$StaffGpoName' does not exist and was not created."
}
$staffLink = @(Get-GPInheritance -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $StaffGpoName | Select-Object -First 1
if (-not $staffLink -and $PSCmdlet.ShouldProcess($laboratoryOuDn, "Link '$StaffGpoName'")) {
New-GPLink -Name $StaffGpoName -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController -LinkEnabled Yes | Out-Null
}
elseif ($staffLink -and -not [bool]$staffLink.Enabled -and
$PSCmdlet.ShouldProcess($laboratoryOuDn, "Enable '$StaffGpoName' rollback link")) {
Set-GPLink -Name $StaffGpoName -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController -LinkEnabled Yes | Out-Null
}
$profilesRoot = 'HKLM\SOFTWARE\FSLogix\Profiles'
Set-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key $profilesRoot -ValueName Enabled -Type DWord -Value 0
Set-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key 'HKLM\SOFTWARE\FSLogix\ODFC' -ValueName Enabled -Type DWord -Value 0
foreach ($serviceName in 'frxsvc','frxccds') {
Set-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key "HKLM\SYSTEM\CurrentControlSet\Services\$serviceName" `
-ValueName Start -Type DWord -Value 4
}
Remove-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key 'HKLM\SOFTWARE\FSLogix\Apps' -ValueName VHDCompactDisk
$profileValueNames = @(
'CCDLocations','VHDLocations','CcdUnregisterTimeout','ClearCacheOnForcedUnregister',
'ClearCacheOnLogoff','HealthyProvidersRequiredForRegister',
'HealthyProvidersRequiredForUnregister','PreventLoginWithFailure',
'PreventLoginWithTempProfile','DeleteLocalProfileWhenVHDShouldApply',
'FlipFlopProfileDirectoryName','IsDynamic','LockedRetryCount','LockedRetryInterval',
'ProfileType','ReAttachIntervalSeconds','ReAttachRetryCount','SizeInMBs','VolumeType',
'VHDCompactDisk'
)
$roleGroups = @(
Get-ADGroup -Identity "CN=$ProfessorGroupName,$professorOuDn" -Server $DomainController
Get-ADGroup -Identity "CN=$AdministrativeGroupName,$administrativeOuDn" -Server $DomainController
)
foreach ($group in $roleGroups) {
$key = "$profilesRoot\ObjectSpecific\$($group.SID.Value)"
Set-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key $key -ValueName Enabled -Type DWord -Value 0
foreach ($valueName in $profileValueNames) {
Remove-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName `
-Server $DomainController -Key $key -ValueName $valueName
}
}
Set-SguPolicyValue -GpoName $StaffGpoName -DomainName $domainName -Server $DomainController `
-Key 'HKLM\SOFTWARE\SGU\UserRoaming' -ValueName StaffProfileStorageMode `
-Type String -Value Disabled
$studentGpo = Get-GPO -Name $StudentGpoName -Domain $domainName -Server $DomainController `
-ErrorAction SilentlyContinue
if ($studentGpo) {
$studentLink = @(Get-GPInheritance -Target $studentOuDn -Domain $domainName `
-Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $StudentGpoName | Select-Object -First 1
if ($studentLink -and -not [bool]$studentLink.Enabled -and
$PSCmdlet.ShouldProcess($studentOuDn, "Enable '$StudentGpoName' local-path rollback")) {
Set-GPLink -Name $StudentGpoName -Target $studentOuDn -Domain $domainName `
-Server $DomainController -LinkEnabled Yes | Out-Null
}
$shellFoldersKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
Set-SguPolicyValue -GpoName $StudentGpoName -DomainName $domainName -Server $DomainController `
-Key $shellFoldersKey -ValueName Desktop -Type ExpandString `
-Value '%USERPROFILE%\Desktop'
Set-SguPolicyValue -GpoName $StudentGpoName -DomainName $domainName -Server $DomainController `
-Key $shellFoldersKey -ValueName Personal -Type ExpandString `
-Value '%USERPROFILE%\Documents'
Remove-SguPolicyValue -GpoName $StudentGpoName -DomainName $domainName `
-Server $DomainController -Key 'HKCU\Software\Policies\Microsoft\Windows\NetCache' `
-ValueName DisableFRAdminPin
}
$deploymentGpo = Get-GPO -Name $FsLogixDeploymentGpoName -Domain $domainName `
-Server $DomainController -ErrorAction SilentlyContinue
if ($deploymentGpo) {
$deploymentLink = @(Get-GPInheritance -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $FsLogixDeploymentGpoName | Select-Object -First 1
if ($deploymentLink -and [bool]$deploymentLink.Enabled -and
$PSCmdlet.ShouldProcess($laboratoryOuDn, "Disable '$FsLogixDeploymentGpoName'")) {
Set-GPLink -Name $FsLogixDeploymentGpoName -Target $laboratoryOuDn `
-Domain $domainName -Server $DomainController -LinkEnabled No | Out-Null
}
}
$clearedUsers = [Collections.Generic.List[string]]::new()
if (-not $PreserveLegacyUserMappings) {
foreach ($roleOu in $studentOuDn,$professorOuDn,$administrativeOuDn) {
foreach ($user in Get-ADUser -SearchBase $roleOu -SearchScope Subtree -Filter * `
-Server $DomainController -Properties profilePath,homeDirectory,homeDrive) {
if ($user.profilePath -or $user.homeDirectory -or $user.homeDrive) {
if ($PSCmdlet.ShouldProcess($user.SamAccountName, 'Clear AD profile and home-drive mappings')) {
Set-ADUser -Identity $user -Server $DomainController `
-Clear profilePath,homeDirectory,homeDrive
$clearedUsers.Add($user.SamAccountName)
}
}
}
}
}
$staffGpo = Get-GPO -Name $StaffGpoName -Domain $domainName -Server $DomainController
$studentGpo = Get-GPO -Name $StudentGpoName -Domain $domainName -Server $DomainController `
-ErrorAction SilentlyContinue
$deploymentLink = @(Get-GPInheritance -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $FsLogixDeploymentGpoName | Select-Object -First 1
[pscustomobject]@{
Domain = $domainName
UserRoamingEnabled = $false
StaffGpoVersion = "$($staffGpo.Computer.DSVersion)/$($staffGpo.Computer.SysVolVersion)"
StudentGpoVersion = if ($studentGpo) {
"$($studentGpo.User.DSVersion)/$($studentGpo.User.SysVolVersion)"
} else { $null }
FsLogixDeploymentLinkEnabled = [bool]$deploymentLink.Enabled
StaffProfilesEnabled = 0
StudentDesktop = '%USERPROFILE%\Desktop'
StudentDocuments = '%USERPROFILE%\Documents'
ClearedAdUsers = @($clearedUsers)
RebootManagedWindowsClients = $true
}
+26 -1
View File
@@ -29,10 +29,15 @@ param(
[int]$FsLogixProfileSizeMiB = 30000,
[string]$AzFilesHybridModulePath,
[switch]$UseDeviceAuthentication,
[switch]$DeleteExistingStaffLocalProfiles
[switch]$DeleteExistingStaffLocalProfiles,
[switch]$AcknowledgeUserRoamingRisks,
[string]$FsLogixDeploymentGpoName = 'SGU - FSLogix client deployment'
)
$ErrorActionPreference = 'Stop'
if (-not $AcknowledgeUserRoamingRisks -and -not $WhatIfPreference) {
throw 'User roaming is an optional high-risk feature. Pass -AcknowledgeUserRoamingRisks only after reviewing docs/user-roaming.md, testing sign-in and sign-out, and accepting the documented storage and recovery failure modes.'
}
function Assert-Administrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
@@ -158,6 +163,8 @@ function Set-SguGpoRegistryValue {
)
if ($PSCmdlet.ShouldProcess("$GpoName :: $Key\\$ValueName", "Set $Type policy value")) {
Remove-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName "**del.$ValueName" -ErrorAction SilentlyContinue | Out-Null
Set-GPRegistryValue -Name $GpoName -Domain $DomainName -Server $Server `
-Key $Key -ValueName $ValueName -Type $Type -Value $Value | Out-Null
}
@@ -431,6 +438,24 @@ $staffGpo = Ensure-SguGpoLink -Name $StaffGpoName -TargetOuDn $laboratoryOuDn `
$fsLogixRoot = 'HKLM\SOFTWARE\FSLogix\Profiles'
Set-SguGpoRegistryValue -GpoName $staffGpo.DisplayName -DomainName $domainName `
-Server $DomainController -Key $fsLogixRoot -ValueName 'Enabled' -Type DWord -Value 0
Set-SguGpoRegistryValue -GpoName $staffGpo.DisplayName -DomainName $domainName `
-Server $DomainController -Key 'HKLM\SYSTEM\CurrentControlSet\Services\frxsvc' `
-ValueName 'Start' -Type DWord -Value 2
Set-SguGpoRegistryValue -GpoName $staffGpo.DisplayName -DomainName $domainName `
-Server $DomainController -Key 'HKLM\SYSTEM\CurrentControlSet\Services\frxccds' `
-ValueName 'Start' -Type DWord -Value 2
$deploymentGpo = Get-GPO -Name $FsLogixDeploymentGpoName -Domain $domainName `
-Server $DomainController -ErrorAction SilentlyContinue
if ($deploymentGpo) {
$deploymentLink = @(Get-GPInheritance -Target $laboratoryOuDn -Domain $domainName `
-Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $FsLogixDeploymentGpoName | Select-Object -First 1
if ($deploymentLink -and -not [bool]$deploymentLink.Enabled -and
$PSCmdlet.ShouldProcess($laboratoryOuDn, "Enable '$FsLogixDeploymentGpoName'")) {
Set-GPLink -Name $FsLogixDeploymentGpoName -Target $laboratoryOuDn `
-Domain $domainName -Server $DomainController -LinkEnabled Yes | Out-Null
}
}
$fsLogixValues = [ordered]@{
Enabled = @{ Type = 'DWord'; Value = 1 }
DeleteLocalProfileWhenVHDShouldApply = @{
+1
View File
@@ -196,6 +196,7 @@ Copy-RequiredFile -Source (Join-Path $PSScriptRoot 'Start-SguAzureServerBootstra
-Destination (Join-Path $serverRoot 'Start-SguAzureServerBootstrap.cmd')
$serverScripts = @(
'Deploy-AuthBroker.ps1',
'Disable-SguAzureUserRoaming.ps1',
'Enable-SguAzureUserRoaming.ps1',
'Enable-SguServerRemoteManagement.ps1',
'Get-SguUsageReport.ps1',