Todos sabemos que la creación de grupos en el AD es lo más conveniente a la hora de organizar los permisos en un árbol de carpetas y ficheros. Una vez otorgamos los permisos a cada grupo luego solo tenemos que introducir y eliminar usuarios de cada grupo a medida que necesiten permisos o causen baja o alta en la empresa.
Sin embargo, muchas veces heredas un sistema que ha sido mal organizado desde el principio o simplemente no es práctico porque no hay una organización en la empresa que se puede replicar con grupos del AD. Y ahí es donde empiezan los quebraderos de cabeza y el trabajo inmenso de tener que dar permisos a cada carpeta y fichero de forma individualizada.
Por ello, hoy os traemos una procedimiento utilizando scripts en Powershell que buscarán todos los permisos que un «Usuario A» tiene en una ruta concreta de carpetas y ficheros, y los replicará en un «Usuario B». Esto es un ahorro de trabajo brutal si una persona causa baja en una empresa y la sustituye un nuevo empleado. Solo tienes que configurar el script con los dos usuarios y la ruta raíz donde guardas toda la documentación organizada de la empresa para aplicar los mismos permisos que tenía el usuario que causó baja en el usuario que lo sustituye. En el siguiente vídeo tienes todos los pasos explicados uno por uno lo que te resultará extremadamente sencillo de ejecutar el proceso:
Vamos con el proceso:
Comprobar que el servidor tiene habilitada la ejecución de scripts
Lo primero que debemos hacer tras acceder al servidor donde se encuentra nuestra estructura de carpetas y ficheros es asegurarnos que la ejecución de scripts está habilitada. Para ello ejecutamos una consola de Powershell como administrador:
En la consola escribimos el siguiente comando:
Get-ExecutionPolicy
Si la respuesta, como vemos en la imagen de abajo es «RemoteSigned» significa que efectivamente está habilitada la ejecución de scripts en el servidor:
En caso negativo deberíamos ejecutar el siguiente comando:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
Establecer los permisos adicionales para poder otorgar permisos desde la consola de Powershell
Ejecutar Powershell o Powershell ISE como administrador no es suficiente para que nuestro script sea capaz de colocar los permisos del usuario B tal y como están habilitados para el usuario A. Para ello tenemos que crear un script previo que establece el privilegio requerido que es concretamente «SeSecurityPrivilege» que permite a un usuario administrar los permisos de auditoría y seguridad de objetos.
Para crear este primer script vamos a abrir la consola gráfica de Powershell ISE como administrador:
Y seleccionamos en el menú «Archivo – Nuevo». Y pegamos el siguiente script:
# Función para habilitar un privilegio en el token del proceso actual
function Enable-SeSecurityPrivilege {
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object System.Security.Principal.WindowsPrincipal($identity)
# Verificar si el usuario es un administrador
if ($principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
$adjustTokenPrivileges = @"
using System;
using System.Runtime.InteropServices;
public class TokenAdjuster {
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out long pluid);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, UInt32 BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TOKEN_PRIVILEGES {
public UInt32 PrivilegeCount;
public long Luid;
public UInt32 Attributes;
}
public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const UInt32 TOKEN_QUERY = 0x0008;
public static bool EnablePrivilege(string privilege) {
IntPtr hToken;
TOKEN_PRIVILEGES tkp;
if (!OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken)) return false;
if (!LookupPrivilegeValue(null, privilege, out tkp.Luid)) return false;
tkp.PrivilegeCount = 1;
tkp.Attributes = SE_PRIVILEGE_ENABLED;
return AdjustTokenPrivileges(hToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
}
}
"@
Add-Type -TypeDefinition $adjustTokenPrivileges -PassThru
[TokenAdjuster]::EnablePrivilege("SeSecurityPrivilege")
Write-Output "Privilegio 'SeSecurityPrivilege' habilitado."
} else {
Write-Output "Este script debe ejecutarse como administrador."
}
}
# Habilitar el privilegio SeSecurityPrivilege
Enable-SeSecurityPrivilege
Ahora guarda el script con el nombre «Enable-SeSecurityPrivilege.ps1» o el que tú quieras darle para identificar lo que hace el script. Puedes guardarlo en la ruta que sea de tu preferencia. Y ejecútalo.
Con esto ya has informado al sistema que tu usuario obtiene privilegios para colocar permisos desde powershell.
Ejecutar el script que replica los permisos de un usuario en otro
Vamos a crear un nuevo fichero en Powershell ISE con «Archivo – Nuevo». Y copiamos el siguiente código:
# Variables
$sourceUser = "dominio\usuario-A"
$targetUser = "dominio\usuario-B"
$folderPath = "ruta-carpetas"
# Función para replicar permisos
function Copy-Permissions {
param (
[string]$path
)
# Obtener los permisos actuales del archivo o carpeta
$acl = Get-Acl -Path $path
# Filtrar las entradas de control de acceso (ACEs) del usuario fuente
$sourceUserAclEntries = $acl.Access | Where-Object { $_.IdentityReference -eq $sourceUser }
if ($sourceUserAclEntries.Count -eq 0) {
Write-Output "No se encontraron entradas de permisos para $sourceUser en ${path}."
} else {
Write-Output "Se encontraron $($sourceUserAclEntries.Count) entradas de permisos para $sourceUser en ${path}."
# Iterar sobre cada ACE del usuario fuente y crear una nueva ACE para el usuario objetivo
foreach ($sourceUserAce in $sourceUserAclEntries) {
$targetUserAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
$targetUser,
$sourceUserAce.FileSystemRights,
$sourceUserAce.InheritanceFlags,
$sourceUserAce.PropagationFlags,
$sourceUserAce.AccessControlType
)
# Agregar la nueva ACE al ACL
$acl.AddAccessRule($targetUserAce)
Write-Output "Permiso agregado para ${targetUser} en ${path}: $targetUserAce"
}
# Aplicar los nuevos permisos al archivo o carpeta
try {
Set-Acl -Path $path -AclObject $acl
Write-Output "Permisos de $sourceUser copiados exitosamente a $targetUser en ${path}."
} catch {
Write-Output "Error al aplicar los permisos en ${path}: $_"
}
}
}
# Recorrer todas las carpetas y archivos en la ruta especificada
Get-ChildItem -Path $folderPath -Recurse | ForEach-Object {
Copy-Permissions -path $_.FullName
}
# Aplicar los permisos a la carpeta raíz también
Copy-Permissions -path $folderPath
Lógicamente tienes que cambiar los usuarios y la ruta para personalizarlo con los datos de tu empresa y de tus usuarios. Vamos a ver cómo sería un ejemplo para una empresa cuyo dominio es «gruponecayu.local» y los usuarios y la ruta raíz de todo el sistema de carpetas y ficheros de la empresa son:
- Usuario que causa baja: «agustin.puertas»
- Usuario que causa alta: «esteban.trabajos»
- Ruta de carpetas: «C:\Datos\GrupoNecayu»
- Dominio: «gruponecayu.local»
Solo hay que cambiar el primer apartado el de «# Variables»:
# Variables
$sourceUser = "dominio\usuario-A"
$targetUser = "dominio\usuario-B"
$folderPath = "ruta-carpetas"
Y así se vería con los cambios ya hechos:
# Variables
$sourceUser = "gruponecayu\agustin.puertas"
$targetUser = "gruponecayu\esteban.trabajos"
$folderPath = "C:\Datos\GrupoNecayu"
Ahora guarda este script con el nombre: «copiar-permisos.ps1». Y en cuanto lo ejecutes, comenzará a buscar en todas las carpetas, subcarpetas y ficheros todos los permisos de «agustin.puertas» y a medida que vaya encontrándolos otorgará el mismo permiso a «esteban.trabajos».
0 comentarios