[CmdletBinding(SupportsShouldProcess)] param( [string]$RemoteDesktopPrincipal = 'LCI\SG-Laboratorio-Usuarios-RDP', [switch]$EnableAdministrativeFirewallGroups ) $ErrorActionPreference = 'Stop' $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.' } $computer = Get-CimInstance Win32_ComputerSystem if (-not $computer.PartOfDomain) { throw 'Join the computer to the domain before enabling domain-scoped remote access.' } $remoteDesktopUsersSid = [Security.Principal.SecurityIdentifier]::new('S-1-5-32-555') $remoteDesktopUsersGroup = ($remoteDesktopUsersSid.Translate([Security.Principal.NTAccount]).Value -split '\\', 2)[1] $remoteDesktopPrincipalSid = ([Security.Principal.NTAccount]::new($RemoteDesktopPrincipal)).Translate( [Security.Principal.SecurityIdentifier]) function Get-LocalGroupMemberSid { param([Parameter(Mandatory)][string]$Name) $group = [ADSI]("WinNT://$env:COMPUTERNAME/$Name,group") foreach ($member in @($group.psbase.Invoke('Members'))) { try { $sidBytes = $member.GetType().InvokeMember('objectSid', [Reflection.BindingFlags]::GetProperty, $null, $member, $null) if ($sidBytes) { ([Security.Principal.SecurityIdentifier]::new([byte[]]$sidBytes, 0)).Value } } catch { } } } if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Enable RDP and grant $RemoteDesktopPrincipal access")) { function Invoke-PowerCfgBestEffort { param([Parameter(Mandatory)][string[]]$Arguments) # Start-Process keeps powercfg's policy-override diagnostic on its own # stderr stream. In PowerShell 7, directly invoking that native command # turns stderr into a terminating ErrorRecord under $ErrorActionPreference # = 'Stop', which previously aborted this unrelated remediation work. $process = Start-Process -FilePath "$env:SystemRoot\System32\powercfg.exe" ` -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden if ($process.ExitCode -ne 0) { Write-Warning "powercfg $($Arguments -join ' ') returned exit code $($process.ExitCode); continuing enrollment repair." } } foreach ($powerChange in @( @('monitor-timeout-ac', '0'), @('monitor-timeout-dc', '0'), @('standby-timeout-ac', '0'), @('standby-timeout-dc', '0'), @('hibernate-timeout-ac', '0'), @('hibernate-timeout-dc', '0'))) { Invoke-PowerCfgBestEffort -Arguments @('/change', $powerChange[0], $powerChange[1]) } Invoke-PowerCfgBestEffort -Arguments @('/hibernate', 'off') Set-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' ` -Name fDenyTSConnections -Type DWord -Value 0 Set-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` -Name UserAuthentication -Type DWord -Value 1 Set-Service -Name TermService -StartupType Automatic Start-Service -Name TermService Get-NetFirewallRule -Name 'RemoteDesktop-UserMode-In-TCP','RemoteDesktop-UserMode-In-UDP' ` -ErrorAction SilentlyContinue | Set-NetFirewallRule -Enabled True -Profile Domain $existingMembers = @(Get-LocalGroupMemberSid -Name $remoteDesktopUsersGroup) if ($existingMembers -notcontains $remoteDesktopPrincipalSid.Value) { Add-LocalGroupMember -Group $remoteDesktopUsersGroup -Member $remoteDesktopPrincipalSid.Value } # Use Windows PowerShell so both the inbox and compatible remoting endpoints # are configured even when this helper is launched from PowerShell 7. $enableRemoting = Start-Process -FilePath "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" ` -ArgumentList @('-NoLogo', '-NoProfile', '-NonInteractive', '-Command', 'Enable-PSRemoting -Force -SkipNetworkProfileCheck') ` -Wait -PassThru -WindowStyle Hidden if ($enableRemoting.ExitCode -ne 0) { throw "Enable-PSRemoting returned $($enableRemoting.ExitCode)." } Set-Service -Name WinRM -StartupType Automatic Start-Service -Name WinRM Get-NetFirewallRule -Name 'WINRM-HTTP-In-TCP','WINRM-HTTP-In-TCP-NoScope' ` -ErrorAction SilentlyContinue | Set-NetFirewallRule -Enabled True -Profile Domain Get-NetFirewallRule -Name 'WINRM-HTTP-In-TCP-PUBLIC' -ErrorAction SilentlyContinue | Disable-NetFirewallRule if ($EnableAdministrativeFirewallGroups) { $administrativeRules = @( 'RemoteEventLogSvc-In-TCP', 'RemoteEventLogSvc-NP-In-TCP', 'RemoteEventLogSvc-RPCSS-In-TCP', 'RemoteSvcAdmin-In-TCP', 'RemoteSvcAdmin-NP-In-TCP', 'RemoteSvcAdmin-RPCSS-In-TCP', 'WMI-RPCSS-In-TCP', 'WMI-WINMGMT-In-TCP', 'WMI-ASYNC-In-TCP' ) Get-NetFirewallRule -Name $administrativeRules -ErrorAction SilentlyContinue | Set-NetFirewallRule -Enabled True -Profile Domain } } $rdpMembers = @(Get-LocalGroupMemberSid -Name $remoteDesktopUsersGroup) [pscustomobject]@{ ComputerName = $env:COMPUTERNAME Domain = $computer.Domain RemoteDesktopEnabled = (Get-ItemPropertyValue ` 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' ` -Name fDenyTSConnections) -eq 0 NetworkLevelAuthentication = (Get-ItemPropertyValue ` 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` -Name UserAuthentication) -eq 1 RemoteDesktopPrincipal = $RemoteDesktopPrincipal PrincipalIsAuthorized = $rdpMembers -contains $remoteDesktopPrincipalSid.Value TermService = (Get-Service TermService).Status WinRM = (Get-Service WinRM).Status FirewallProfile = 'Domain' AlwaysOnPowerPolicyApplied = $true }