diff --git a/setup.ps1 b/setup.ps1 index 2aeff46..6dfd075 100644 --- a/setup.ps1 +++ b/setup.ps1 @@ -2,38 +2,101 @@ #Requires -Version 5.1 <# - setup.ps1 - ------------------------------------------------------------ - Configuración inicial de Windows 10 +.SYNOPSIS + Configuración inicial de Windows 10. - Este script: +.DESCRIPTION + Este script configura una cuenta técnica llamada "tecnica" y + habilita Escritorio Remoto. - 1. Se ejecuta como Administrador (se autoeleva si es necesario). - 2. Crea el usuario local "tecnica" si no existe. - 3. Solicita la contraseña dos veces al crear el usuario. - 4. Añade "tecnica" al grupo de Administradores. - 5. Activa Escritorio Remoto (RDP) en Windows. - 6. Activa las reglas correspondientes del Firewall. - 7. Añade "tecnica" al grupo de usuarios de Escritorio Remoto. - 8. Oculta "tecnica" de la pantalla de inicio de sesión. - 9. Puede ejecutarse varias veces sin recrear ni modificar - innecesariamente el usuario. + Características: + + - Se autoeleva a Administrador. + - Crea el usuario "tecnica" si no existe. + - Solicita la contraseña dos veces al crear el usuario. + - NO cambia la contraseña si el usuario ya existe. + - Añade el usuario al grupo Administradores. + - Activa Escritorio Remoto. + - Configura el Firewall para RDP. + - Añade el usuario al grupo Usuarios de escritorio remoto. + - Oculta el usuario de la pantalla de inicio de sesión. + - Verifica al final que cada configuración está realmente aplicada. + - Devuelve código de salida 0 si todo está correcto. + - Devuelve código de salida 1 si hay algún error. + +.NOTES + Diseñado para Windows 10 / PowerShell 5.1. IMPORTANTE: - - La ocultación del usuario NO es una medida de seguridad. - - La cuenta sigue existiendo y puede utilizarse mediante RDP. - - Si "tecnica" ya existe, NO se modifica su contraseña. + Ocultar una cuenta de la pantalla de login NO es una medida + de seguridad. La cuenta sigue existiendo. + + Este script NO cambia la configuración de Network Level + Authentication ni abre RDP fuera del Firewall de Windows. #> -# ------------------------------------------------------------ +# ============================================================ # CONFIGURACIÓN -# ------------------------------------------------------------ +# ============================================================ $Username = "tecnica" -# ------------------------------------------------------------ -# COMPROBAR SI SOMOS ADMINISTRADOR -# ------------------------------------------------------------ +# ============================================================ +# CONFIGURACIÓN DE ERRORES +# ============================================================ + +$ErrorActionPreference = "Stop" + +# ============================================================ +# FUNCIONES AUXILIARES +# ============================================================ + +function Write-Step { + param ( + [string]$Message + ) + + Write-Host "" + Write-Host "--------------------------------------------------" ` + -ForegroundColor DarkGray + + Write-Host $Message ` + -ForegroundColor Cyan + + Write-Host "--------------------------------------------------" ` + -ForegroundColor DarkGray +} + +function Write-Ok { + param ( + [string]$Message + ) + + Write-Host "[OK] $Message" ` + -ForegroundColor Green +} + +function Write-WarningMessage { + param ( + [string]$Message + ) + + Write-Host "[AVISO] $Message" ` + -ForegroundColor Yellow +} + +function Write-ErrorMessage { + param ( + [string]$Message + ) + + Write-Host "[ERROR] $Message" ` + -ForegroundColor Red +} + +# ============================================================ +# COMPROBAR ADMINISTRADOR +# ============================================================ function Test-IsAdministrator { @@ -46,36 +109,67 @@ function Test-IsAdministrator { ) } -# ------------------------------------------------------------ -# AUTOELEVAR EL SCRIPT -# ------------------------------------------------------------ +# ============================================================ +# AUTOELEVAR +# ============================================================ -function Restart-AsAdministrator { +function Ensure-Administrator { if (Test-IsAdministrator) { return } Write-Host "" - Write-Host "El script necesita permisos de Administrador." -ForegroundColor Yellow + Write-WarningMessage "Este script necesita permisos de Administrador." Write-Host "Solicitando elevación..." -ForegroundColor Yellow Write-Host "" - # Volvemos a ejecutar este mismo script como Administrador. - Start-Process ` - -FilePath "powershell.exe" ` - -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" ` - -Verb RunAs + # Si el script está siendo ejecutado desde un archivo .ps1, + # volvemos a abrir el mismo archivo como Administrador. + if (-not $PSCommandPath) { - # Cerramos esta instancia sin privilegios. - exit + Write-ErrorMessage ` + "No se puede determinar la ruta del script." + + exit 1 + } + + $arguments = @( + "-NoProfile" + "-ExecutionPolicy" + "Bypass" + "-File" + "`"$PSCommandPath`"" + ) + + try { + + $process = Start-Process ` + -FilePath "powershell.exe" ` + -ArgumentList $arguments ` + -Verb RunAs ` + -Wait ` + -PassThru + + # Propagamos el código de salida de la instancia elevada. + exit $process.ExitCode + } + catch { + + Write-ErrorMessage ` + "No se pudo obtener permisos de Administrador." + + Write-ErrorMessage $_.Exception.Message + + exit 1 + } } -# ------------------------------------------------------------ -# COMPROBAR SI EXISTE UN USUARIO LOCAL -# ------------------------------------------------------------ +# ============================================================ +# COMPROBAR EXISTENCIA DEL USUARIO +# ============================================================ -function Test-LocalUserExists { +function Get-LocalUserSafe { param ( [Parameter(Mandatory)] @@ -84,45 +178,106 @@ function Test-LocalUserExists { try { - Get-LocalUser ` + return Get-LocalUser ` -Name $Name ` - -ErrorAction Stop | - Out-Null - - return $true + -ErrorAction Stop } catch { - return $false + return $null } } -# ------------------------------------------------------------ -# COMPROBAR SI UN USUARIO PERTENECE A UN GRUPO -# ------------------------------------------------------------ +# ============================================================ +# COMPROBAR SI UN USUARIO EXISTE +# ============================================================ -function Test-UserInLocalGroup { +function Test-LocalUserExists { param ( [Parameter(Mandatory)] - [string]$User, + [string]$Name + ) + + $user = Get-LocalUserSafe -Name $Name + + return ($null -ne $user) +} + +# ============================================================ +# OBTENER GRUPO LOCAL MEDIANTE SID +# +# Los grupos integrados de Windows tienen SIDs conocidos: +# +# Administradores: +# S-1-5-32-544 +# +# Usuarios de escritorio remoto: +# S-1-5-32-555 +# +# De esta forma no dependemos del idioma de Windows. +# ============================================================ + +function Get-LocalGroupBySid { + + param ( + [Parameter(Mandatory)] + [string]$Sid + ) + + try { + + $group = Get-LocalGroup | + Where-Object { + $_.SID.Value -eq $Sid + } | + Select-Object -First 1 + + if ($null -eq $group) { + + throw "No se encontró el grupo con SID $Sid." + } + + return $group + } + catch { + + throw $_ + } +} + +# ============================================================ +# COMPROBAR SI UN USUARIO ESTÁ EN UN GRUPO +# ============================================================ + +function Test-UserInGroup { + + param ( + [Parameter(Mandatory)] + [string]$Username, [Parameter(Mandatory)] - [string]$Group + [Microsoft.PowerShell.Commands.LocalGroup]$Group ) try { $members = Get-LocalGroupMember ` - -Group $Group ` + -Group $Group.Name ` -ErrorAction Stop foreach ($member in $members) { - # Ejemplo: - # DESKTOP-123456\tecnica + # El miembro normalmente aparece como: + # + # EQUIPO\tecnica + # + # Comparamos la parte final. + + $memberName = $member.Name.Split("\")[-1] + + if ($memberName -ieq $Username) { - if ($member.Name -match "\\$([regex]::Escape($User))$") { return $true } } @@ -135,45 +290,66 @@ function Test-UserInLocalGroup { } } -# ------------------------------------------------------------ -# BUSCAR UN GRUPO LOCAL POR SU NOMBRE EN ESPAÑOL O INGLÉS -# ------------------------------------------------------------ +# ============================================================ +# AÑADIR USUARIO A GRUPO DE FORMA IDEMPOTENTE +# ============================================================ -function Get-LocalGroupByKnownNames { +function Ensure-UserInGroup { param ( [Parameter(Mandatory)] - [string[]]$Names + [string]$Username, + + [Parameter(Mandatory)] + [Microsoft.PowerShell.Commands.LocalGroup]$Group ) - foreach ($name in $Names) { + if (Test-UserInGroup ` + -Username $Username ` + -Group $Group) { - try { + Write-Ok ` + "'$Username' ya pertenece a '$($Group.Name)'." - $group = Get-LocalGroup ` - -Name $name ` - -ErrorAction Stop - - return $group - } - catch { - # Probamos el siguiente nombre. - } + return } - throw "No se encontró ninguno de estos grupos: $($Names -join ', ')" + Write-Host ` + "Añadiendo '$Username' a '$($Group.Name)'..." ` + -ForegroundColor Cyan + + Add-LocalGroupMember ` + -Group $Group.Name ` + -Member $Username ` + -ErrorAction Stop + + # VERIFICACIÓN INMEDIATA + + if (-not ( + Test-UserInGroup ` + -Username $Username ` + -Group $Group + )) { + + throw ` + "El usuario no aparece en el grupo después de añadirlo." + } + + Write-Ok ` + "'$Username' pertenece ahora a '$($Group.Name)'." } -# ------------------------------------------------------------ -# PEDIR CONTRASEÑA DOS VECES -# ------------------------------------------------------------ +# ============================================================ +# PEDIR CONTRASEÑA Y CONFIRMARLA +# ============================================================ -function Read-AndConfirmPassword { +function Read-ConfirmedPassword { while ($true) { Write-Host "" - Write-Host "Introduce la contraseña para '$Username'." ` + Write-Host ` + "Introduce la contraseña para '$Username'." ` -ForegroundColor Cyan $password1 = Read-Host ` @@ -184,39 +360,43 @@ function Read-AndConfirmPassword { "Repite la contraseña" ` -AsSecureString - # Convertimos temporalmente a texto para poder comparar. - $ptr1 = [Runtime.InteropServices.Marshal]::SecureStringToBSTR( - $password1 - ) - - $ptr2 = [Runtime.InteropServices.Marshal]::SecureStringToBSTR( - $password2 - ) + $ptr1 = [IntPtr]::Zero + $ptr2 = [IntPtr]::Zero try { - $plain1 = [Runtime.InteropServices.Marshal]::PtrToStringBSTR( - $ptr1 - ) + $ptr1 = + [Runtime.InteropServices.Marshal]::SecureStringToBSTR( + $password1 + ) - $plain2 = [Runtime.InteropServices.Marshal]::PtrToStringBSTR( - $ptr2 - ) + $ptr2 = + [Runtime.InteropServices.Marshal]::SecureStringToBSTR( + $password2 + ) + + $plain1 = + [Runtime.InteropServices.Marshal]::PtrToStringBSTR( + $ptr1 + ) + + $plain2 = + [Runtime.InteropServices.Marshal]::PtrToStringBSTR( + $ptr2 + ) if ([string]::IsNullOrWhiteSpace($plain1)) { - Write-Host "" - Write-Host "La contraseña no puede estar vacía." ` - -ForegroundColor Red + Write-ErrorMessage ` + "La contraseña no puede estar vacía." continue } if ($plain1 -cne $plain2) { - Write-Host "" - Write-Host "Las contraseñas no coinciden." ` - -ForegroundColor Red + Write-ErrorMessage ` + "Las contraseñas no coinciden." continue } @@ -225,13 +405,18 @@ function Read-AndConfirmPassword { } finally { - # Liberamos los BSTR de memoria. if ($ptr1 -ne [IntPtr]::Zero) { - [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr1) + + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + $ptr1 + ) } if ($ptr2 -ne [IntPtr]::Zero) { - [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr2) + + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + $ptr2 + ) } $plain1 = $null @@ -240,105 +425,97 @@ function Read-AndConfirmPassword { } } -# ------------------------------------------------------------ -# CREAR EL USUARIO SI NO EXISTE -# ------------------------------------------------------------ +# ============================================================ +# CREAR USUARIO +# ============================================================ -function Ensure-LocalUser { +function Ensure-TechnicalUser { param ( [Parameter(Mandatory)] [string]$Name ) - if (Test-LocalUserExists -Name $Name) { + $existingUser = Get-LocalUserSafe -Name $Name - Write-Host "[OK] El usuario '$Name' ya existe." ` - -ForegroundColor Green + # -------------------------------------------------------- + # EL USUARIO YA EXISTE + # -------------------------------------------------------- - return Get-LocalUser -Name $Name + if ($null -ne $existingUser) { + + Write-Ok ` + "El usuario '$Name' ya existe." + + return $existingUser } + # -------------------------------------------------------- + # CREAR USUARIO + # -------------------------------------------------------- + Write-Host "" - Write-Host "El usuario '$Name' no existe." ` + Write-Host ` + "El usuario '$Name' no existe." ` -ForegroundColor Yellow - $password = Read-AndConfirmPassword + $password = Read-ConfirmedPassword Write-Host "" - Write-Host "Creando usuario '$Name'..." ` + Write-Host ` + "Creando usuario '$Name'..." ` -ForegroundColor Cyan - New-LocalUser ` - -Name $Name ` - -Password $password ` - -Description "Cuenta técnica de administración" ` - -AccountNeverExpires ` - -PasswordNeverExpires:$true + try { - Write-Host "[OK] Usuario '$Name' creado." ` - -ForegroundColor Green + $newUser = New-LocalUser ` + -Name $Name ` + -Password $password ` + -Description "Cuenta técnica de administración" ` + -AccountNeverExpires ` + -PasswordNeverExpires:$true ` + -ErrorAction Stop - return Get-LocalUser -Name $Name -} + # VERIFICACIÓN INMEDIATA -# ------------------------------------------------------------ -# AÑADIR USUARIO A UN GRUPO -# ------------------------------------------------------------ + $verifiedUser = Get-LocalUserSafe -Name $Name -function Ensure-UserInGroup { + if ($null -eq $verifiedUser) { - param ( - [Parameter(Mandatory)] - [string]$User, + throw ` + "New-LocalUser terminó correctamente pero el usuario no aparece." + } - [Parameter(Mandatory)] - [string[]]$PossibleGroupNames - ) + Write-Ok ` + "Usuario '$Name' creado correctamente." - # Buscar el nombre real del grupo en este Windows. - $group = Get-LocalGroupByKnownNames ` - -Names $PossibleGroupNames - - $groupName = $group.Name - - if (Test-UserInLocalGroup ` - -User $User ` - -Group $groupName) { - - Write-Host "[OK] '$User' ya pertenece a '$groupName'." ` - -ForegroundColor Green - - return + return $verifiedUser } + catch { - Write-Host "" - Write-Host "Añadiendo '$User' a '$groupName'..." ` - -ForegroundColor Cyan - - Add-LocalGroupMember ` - -Group $groupName ` - -Member $User - - Write-Host "[OK] Usuario añadido a '$groupName'." ` - -ForegroundColor Green + throw ` + "No se pudo crear el usuario '$Name': $($_.Exception.Message)" + } } -# ------------------------------------------------------------ +# ============================================================ # ACTIVAR ESCRITORIO REMOTO -# ------------------------------------------------------------ +# ============================================================ function Enable-RemoteDesktop { Write-Host "" - Write-Host "Configurando Escritorio remoto..." ` + Write-Host ` + "Activando Escritorio remoto..." ` -ForegroundColor Cyan # -------------------------------------------------------- - # 1. Permitir conexiones RDP + # REGISTRO DE WINDOWS # - # fDenyTSConnections = 0 - # significa que NO se deniegan las conexiones RDP. + # fDenyTSConnections: + # + # 1 = RDP desactivado + # 0 = RDP activado # -------------------------------------------------------- $rdpRegistryPath = @@ -348,27 +525,49 @@ function Enable-RemoteDesktop { -Path $rdpRegistryPath ` -Name "fDenyTSConnections" ` -Type DWord ` - -Value 0 + -Value 0 ` + -ErrorAction Stop - Write-Host "[OK] Conexiones RDP habilitadas." ` - -ForegroundColor Green + # Verificación. + $rdpValue = ( + Get-ItemProperty ` + -Path $rdpRegistryPath ` + -Name "fDenyTSConnections" ` + -ErrorAction Stop + ).fDenyTSConnections + + if ($rdpValue -ne 0) { + + throw ` + "No se pudo activar RDP en el registro." + } + + Write-Ok ` + "Windows tiene Escritorio remoto activado." # -------------------------------------------------------- - # 2. Configurar el servicio de Escritorio remoto + # SERVICIO TermService # -------------------------------------------------------- $service = Get-Service ` -Name "TermService" ` -ErrorAction Stop - # Dejamos el servicio con inicio manual. - # Windows puede iniciarlo cuando sea necesario. + # No necesitamos forzar "Automático". + # Manual es suficiente y Windows lo inicia cuando corresponde. + Set-Service ` -Name "TermService" ` - -StartupType Manual + -StartupType Manual ` + -ErrorAction Stop + + # Arrancamos el servicio si está parado. + + $service = Get-Service ` + -Name "TermService" ` + -ErrorAction Stop - # Si no está funcionando, lo arrancamos. if ($service.Status -ne "Running") { Start-Service ` @@ -376,181 +575,541 @@ function Enable-RemoteDesktop { -ErrorAction Stop } - Write-Host "[OK] Servicio de Escritorio remoto iniciado." ` - -ForegroundColor Green + # Verificación. + $service = Get-Service ` + -Name "TermService" ` + -ErrorAction Stop + + if ($service.Status -ne "Running") { + + throw ` + "El servicio TermService no está ejecutándose." + } + + Write-Ok ` + "Servicio de Escritorio remoto funcionando." # -------------------------------------------------------- - # 3. Abrir el Firewall para RDP - # - # DisplayGroup puede aparecer en español o inglés, - # dependiendo de la instalación. + # FIREWALL # -------------------------------------------------------- $firewallRules = Get-NetFirewallRule ` - -ErrorAction SilentlyContinue | + -ErrorAction Stop | Where-Object { - $_.DisplayGroup -in @( - "Remote Desktop", - "Escritorio remoto" - ) + $_.DisplayGroup -eq "Remote Desktop" -or + $_.DisplayGroup -eq "Escritorio remoto" } - if ($firewallRules) { + if ($null -eq $firewallRules) { - $firewallRules | - Enable-NetFirewallRule - - Write-Host "[OK] Firewall configurado para RDP." ` - -ForegroundColor Green + throw ` + "No se encontraron las reglas de Firewall de Escritorio remoto." } - else { - Write-Host "[AVISO] No se encontraron las reglas de Firewall de RDP." ` - -ForegroundColor Yellow + $firewallRules | + Enable-NetFirewallRule ` + -ErrorAction Stop + + # Verificar que al menos una regla está habilitada. + + $enabledRules = $firewallRules | + Where-Object { + $_.Enabled -eq "True" + } + + if ($null -eq $enabledRules) { + + throw ` + "No se pudo habilitar ninguna regla de Firewall de RDP." } + + Write-Ok ` + "Firewall de Escritorio remoto configurado." } -# ------------------------------------------------------------ -# OCULTAR USUARIO DE LA PANTALLA DE LOGIN -# ------------------------------------------------------------ +# ============================================================ +# OCULTAR USUARIO DEL LOGIN +# ============================================================ -function Hide-UserFromLoginScreen { +function Hide-UserFromLogin { param ( [Parameter(Mandatory)] - [string]$User + [string]$Username ) Write-Host "" - Write-Host "Ocultando '$User' de la pantalla de login..." ` + Write-Host ` + "Ocultando '$Username' de la pantalla de login..." ` -ForegroundColor Cyan $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" # Crear la clave si no existe. + if (-not (Test-Path $registryPath)) { New-Item ` -Path $registryPath ` - -Force | + -Force ` + -ErrorAction Stop | Out-Null } - # DWORD 0 = no mostrar en la pantalla de login. + # 0 = no mostrar el usuario en la lista. + New-ItemProperty ` -Path $registryPath ` - -Name $User ` + -Name $Username ` -PropertyType DWord ` -Value 0 ` - -Force | + -Force ` + -ErrorAction Stop | Out-Null - Write-Host "[OK] '$User' ocultado de la pantalla de login." ` - -ForegroundColor Green + # VERIFICACIÓN + + $value = ( + Get-ItemProperty ` + -Path $registryPath ` + -Name $Username ` + -ErrorAction Stop + ).$Username + + if ($value -ne 0) { + + throw ` + "No se pudo ocultar '$Username' de la pantalla de login." + } + + Write-Ok ` + "'$Username' está oculto de la lista de usuarios del login." } # ============================================================ -# INICIO DEL SCRIPT +# VERIFICACIÓN FINAL COMPLETA # ============================================================ -Clear-Host +function Test-FinalConfiguration { -Write-Host "==================================================" ` - -ForegroundColor Cyan + Write-Step ` + "VERIFICACIÓN FINAL DEL SISTEMA" -Write-Host " CONFIGURACIÓN INICIAL DE WINDOWS 10" ` - -ForegroundColor Cyan + $allOk = $true -Write-Host "==================================================" ` - -ForegroundColor Cyan + # -------------------------------------------------------- + # USUARIO + # -------------------------------------------------------- -Write-Host "" + $user = Get-LocalUserSafe -Name $Username -# ------------------------------------------------------------ -# 1. ELEVAR A ADMINISTRADOR -# ------------------------------------------------------------ + if ($null -ne $user) { -Restart-AsAdministrator + Write-Ok "Usuario '$Username': EXISTE" + } + else { -Write-Host "[OK] Ejecutando con privilegios de Administrador." ` - -ForegroundColor Green + Write-ErrorMessage "Usuario '$Username': NO EXISTE" + $allOk = $false + } -Write-Host "" + # -------------------------------------------------------- + # GRUPO ADMINISTRADORES + # -------------------------------------------------------- -# ------------------------------------------------------------ -# 2. CREAR USUARIO "TECNICA" -# ------------------------------------------------------------ + try { -Ensure-LocalUser ` - -Name $Username | - Out-Null + $administratorsGroup = + Get-LocalGroupBySid "S-1-5-32-544" -# ------------------------------------------------------------ -# 3. HACERLO ADMINISTRADOR -# ------------------------------------------------------------ + if (Test-UserInGroup ` + -Username $Username ` + -Group $administratorsGroup) { -Ensure-UserInGroup ` - -User $Username ` - -PossibleGroupNames @( - "Administradores", - "Administrators" - ) + Write-Ok ` + "Administrador: SI" + } + else { -# ------------------------------------------------------------ -# 4. ACTIVAR ESCRITORIO REMOTO EN WINDOWS -# ------------------------------------------------------------ + Write-ErrorMessage ` + "Administrador: NO" -Enable-RemoteDesktop + $allOk = $false + } + } + catch { -# ------------------------------------------------------------ -# 5. PERMITIR AL USUARIO "TECNICA" USAR RDP -# ------------------------------------------------------------ + Write-ErrorMessage ` + "No se pudo comprobar el grupo Administradores." -Ensure-UserInGroup ` - -User $Username ` - -PossibleGroupNames @( - "Usuarios de escritorio remoto", - "Remote Desktop Users" - ) + $allOk = $false + } -# ------------------------------------------------------------ -# 6. OCULTAR "TECNICA" DEL LOGIN -# ------------------------------------------------------------ + # -------------------------------------------------------- + # RDP + # -------------------------------------------------------- -Hide-UserFromLoginScreen ` - -User $Username + try { + + $rdpRegistryPath = + "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" + + $rdpValue = ( + Get-ItemProperty ` + -Path $rdpRegistryPath ` + -Name "fDenyTSConnections" ` + -ErrorAction Stop + ).fDenyTSConnections + + if ($rdpValue -eq 0) { + + Write-Ok ` + "Escritorio remoto de Windows: ACTIVADO" + } + else { + + Write-ErrorMessage ` + "Escritorio remoto de Windows: DESACTIVADO" + + $allOk = $false + } + } + catch { + + Write-ErrorMessage ` + "No se pudo comprobar la configuración RDP." + + $allOk = $false + } + + # -------------------------------------------------------- + # SERVICIO RDP + # -------------------------------------------------------- + + try { + + $service = Get-Service ` + -Name "TermService" ` + -ErrorAction Stop + + if ($service.Status -eq "Running") { + + Write-Ok ` + "Servicio TermService: EJECUTÁNDOSE" + } + else { + + Write-ErrorMessage ` + "Servicio TermService: $($service.Status)" + + $allOk = $false + } + } + catch { + + Write-ErrorMessage ` + "No se pudo comprobar TermService." + + $allOk = $false + } + + # -------------------------------------------------------- + # USUARIO EN GRUPO RDP + # -------------------------------------------------------- + + try { + + $rdpGroup = + Get-LocalGroupBySid "S-1-5-32-555" + + if (Test-UserInGroup ` + -Username $Username ` + -Group $rdpGroup) { + + Write-Ok ` + "Usuario autorizado para RDP: SI" + } + else { + + Write-ErrorMessage ` + "Usuario autorizado para RDP: NO" + + $allOk = $false + } + } + catch { + + Write-ErrorMessage ` + "No se pudo comprobar el grupo de usuarios RDP." + + $allOk = $false + } + + # -------------------------------------------------------- + # USUARIO OCULTO + # -------------------------------------------------------- + + try { + + $loginPath = + "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" + + $hiddenValue = ( + Get-ItemProperty ` + -Path $loginPath ` + -Name $Username ` + -ErrorAction Stop + ).$Username + + if ($hiddenValue -eq 0) { + + Write-Ok ` + "Usuario oculto del login: SI" + } + else { + + Write-ErrorMessage ` + "Usuario oculto del login: NO" + + $allOk = $false + } + } + catch { + + Write-ErrorMessage ` + "No se pudo comprobar la ocultación del usuario." + + $allOk = $false + } + + # -------------------------------------------------------- + # RESULTADO + # -------------------------------------------------------- + + Write-Host "" + + if ($allOk) { + + Write-Host ` + "==================================================" ` + -ForegroundColor Green + + Write-Host ` + " TODO CORRECTO" ` + -ForegroundColor Green + + Write-Host ` + "==================================================" ` + -ForegroundColor Green + + return $true + } + else { + + Write-Host ` + "==================================================" ` + -ForegroundColor Red + + Write-Host ` + " HAY ERRORES" ` + -ForegroundColor Red + + Write-Host ` + "==================================================" ` + -ForegroundColor Red + + return $false + } +} # ============================================================ -# FINAL +# PROGRAMA PRINCIPAL # ============================================================ -Write-Host "" -Write-Host "==================================================" ` - -ForegroundColor Green +try { -Write-Host " CONFIGURACIÓN COMPLETADA" ` - -ForegroundColor Green + Clear-Host -Write-Host "==================================================" ` - -ForegroundColor Green + Write-Host "" + Write-Host ` + "==================================================" ` + -ForegroundColor Cyan -Write-Host "" + Write-Host ` + " WINDOWS 10 - CONFIGURACIÓN INICIAL" ` + -ForegroundColor Cyan -Write-Host "Usuario: $Username" -Write-Host "Administrador: SI" -Write-Host "Escritorio remoto: ACTIVADO" -Write-Host "Usuario autorizado: SI" -Write-Host "Firewall RDP: CONFIGURADO" -Write-Host "Visible en login: NO" + Write-Host ` + "==================================================" ` + -ForegroundColor Cyan -Write-Host "" -Write-Host "El script es idempotente y puede volver a ejecutarse." ` - -ForegroundColor Green + Write-Host "" + Write-Host "Usuario técnico: $Username" + Write-Host "" -Write-Host "" -Write-Host "Pulsa ENTER para salir..." -Read-Host + # -------------------------------------------------------- + # 0. ADMINISTRADOR + # -------------------------------------------------------- + + Ensure-Administrator + + Write-Ok ` + "El script se está ejecutando como Administrador." + + # -------------------------------------------------------- + # 1. OBTENER GRUPOS + # -------------------------------------------------------- + + Write-Step ` + "COMPROBANDO GRUPOS LOCALES" + + $administratorsGroup = + Get-LocalGroupBySid "S-1-5-32-544" + + $rdpGroup = + Get-LocalGroupBySid "S-1-5-32-555" + + Write-Ok ` + "Grupo Administradores: $($administratorsGroup.Name)" + + Write-Ok ` + "Grupo Escritorio remoto: $($rdpGroup.Name)" + + # -------------------------------------------------------- + # 2. CREAR USUARIO + # -------------------------------------------------------- + + Write-Step ` + "CREANDO / COMPROBANDO USUARIO" + + Ensure-TechnicalUser ` + -Name $Username | + Out-Null + + # -------------------------------------------------------- + # 3. ADMINISTRADORES + # -------------------------------------------------------- + + Write-Step ` + "CONFIGURANDO PRIVILEGIOS DE ADMINISTRADOR" + + Ensure-UserInGroup ` + -Username $Username ` + -Group $administratorsGroup + + # -------------------------------------------------------- + # 4. ESCRITORIO REMOTO + # -------------------------------------------------------- + + Write-Step ` + "ACTIVANDO ESCRITORIO REMOTO" + + Enable-RemoteDesktop + + # -------------------------------------------------------- + # 5. AUTORIZAR USUARIO PARA RDP + # -------------------------------------------------------- + + Write-Step ` + "AUTORIZANDO USUARIO PARA ESCRITORIO REMOTO" + + Ensure-UserInGroup ` + -Username $Username ` + -Group $rdpGroup + + # -------------------------------------------------------- + # 6. OCULTAR USUARIO + # -------------------------------------------------------- + + Write-Step ` + "OCULTANDO USUARIO DE LA PANTALLA DE LOGIN" + + Hide-UserFromLogin ` + -Username $Username + + # -------------------------------------------------------- + # 7. VERIFICACIÓN FINAL + # -------------------------------------------------------- + + $result = Test-FinalConfiguration + + # -------------------------------------------------------- + # SALIDA + # -------------------------------------------------------- + + Write-Host "" + + if ($result) { + + Write-Host ` + "La configuración se ha completado correctamente." ` + -ForegroundColor Green + + Write-Host "" + Write-Host ` + "Puedes volver a ejecutar este script sin problema." ` + -ForegroundColor Green + + Write-Host "" + + exit 0 + } + else { + + Write-Host "" + Write-Host ` + "La configuración NO se ha completado correctamente." ` + -ForegroundColor Red + + Write-Host "" + Write-Host ` + "Revisa los errores mostrados arriba." ` + -ForegroundColor Yellow + + Write-Host "" + + exit 1 + } +} +catch { + + # ======================================================== + # ERROR NO CONTROLADO + # ======================================================== + + Write-Host "" + Write-Host ` + "==================================================" ` + -ForegroundColor Red + + Write-Host ` + " ERROR FATAL" ` + -ForegroundColor Red + + Write-Host ` + "==================================================" ` + -ForegroundColor Red + + Write-Host "" + + Write-ErrorMessage ` + $_.Exception.Message + + Write-Host "" + + Write-Host ` + "El script se ha detenido para evitar continuar" ` + -ForegroundColor Yellow + + Write-Host ` + "con una configuración incompleta." ` + -ForegroundColor Yellow + + Write-Host "" + + exit 1 +} ```