Enforce SGU sign-in and session policies

This commit is contained in:
2026-09-01 15:48:26 -06:00
parent 0391320a3e
commit a166193b66
9 changed files with 227 additions and 29 deletions
+29 -1
View File
@@ -34,6 +34,7 @@ $settingsPath = Join-Path $env:ProgramData 'SGU\CredentialProvider\settings.json
$providerRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\$providerClassId"
$classRegistryPath = "HKLM:\SOFTWARE\Classes\CLSID\$providerClassId\InprocServer32"
$defaultProviderPolicyPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System'
$interactiveLogonPolicyPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
@@ -181,13 +182,34 @@ if ($PSCmdlet.ShouldProcess($installPath, 'Install and register the SGU Credenti
Set-Item -Path $providerRegistryPath -Value 'Universidad La Salle · Acceso SGU'
if (-not $DoNotSetAsDefaultCredentialProvider) {
New-Item -Path $defaultProviderPolicyPath -Force | Out-Null
if (-not (Test-Path -LiteralPath $defaultProviderPolicyPath)) {
New-Item -Path $defaultProviderPolicyPath -Force | Out-Null
}
New-ItemProperty -Path $defaultProviderPolicyPath `
-Name DefaultCredentialProvider `
-Value $providerClassId `
-PropertyType String `
-Force | Out-Null
}
# Do not leave a signed-out SGU identity exposed as a persistent user tile.
# The Microsoft password provider remains registered and supplies Other user.
if (-not (Test-Path -LiteralPath $interactiveLogonPolicyPath)) {
New-Item -Path $interactiveLogonPolicyPath -Force | Out-Null
}
New-ItemProperty -Path $interactiveLogonPolicyPath `
-Name DontDisplayLastUserName `
-Value 1 `
-PropertyType DWord `
-Force | Out-Null
if (-not (Test-Path -LiteralPath $defaultProviderPolicyPath)) {
New-Item -Path $defaultProviderPolicyPath -Force | Out-Null
}
New-ItemProperty -Path $defaultProviderPolicyPath `
-Name EnumerateLocalUsers `
-Value 0 `
-PropertyType DWord `
-Force | Out-Null
}
$defaultProviderConfigured = $false
@@ -207,5 +229,11 @@ catch {
SettingsPath = $settingsPath
Registered = Test-Path -LiteralPath $providerRegistryPath
DefaultProviderConfigured = $defaultProviderConfigured
LastSignedInUserHidden = (Get-ItemPropertyValue `
-LiteralPath $interactiveLogonPolicyPath `
-Name DontDisplayLastUserName) -eq 1
LocalUserEnumerationDisabled = (Get-ItemPropertyValue `
-LiteralPath $defaultProviderPolicyPath `
-Name EnumerateLocalUsers) -eq 0
SystemPasswordProviderPreserved = $true
}
+95
View File
@@ -0,0 +1,95 @@
[CmdletBinding(SupportsShouldProcess)]
param(
[string]$TargetOuDn = 'OU=Usuarios-SGU,DC=lci,DC=lasalle,DC=mx',
[string]$GpoName = 'SGU - User session restrictions',
[string]$DomainController = $env:COMPUTERNAME
)
$ErrorActionPreference = 'Stop'
$policyKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System'
$policyValueName = 'DisableLockWorkstation'
$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 session on a domain controller or management host.'
}
Import-Module ActiveDirectory -ErrorAction Stop
Import-Module GroupPolicy -ErrorAction Stop
$targetOu = Get-ADOrganizationalUnit `
-Identity $TargetOuDn `
-Server $DomainController `
-ErrorAction Stop
$domainDn = ($targetOu.DistinguishedName -split ',DC=', 2)[1]
if (-not $domainDn) {
throw 'TargetOuDn does not contain a domain distinguished name.'
}
$domainName = ($domainDn -replace ',DC=', '.')
$gpo = Get-GPO -Name $GpoName -Domain $domainName -Server $DomainController -ErrorAction SilentlyContinue
if (-not $gpo -and $PSCmdlet.ShouldProcess($GpoName, 'Create the SGU user policy GPO')) {
$gpo = New-GPO -Name $GpoName -Domain $domainName -Server $DomainController
}
if (-not $gpo) {
throw "The GPO '$GpoName' does not exist and was not created."
}
$existingLink = @(Get-GPInheritance -Target $TargetOuDn -Domain $domainName -Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $GpoName |
Select-Object -First 1
$existingLinkEnabled = $existingLink -and (
$existingLink.Enabled -eq $true -or
[string]$existingLink.Enabled -eq 'Yes')
if (-not $existingLink) {
if ($PSCmdlet.ShouldProcess($TargetOuDn, "Link and enable '$GpoName'")) {
New-GPLink `
-Name $GpoName `
-Target $TargetOuDn `
-Domain $domainName `
-Server $DomainController `
-LinkEnabled Yes | Out-Null
}
}
elseif (-not $existingLinkEnabled -and
$PSCmdlet.ShouldProcess($TargetOuDn, "Enable the '$GpoName' link")) {
Set-GPLink `
-Name $GpoName `
-Target $TargetOuDn `
-Domain $domainName `
-Server $DomainController `
-LinkEnabled Yes | Out-Null
}
if ($PSCmdlet.ShouldProcess($GpoName, 'Prevent SGU users from manually locking workstations')) {
Set-GPRegistryValue `
-Name $GpoName `
-Domain $domainName `
-Server $DomainController `
-Key $policyKey `
-ValueName $policyValueName `
-Type DWord `
-Value 1 | Out-Null
}
$configuredValue = Get-GPRegistryValue `
-Name $GpoName `
-Domain $domainName `
-Server $DomainController `
-Key $policyKey `
-ValueName $policyValueName
$link = @(Get-GPInheritance -Target $TargetOuDn -Domain $domainName -Server $DomainController).GpoLinks |
Where-Object DisplayName -eq $GpoName |
Select-Object -First 1
$linkEnabled = $link -and (
$link.Enabled -eq $true -or
[string]$link.Enabled -eq 'Yes')
[pscustomobject]@{
GpoName = $GpoName
GpoId = $gpo.Id
TargetOu = $TargetOuDn
LinkEnabled = [bool]$linkEnabled
DisableLockWorkstation = [int]$configuredValue.Value
}
+31
View File
@@ -14,6 +14,7 @@ $providerRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authent
$passwordProviderRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\$passwordProviderClassId"
$classRegistryPath = "HKLM:\SOFTWARE\Classes\CLSID\$providerClassId\InprocServer32"
$defaultProviderPolicyPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System'
$interactiveLogonPolicyPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
$settingsPath = Join-Path $env:ProgramData 'SGU\CredentialProvider\settings.json'
$issues = [Collections.Generic.List[string]]::new()
@@ -51,6 +52,34 @@ if (-not $defaultProviderConfigured) {
$issues.Add('The SGU provider is not assigned as the machine default credential provider.')
}
$lastSignedInUserHidden = $false
try {
$lastSignedInUserHidden = (Get-ItemPropertyValue `
-LiteralPath $interactiveLogonPolicyPath `
-Name DontDisplayLastUserName `
-ErrorAction Stop) -eq 1
}
catch {
# Report the missing or unreadable policy as a failed enrollment check.
}
if (-not $lastSignedInUserHidden) {
$issues.Add('The last signed-in user is not hidden from LogonUI.')
}
$localUserEnumerationDisabled = $false
try {
$localUserEnumerationDisabled = (Get-ItemPropertyValue `
-LiteralPath $defaultProviderPolicyPath `
-Name EnumerateLocalUsers `
-ErrorAction Stop) -eq 0
}
catch {
# Report the missing or unreadable policy as a failed enrollment check.
}
if (-not $localUserEnumerationDisabled) {
$issues.Add('Local user enumeration is not explicitly disabled for the domain client.')
}
$passwordProviderPreserved = Test-Path -LiteralPath $passwordProviderRegistryPath
if (-not $passwordProviderPreserved) {
$issues.Add('The built-in Microsoft password provider registration is missing.')
@@ -137,6 +166,8 @@ $result = [pscustomobject]@{
ProviderBinary = $registeredDll
ProviderBinaryPresent = [bool]$providerBinaryPresent
DefaultProviderConfigured = $defaultProviderConfigured
LastSignedInUserHidden = $lastSignedInUserHidden
LocalUserEnumerationDisabled = $localUserEnumerationDisabled
PasswordProviderPreserved = $passwordProviderPreserved
SettingsPresent = [bool]$settings
ClientCertificatePresent = [bool]$clientCertificatePresent