Guía técnica completa: Usuarios, Grupos, GPO, Sistemas de Ficheros y Scripts de Administración
| Término | Descripción |
|---|---|
| DN (Distinguished Name) | Ruta completa del objeto: CN=Juan,OU=Ventas,DC=empresa,DC=local |
| UPN (User Principal Name) | Nombre de inicio de sesión: juan@empresa.local |
| SAMAccountName | Login heredado (NetBIOS): EMPRESA\juan |
| SID | Identificador único de seguridad, permanente e irrepetible |
| GUID | Identificador global único del objeto en el directorio |
| OU (Organizational Unit) | Contenedor lógico para organizar objetos y aplicar GPOs |
Creación → Configuración → Habilitación → Uso → Bloqueo/Deshabilitación → Eliminación
- displayName → Nombre completo mostrado
- sAMAccountName → Nombre de cuenta (único en el dominio)
- userPrincipalName → UPN (único en el bosque)
- mail → Correo electrónico
- telephoneNumber → Teléfono
- department → Departamento
- title → Cargo
- manager → Jefe directo (referencia a otro objeto)
- memberOf → Grupos a los que pertenece
- accountExpires → Fecha de expiración de la cuenta
- pwdLastSet → Última vez que se cambió la contraseña
- logonHours → Horas permitidas de inicio de sesión
- userWorkstations → Equipos desde los que puede iniciar sesión
- homeDirectory → Ruta del directorio personal
- homeDrive → Letra de unidad del directorio personal (ej: H:)
- scriptPath → Script de inicio de sesión
- profilePath → Perfil de usuario en red
dsa.msc (Active Directory Users and Computers)User must change password at next logonUser cannot change passwordPassword never expiresAccount is disabled| Opción | Uso Recomendado |
|---|---|
| Cambiar contraseña en el próximo inicio | Cuentas nuevas o restablecidas |
| Contraseña nunca caduca | Cuentas de servicio (con precaución) |
| No puede cambiar contraseña | Cuentas compartidas o de servicio |
| Cuenta deshabilitada | Usuarios de baja o temporales |
| Cuenta bloqueada | Visible solo si hay bloqueo activo |
| Tipo | Descripción |
|---|---|
| Local | Almacenado en el equipo local |
| Móvil (Roaming) | Sincronizado con un servidor al iniciar/cerrar sesión |
| Obligatorio | Perfil móvil de solo lectura, no se guardan cambios |
| Temporal | Se crea si el perfil asignado no está disponible |
Ruta perfil móvil: \\servidor\perfiles$\%username%
| Alcance | Miembros pueden ser | Ámbito de uso |
|---|---|---|
| Local de Dominio | Usuarios, grupos globales y universales de cualquier dominio | Solo en el dominio donde se define |
| Global | Usuarios y grupos globales del mismo dominio | Cualquier dominio del bosque |
| Universal | Usuarios y grupos de cualquier dominio del bosque | Cualquier dominio del bosque |
| Tipo | Uso |
|---|---|
| Seguridad | Asignar permisos a recursos; también puede usarse como lista de distribución |
| Distribución | Solo para listas de correo (sin permisos de seguridad) |
La mejor práctica de Microsoft para gestionar permisos:
A → Accounts (Cuentas de usuario)
G → Global Groups (Grupos Globales)
DL → Domain Local Groups (Grupos Locales de Dominio)
P → Permissions (Permisos sobre el recurso)
Flujo:
Usuario → Grupo Global → Grupo Local de Dominio → Permiso en recurso
Ejemplo práctico:
Juan (cuenta)
└─ G_Ventas (Grupo Global – todos los comerciales)
└─ DL_CarpetaVentas_Escritura (Grupo Local de Dominio)
└─ Permiso: Escritura en \\servidor\Ventas
Ventaja: Al añadir un empleado a G_Ventas, automáticamente obtiene todos los permisos asociados a ese grupo global.
| Grupo | Descripción |
|---|---|
Domain Admins |
Administradores del dominio (máximo privilegio en el dominio) |
Enterprise Admins |
Administradores del bosque completo |
Schema Admins |
Pueden modificar el esquema de AD |
Domain Users |
Todos los usuarios del dominio (grupo predeterminado) |
Domain Computers |
Todos los equipos unidos al dominio |
Administrators |
Admins locales en todos los DCs |
Backup Operators |
Pueden hacer copias sin ser administradores |
Remote Desktop Users |
Acceso RDP a equipos |
Group Policy Creator Owners |
Pueden crear y gestionar GPOs |
Account Operators |
Pueden crear/gestionar cuentas (no admins) |
Server Operators |
Pueden gestionar servidores |
Grupos implícitos que no se gestionan manualmente:
| Grupo | Descripción |
|---|---|
Everyone |
Todos, incluidos usuarios no autenticados (con cuidado) |
Authenticated Users |
Todos los usuarios autenticados en el dominio |
CREATOR OWNER |
El propietario del objeto o archivo |
NETWORK |
Usuarios que acceden a través de la red |
INTERACTIVE |
Usuarios que inician sesión localmente |
SYSTEM |
El propio sistema operativo |
SERVICE |
Servicios del sistema |
| Término | Descripción |
|---|---|
| GPO | Group Policy Object – Colección de configuraciones |
| GPMC | Group Policy Management Console (gpmc.msc) |
| GPEdit | Editor de directivas locales (gpedit.msc) |
| SYSVOL | Carpeta compartida en DCs que contiene los archivos de GPO |
| ADMX | Plantillas administrativas (formato XML moderno) |
| ADM | Plantillas administrativas (formato antiguo) |
| Resultant Set of Policy (RSoP) | Conjunto resultante de directivas aplicadas |
| Loopback Processing | Aplica las GPO del equipo al usuario que inicia sesión |
GPO
├── Computer Configuration (Configuración del equipo)
│ ├── Policies (Directivas)
│ │ ├── Software Settings
│ │ │ └── Software Installation
│ │ ├── Windows Settings
│ │ │ ├── Scripts (Startup/Shutdown)
│ │ │ ├── Security Settings
│ │ │ │ ├── Account Policies
│ │ │ │ │ ├── Password Policy
│ │ │ │ │ └── Account Lockout Policy
│ │ │ │ ├── Local Policies
│ │ │ │ ├── Windows Firewall
│ │ │ │ ├── Public Key Policies
│ │ │ │ └── Software Restriction Policies
│ │ │ └── Administrative Templates
│ │ └── Preferences
│ │ ├── Windows Settings
│ │ └── Control Panel Settings
└── User Configuration (Configuración del usuario)
├── Policies
│ ├── Software Settings
│ ├── Windows Settings
│ │ ├── Scripts (Logon/Logoff)
│ │ ├── Security Settings
│ │ ├── Folder Redirection
│ │ └── Administrative Templates
│ └── Preferences
└── Preferences
Las GPOs se aplican en este orden (cada nivel sobreescribe al anterior):
L → Local GPO (equipo local)
S → Site GPO (sitio de AD)
D → Domain GPO (dominio)
O → Organizational Unit (OU padre → OU hijo, de más general a más específico)
Regla: La última en aplicarse tiene más prioridad. Dentro de cada nivel, el número de orden más bajo tiene más prioridad.
| Opción | Descripción |
|---|---|
| Enforced (Forzado) | La GPO no puede ser bloqueada por niveles inferiores. Marca la GPO en el enlace. |
| Block Inheritance | La OU bloquea todas las GPOs de niveles superiores (excepto las Enforced). Se aplica en la OU. |
| Disabled (Deshabilitado) | El enlace de GPO está deshabilitado (no se aplica). |
Por defecto, una GPO se aplica a Authenticated Users. Se puede filtrar por:
- Usuarios específicos
- Grupos de seguridad
- Equipos
Para excluir un grupo: denegar el permiso Apply Group Policy.
Aplica la GPO solo si se cumple una consulta WMI:
-- Ejemplo: Solo Windows 10
SELECT * FROM Win32_OperatingSystem WHERE Version LIKE "10.%" AND ProductType = "1"
-- Solo equipos con más de 4GB de RAM
SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory >= 4294967296
-- Solo portátiles
SELECT * FROM Win32_SystemEnclosure WHERE ChassisTypes = 9 OR ChassisTypes = 10
Permiten tener distintas políticas de contraseña para diferentes grupos/usuarios (desde Windows Server 2008):
Herramienta: ADSI Edit → CN=Password Settings Container,CN=System,DC=empresa,DC=local
| Atributo PSO | Descripción |
|---|---|
msDS-PasswordSettingsPrecedence |
Prioridad (número menor = mayor prioridad) |
msDS-PasswordReversibleEncryptionEnabled |
Cifrado reversible |
msDS-PasswordHistoryLength |
Historial de contraseñas |
msDS-PasswordComplexityEnabled |
Complejidad requerida |
msDS-MinimumPasswordLength |
Longitud mínima |
msDS-MinimumPasswordAge |
Edad mínima |
msDS-MaximumPasswordAge |
Edad máxima |
msDS-LockoutThreshold |
Intentos antes de bloqueo |
msDS-LockoutObservationWindow |
Ventana de observación |
msDS-LockoutDuration |
Duración del bloqueo |
Computer Config → Windows Settings → Security Settings → Account Policies
├── Password Policy
│ ├── Enforce password history: 24 passwords
│ ├── Maximum password age: 60 days
│ ├── Minimum password age: 1 day
│ ├── Minimum password length: 12 characters
│ └── Password must meet complexity requirements: Enabled
└── Account Lockout Policy
├── Account lockout duration: 30 minutes
├── Account lockout threshold: 5 invalid attempts
└── Reset account lockout counter after: 30 minutes
User Config → Windows Settings → Folder Redirection
├── Desktop → \\servidor\perfiles$\%username%\Desktop
├── Documents → \\servidor\perfiles$\%username%\Documents
└── AppData → \\servidor\perfiles$\%username%\AppData
User Config → Windows Settings → Scripts → Logon/Logoff
Computer Config → Windows Settings → Scripts → Startup/Shutdown
User Config → Preferences → Windows Settings → Drive Maps
→ New → Mapped Drive
- Action: Create / Update / Replace / Delete
- Location: \\servidor\compartido
- Drive Letter: H:
- Label: Datos personales
- Item-level targeting: Grupo de seguridad
Computer Config → Windows Settings → Security Settings → Application Control Policies → AppLocker
├── Executable Rules (.exe, .com)
├── Windows Installer Rules (.msi, .msp)
├── Script Rules (.ps1, .bat, .vbs)
└── Packaged App Rules (UWP)
:: Actualizar directivas inmediatamente
gpupdate /force
:: Ver directivas aplicadas (HTML)
gpresult /h C:\GPReport.html /f
:: Ver directivas de usuario actual
gpresult /r
:: Ver directivas de usuario específico
gpresult /user DOMINIO\usuario /r
:: Ver directivas de un equipo remoto
gpresult /s nombreequipo /r
:: Diagnóstico de RSoP (GUI)
rsop.msc
| Archivo | Contenido |
|---|---|
/etc/passwd |
Información de usuarios (nombre, UID, GID, home, shell) |
/etc/shadow |
Contraseñas cifradas y políticas de expiración |
/etc/group |
Información de grupos |
/etc/gshadow |
Contraseñas cifradas de grupos |
/etc/skel/ |
Plantilla para el directorio home de nuevos usuarios |
/etc/login.defs |
Configuración global de usuarios (UID/GID range, políticas) |
/etc/default/useradd |
Valores por defecto al crear usuarios |
/etc/passwdusuario:x:1001:1001:Nombre Completo,,,:/home/usuario:/bin/bash
1 2 3 4 5 6 7
1 - Nombre de usuario
2 - Contraseña (x = en /etc/shadow)
3 - UID (User ID)
4 - GID (Group ID principal)
5 - GECOS (información adicional: nombre, teléfono, etc.)
6 - Directorio home
7 - Shell por defecto
/etc/shadowusuario:$6$sal$hash:18500:0:99999:7:::
1 2 3 4 5 6 7 8 9
1 - Usuario
2 - Contraseña cifrada ($6$ = SHA-512, $5$ = SHA-256, $1$ = MD5)
3 - Días desde epoch del último cambio
4 - Días mínimos antes de poder cambiar contraseña
5 - Días máximos de validez de contraseña
6 - Días de aviso antes de expiración
7 - Días de gracia tras expiración
8 - Fecha de expiración de cuenta (días desde epoch, vacío = nunca)
9 - Reservado
# Sintaxis básica
useradd [opciones] nombre_usuario
# Opciones importantes
useradd -m # Crear directorio home
useradd -d /ruta/home # Especificar ruta del home
useradd -s /bin/bash # Shell por defecto
useradd -g grupo # Grupo principal
useradd -G g1,g2,g3 # Grupos secundarios
useradd -u 1500 # UID específico
useradd -c "Nombre Completo" # Comentario/GECOS
useradd -e 2025-12-31 # Fecha de expiración (YYYY-MM-DD)
useradd -r # Cuenta de sistema (UID < 1000, sin home)
useradd -M # NO crear directorio home
useradd -N # No crear grupo con el mismo nombre
useradd -k /ruta/skel # Plantilla skel alternativa
useradd -p 'hash' # Contraseña ya cifrada
# Ejemplo completo
useradd -m -d /home/jgarcia -s /bin/bash \
-g empleados -G sudo,docker \
-c "Juan García,Ventas,+34912345678" \
-e 2026-06-30 jgarcia
# Establecer contraseña (interactivo)
passwd nombre_usuario
# Generar contraseña aleatoria y asignarla
openssl rand -base64 12 | passwd --stdin nombre_usuario # RHEL/CentOS
echo "nuevapass" | chpasswd # Debian/Ubuntu
# Forzar cambio de contraseña en próximo login
passwd -e nombre_usuario
chage -d 0 nombre_usuario
# Bloquear/desbloquear cuenta
passwd -l nombre_usuario # Lock (añade ! al hash)
passwd -u nombre_usuario # Unlock
# Ver estado de contraseña
passwd -S nombre_usuario
chage -l nombre_usuario
# Sintaxis: usermod [opciones] usuario
usermod -l nuevo_nombre viejo_nombre # Cambiar nombre de usuario
usermod -d /nueva/ruta -m usuario # Mover directorio home
usermod -s /bin/zsh usuario # Cambiar shell
usermod -g nuevo_grupo usuario # Cambiar grupo principal
usermod -G g1,g2,g3 usuario # Reemplazar grupos secundarios
usermod -aG grupo usuario # AÑADIR a grupo secundario (sin borrar otros)
usermod -u 1600 usuario # Cambiar UID
usermod -L usuario # Bloquear cuenta
usermod -U usuario # Desbloquear cuenta
usermod -e 2026-12-31 usuario # Cambiar fecha expiración
usermod -e "" usuario # Quitar expiración
usermod -c "Nuevo comentario" usuario # Cambiar GECOS
userdel usuario # Eliminar usuario (mantiene home y archivos)
userdel -r usuario # Eliminar usuario + home + archivos de correo
userdel -f usuario # Forzar eliminación aunque el usuario tenga sesión activa
# Buena práctica: antes de eliminar, buscar archivos del usuario
find / -user nombre_usuario 2>/dev/null
find / -uid 1001 2>/dev/null # Por UID (más seguro si el nombre cambió)
# Ver políticas actuales
chage -l usuario
# Establecer políticas
chage -m 1 usuario # Mínimo 1 día entre cambios
chage -M 90 usuario # Contraseña expira en 90 días
chage -W 14 usuario # Avisar 14 días antes de expirar
chage -I 7 usuario # 7 días de gracia tras expirar antes de bloquear
chage -E 2026-12-31 usuario # Fecha de expiración de la cuenta
# Forzar cambio en próximo login
chage -d 0 usuario
# Modo interactivo
chage usuario
# Crear grupo
groupadd nombre_grupo
groupadd -g 2000 nombre_grupo # GID específico
groupadd -r nombre_grupo # Grupo del sistema
# Modificar grupo
groupmod -n nuevo_nombre viejo_nombre # Renombrar
groupmod -g 2001 nombre_grupo # Cambiar GID
# Eliminar grupo
groupdel nombre_grupo
# Añadir usuario a grupo
usermod -aG nombre_grupo usuario
gpasswd -a usuario nombre_grupo
# Eliminar usuario de grupo
gpasswd -d usuario nombre_grupo
# Ver miembros de un grupo
getent group nombre_grupo
grep "^nombre_grupo:" /etc/group
members nombre_grupo # si el paquete 'members' está instalado
# Cambiar grupo principal temporalmente (sesión)
newgrp nombre_grupo
# Información del usuario actual
whoami # Nombre de usuario
id # UID, GID y grupos
id usuario # Info de otro usuario
# Usuarios conectados
who # Usuarios con sesión activa
w # Más detallado (procesos, tiempo inactivo)
last # Historial de logins
lastlog # Último login de todos los usuarios
users # Lista simple de usuarios conectados
# Cambiar de usuario
su - usuario # Cambiar a usuario (con entorno)
su -c "comando" usuario # Ejecutar comando como otro usuario
sudo -u usuario comando # Ejecutar como usuario (con sudo)
sudo -i # Shell de root
# Información de cuenta
finger usuario # Si está instalado
getent passwd usuario
- rwx rwx rwx
│ │ │ └── Otros (Others)
│ │ └────── Grupo (Group)
│ └────────── Propietario (User/Owner)
└────────────── Tipo: - (fichero), d (directorio), l (enlace), b (bloque), c (carácter), p (pipe), s (socket)
| Símbolo | Octal | Fichero | Directorio |
|---|---|---|---|
r |
4 | Leer contenido | Listar contenido (ls) |
w |
2 | Escribir/modificar | Crear/eliminar archivos en él |
x |
1 | Ejecutar | Acceder/entrar (cd) |
- |
0 | Sin permiso | Sin permiso |
rwxr-xr-- = 7 5 4
───┬─── ─┬─ ─┬─
7 5 4
r=4, w=2, x=1
Ejemplos:
777 = rwxrwxrwx (todos los permisos a todos)
755 = rwxr-xr-x (común en directorios y ejecutables)
644 = rw-r--r-- (común en ficheros)
600 = rw------- (ficheros privados: SSH keys)
700 = rwx------ (directorios privados)
640 = rw-r----- (ficheros de grupo)
| Permiso | Octal | En ficheros | En directorios |
|---|---|---|---|
| SUID (Set User ID) | 4000 | Se ejecuta con los permisos del propietario | Sin efecto especial |
| SGID (Set Group ID) | 2000 | Se ejecuta con los permisos del grupo | Nuevos archivos heredan el grupo del directorio |
| Sticky Bit | 1000 | Obsoleto | Solo el propietario puede eliminar sus archivos |
# SUID en notación simbólica: s en posición de x del propietario
-rwsr-xr-x # SUID activo (x presente)
-rwSr-xr-x # SUID activo (x ausente) → Inútil
# SGID: s en posición de x del grupo
drwxrwsr-x # SGID en directorio
# Sticky Bit: t en posición de x de otros
drwxrwxrwt # Sticky bit activo (ej: /tmp)
# Ejemplos de archivos con SUID en el sistema
ls -la /usr/bin/passwd # -rwsr-xr-x → necesita escribir /etc/shadow
ls -la /usr/bin/sudo # -rwsr-xr-x
ls -la /tmp # drwxrwxrwt → sticky bit
# Notación octal
chmod 755 fichero
chmod 644 fichero
chmod -R 750 directorio # Recursivo
# Notación simbólica
# [ugoa][+-=][rwxXstugo]
chmod u+x fichero # Añadir ejecución al propietario
chmod g-w fichero # Quitar escritura al grupo
chmod o=r fichero # Establecer solo lectura para otros
chmod a+r fichero # Añadir lectura a todos (a = ugo)
chmod u=rwx,g=rx,o= fichero # Múltiples en una línea
# Permisos especiales
chmod u+s fichero # SUID
chmod g+s directorio # SGID
chmod +t directorio # Sticky bit
chmod 4755 fichero # SUID + 755
chmod 2775 directorio # SGID + 775
chmod 1777 directorio # Sticky + 777
# Solo cambiar directorios (no ficheros)
chmod -R u+X directorio # X mayúscula: ejecutar solo si es directorio o ya es ejecutable
chown usuario fichero # Cambiar propietario
chown usuario:grupo fichero # Cambiar propietario y grupo
chown :grupo fichero # Cambiar solo grupo
chown -R usuario:grupo directorio # Recursivo
chown --from=viejo_usuario nuevo_usuario fichero # Cambiar solo si es propietario X
chgrp grupo fichero
chgrp -R grupo directorio
Las ACLs (Access Control Lists) permiten permisos más granulares que el modelo UGO clásico.
# Ver ACLs
getfacl fichero
getfacl -R directorio
# Establecer ACL para usuario
setfacl -m u:usuario:rwx fichero
setfacl -m u:usuario:r-- fichero
# Establecer ACL para grupo
setfacl -m g:grupo:rx fichero
# ACL por defecto en directorio (se heredan los nuevos archivos)
setfacl -d -m u:usuario:rwx directorio
setfacl -d -m g:grupo:rx directorio
# Eliminar ACL de usuario/grupo
setfacl -x u:usuario fichero
setfacl -x g:grupo fichero
# Eliminar TODAS las ACLs
setfacl -b fichero
# Copiar ACLs de un fichero a otro
getfacl fichero_origen | setfacl --set-file=- fichero_destino
# Aplicar recursivamente
setfacl -R -m u:usuario:rwX directorio
# Ejemplo: Directorio compartido de proyecto
setfacl -m g:proyectoA:rwx /datos/proyectoA
setfacl -d -m g:proyectoA:rwx /datos/proyectoA # Heredar a nuevos archivos
setfacl -m u:auditor:r-x /datos/proyectoA # Solo lectura para auditor
Indicador en ls -la: Un + al final de los permisos indica que tiene ACLs:
-rw-rw-r--+ 1 usuario grupo 0 ene 1 10:00 fichero
# Hacer fichero inmutable (ni root puede modificarlo)
chattr +i fichero
# Quitar inmutabilidad
chattr -i fichero
# Solo permite añadir datos (logs)
chattr +a fichero
# Ver atributos
lsattr fichero
lsattr -R directorio
La umask define qué permisos se restan al crear nuevos ficheros/directorios.
# Ver umask actual
umask # octal: 0022
umask -S # simbólico: u=rwx,g=rx,o=rx
# Permisos máximos base:
# Ficheros: 666 (rw-rw-rw-)
# Directorios: 777 (rwxrwxrwx)
# Con umask 022:
# Ficheros: 666 - 022 = 644 (rw-r--r--)
# Directorios: 777 - 022 = 755 (rwxr-xr-x)
# Con umask 027:
# Ficheros: 666 - 027 = 640 (rw-r-----)
# Directorios: 777 - 027 = 750 (rwxr-x---)
# Establecer umask
umask 027
# Umask permanente para usuario
echo "umask 027" >> ~/.bashrc
# Umask permanente para el sistema
echo "umask 022" >> /etc/profile
/
├── bin/ → Binarios esenciales (ls, cp, mv, bash...)
├── boot/ → Archivos de arranque (kernel, GRUB)
├── dev/ → Dispositivos (discos, terminales...)
├── etc/ → Configuración del sistema
├── home/ → Directorios de usuarios
├── lib/ → Bibliotecas compartidas
├── media/ → Puntos de montaje para medios extraíbles
├── mnt/ → Montajes temporales
├── opt/ → Software opcional/de terceros
├── proc/ → Sistema de ficheros virtual (procesos, kernel)
├── root/ → Home del usuario root
├── run/ → Datos en tiempo de ejecución
├── sbin/ → Binarios del sistema (para administración)
├── srv/ → Datos de servicios (web, FTP...)
├── sys/ → Sistema de ficheros virtual (kernel, hardware)
├── tmp/ → Archivos temporales (sticky bit)
├── usr/ → Aplicaciones y datos de usuario
│ ├── bin/ → Binarios de usuario
│ ├── lib/ → Bibliotecas
│ ├── local/ → Software instalado localmente
│ └── share/ → Datos independientes de arquitectura
└── var/ → Datos variables (logs, spool, bases de datos)
├── log/ → Registros del sistema
├── spool/ → Colas de impresión y correo
└── www/ → Datos web (en muchas distros)
# Importar módulo AD (necesario en algunos casos)
Import-Module ActiveDirectory
# Verificar módulo disponible
Get-Module -ListAvailable -Name ActiveDirectory
# Conectar a un dominio específico (o DC específico)
Get-ADUser -Identity "jgarcia" -Server "dc01.empresa.local"
# Ver el dominio actual
Get-ADDomain
Get-ADForest
function New-ADUserCompleto {
param(
[Parameter(Mandatory)][string]$Nombre,
[Parameter(Mandatory)][string]$Apellido,
[Parameter(Mandatory)][string]$Departamento,
[Parameter(Mandatory)][string]$OU,
[string]$Dominio = "empresa.local",
[string]$Servidor = "\\Servidor01\Perfiles$"
)
# Generar nombre de usuario
$Username = ($Nombre.Substring(0,1) + $Apellido).ToLower() -replace '[áàâä]','a' -replace '[éèêë]','e' -replace '[íìîï]','i' -replace '[óòôö]','o' -replace '[úùûü]','u' -replace '[ñ]','n' -replace '\s',''
# Verificar si ya existe
if (Get-ADUser -Filter "SamAccountName -eq '$Username'" -ErrorAction SilentlyContinue) {
$Username = $Username + (Get-Random -Minimum 1 -Maximum 99)
Write-Warning "Usuario duplicado. Usando: $Username"
}
# Generar contraseña segura
$Password = ConvertTo-SecureString "Contraseña@$(Get-Random -Min 1000 -Max 9999)" -AsPlainText -Force
# Parámetros del usuario
$Params = @{
Name = "$Nombre $Apellido"
GivenName = $Nombre
Surname = $Apellido
SamAccountName = $Username
UserPrincipalName = "$Username@$Dominio"
DisplayName = "$Apellido, $Nombre"
Department = $Departamento
Path = $OU
AccountPassword = $Password
ChangePasswordAtLogon = $true
Enabled = $true
HomeDirectory = "$Servidor\$Username"
HomeDrive = "H:"
ProfilePath = "$Servidor\Profiles\$Username"
Description = "Creado por script el $(Get-Date -Format 'dd/MM/yyyy')"
}
try {
New-ADUser @Params
Write-Host "✓ Usuario '$Username' creado correctamente." -ForegroundColor Green
# Crear directorio home
$HomeDir = "$Servidor\$Username"
if (-not (Test-Path $HomeDir)) {
New-Item -ItemType Directory -Path $HomeDir | Out-Null
# Asignar permisos al usuario en su home
$Acl = Get-Acl $HomeDir
$Rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"$Username", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$Acl.SetAccessRule($Rule)
Set-Acl -Path $HomeDir -AclObject $Acl
Write-Host "✓ Directorio home creado: $HomeDir" -ForegroundColor Green
}
return $Username
}
catch {
Write-Error "Error al crear usuario: $_"
}
}
# Uso
New-ADUserCompleto -Nombre "Juan" -Apellido "García" -Departamento "Ventas" -OU "OU=Ventas,DC=empresa,DC=local"
# CSV esperado: Nombre,Apellido,Departamento,OU,Email,Telefono,Manager
function Import-ADUsersFromCSV {
param(
[Parameter(Mandatory)][string]$CsvPath,
[string]$Dominio = "empresa.local",
[string]$LogPath = "C:\Logs\CreacionUsuarios_$(Get-Date -Format 'yyyyMMdd_HHmm').log"
)
# Crear directorio de logs si no existe
$LogDir = Split-Path $LogPath
if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir | Out-Null }
$Usuarios = Import-Csv -Path $CsvPath -Encoding UTF8
$Resultados = @()
foreach ($U in $Usuarios) {
$Username = ($U.Nombre.Substring(0,1) + $U.Apellido).ToLower()
$Password = ConvertTo-SecureString "Temporal@2024" -AsPlainText -Force
try {
$Params = @{
Name = "$($U.Nombre) $($U.Apellido)"
GivenName = $U.Nombre
Surname = $U.Apellido
SamAccountName = $Username
UserPrincipalName = "$Username@$Dominio"
EmailAddress = $U.Email
OfficePhone = $U.Telefono
Department = $U.Departamento
Path = $U.OU
AccountPassword = $Password
ChangePasswordAtLogon = $true
Enabled = $true
}
# Añadir manager si se especifica
if ($U.Manager) {
$ManagerObj = Get-ADUser -Filter "SamAccountName -eq '$($U.Manager)'" -ErrorAction SilentlyContinue
if ($ManagerObj) { $Params.Manager = $ManagerObj.DistinguishedName }
}
New-ADUser @Params
$Estado = "OK"
Write-Host "✓ $Username" -ForegroundColor Green
}
catch {
$Estado = "ERROR: $_"
Write-Host "✗ $Username - $_" -ForegroundColor Red
}
$Resultados += [PSCustomObject]@{
Usuario = $Username
NombreCompleto = "$($U.Nombre) $($U.Apellido)"
Estado = $Estado
Fecha = (Get-Date -Format "dd/MM/yyyy HH:mm:ss")
}
}
# Exportar resultados
$Resultados | Export-Csv -Path $LogPath -NoTypeInformation -Encoding UTF8
Write-Host "`nInforme guardado en: $LogPath" -ForegroundColor Cyan
return $Resultados
}
# Uso
Import-ADUsersFromCSV -CsvPath "C:\Datos\nuevos_empleados.csv"
function Disable-InactiveADAccounts {
param(
[int]$DiasInactividad = 90,
[string]$OUExcluir = "OU=ServiceAccounts,DC=empresa,DC=local",
[string]$OUMover = "OU=Deshabilitadas,DC=empresa,DC=local",
[switch]$WhatIf
)
$FechaLimite = (Get-Date).AddDays(-$DiasInactividad)
# Buscar usuarios habilitados sin login en X días
$InactiveUsers = Get-ADUser -Filter {
Enabled -eq $true -and
LastLogonDate -lt $FechaLimite -and
LastLogonDate -ne $null
} -Properties LastLogonDate, Description, DistinguishedName |
Where-Object { $_.DistinguishedName -notlike "*$OUExcluir*" }
Write-Host "Usuarios inactivos encontrados: $($InactiveUsers.Count)" -ForegroundColor Yellow
foreach ($User in $InactiveUsers) {
$Descripcion = "Deshabilitado automáticamente el $(Get-Date -Format 'dd/MM/yyyy'). Último login: $($User.LastLogonDate)"
if (-not $WhatIf) {
# Deshabilitar cuenta
Disable-ADAccount -Identity $User.SamAccountName
# Actualizar descripción
Set-ADUser -Identity $User.SamAccountName -Description $Descripcion
# Mover a OU de deshabilitadas
Move-ADObject -Identity $User.DistinguishedName -TargetPath $OUMover
Write-Host "Deshabilitado: $($User.SamAccountName) | Último login: $($User.LastLogonDate)" -ForegroundColor Yellow
} else {
Write-Host "[WHATIF] Deshabilitaría: $($User.SamAccountName) | Último login: $($User.LastLogonDate)"
}
}
}
# Simulación primero
Disable-InactiveADAccounts -DiasInactividad 90 -WhatIf
# Ejecución real
# Disable-InactiveADAccounts -DiasInactividad 90
# Añadir usuarios a grupo desde CSV
function Add-ADGroupMembersFromCSV {
param(
[Parameter(Mandatory)][string]$CsvPath, # CSV con columna 'Usuario' y 'Grupo'
[string]$GrupoFijo = "" # Grupo único para todos si se especifica
)
$Datos = Import-Csv -Path $CsvPath -Encoding UTF8
foreach ($Fila in $Datos) {
$Grupo = if ($GrupoFijo) { $GrupoFijo } else { $Fila.Grupo }
try {
Add-ADGroupMember -Identity $Grupo -Members $Fila.Usuario
Write-Host "✓ $($Fila.Usuario) → $Grupo" -ForegroundColor Green
}
catch {
Write-Warning "✗ $($Fila.Usuario) → $Grupo : $_"
}
}
}
# Generar informe de miembros de grupos
function Export-ADGroupMembersReport {
param(
[string[]]$Grupos,
[string]$OutputPath = "C:\Informes\Grupos_$(Get-Date -Format 'yyyyMMdd').csv"
)
$Resultados = @()
foreach ($Grupo in $Grupos) {
try {
$Miembros = Get-ADGroupMember -Identity $Grupo -Recursive |
Where-Object { $_.objectClass -eq "user" } |
Get-ADUser -Properties DisplayName, Department, Enabled, LastLogonDate
foreach ($M in $Miembros) {
$Resultados += [PSCustomObject]@{
Grupo = $Grupo
SamAccount = $M.SamAccountName
NombreCompleto = $M.DisplayName
Departamento = $M.Department
Habilitado = $M.Enabled
UltimoLogin = $M.LastLogonDate
}
}
}
catch {
Write-Warning "No se pudo obtener miembros de '$Grupo': $_"
}
}
$Resultados | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "Informe exportado: $OutputPath ($($Resultados.Count) registros)" -ForegroundColor Cyan
}
# Exportar configuración de todas las GPOs
function Export-AllGPOReports {
param([string]$OutputDir = "C:\Informes\GPO_$(Get-Date -Format 'yyyyMMdd')")
Import-Module GroupPolicy
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
$GPOs = Get-GPO -All
foreach ($GPO in $GPOs) {
$SafeName = $GPO.DisplayName -replace '[\\/:*?"<>|]', '_'
Get-GPOReport -Guid $GPO.Id -ReportType HTML -Path "$OutputDir\$SafeName.html"
Write-Host "Exportada: $($GPO.DisplayName)" -ForegroundColor Green
}
# También exportar listado general
$GPOs | Select-Object DisplayName, Id, GpoStatus, CreationTime, ModificationTime |
Export-Csv -Path "$OutputDir\_ListadoGPOs.csv" -NoTypeInformation -Encoding UTF8
Write-Host "`nTotal GPOs exportadas: $($GPOs.Count)" -ForegroundColor Cyan
Write-Host "Directorio: $OutputDir" -ForegroundColor Cyan
}
# Hacer backup de todas las GPOs
function Backup-AllGPOs {
param([string]$BackupDir = "C:\Backup\GPO_$(Get-Date -Format 'yyyyMMdd_HHmm')")
Import-Module GroupPolicy
New-Item -ItemType Directory -Path $BackupDir -Force | Out-Null
$GPOs = Get-GPO -All
foreach ($GPO in $GPOs) {
Backup-GPO -Guid $GPO.Id -Path $BackupDir -Comment "Backup automático $(Get-Date -Format 'dd/MM/yyyy')"
Write-Host "Backup: $($GPO.DisplayName)" -ForegroundColor Green
}
Write-Host "`nBackup completado en: $BackupDir" -ForegroundColor Cyan
}
# Restaurar GPO desde backup
function Restore-GPOFromBackup {
param(
[Parameter(Mandatory)][string]$NombreGPO,
[Parameter(Mandatory)][string]$BackupDir
)
Import-Module GroupPolicy
Restore-GPO -Name $NombreGPO -Path $BackupDir
Write-Host "GPO '$NombreGPO' restaurada desde $BackupDir" -ForegroundColor Green
}
# Informe completo de usuarios AD
function Export-ADUsersFullReport {
param([string]$OutputPath = "C:\Informes\Usuarios_AD_$(Get-Date -Format 'yyyyMMdd').csv")
$Propiedades = @(
'SamAccountName', 'DisplayName', 'GivenName', 'Surname',
'UserPrincipalName', 'EmailAddress', 'Department', 'Title',
'Manager', 'Enabled', 'PasswordExpired', 'PasswordNeverExpires',
'PasswordLastSet', 'LastLogonDate', 'AccountExpirationDate',
'LockedOut', 'Created', 'Modified', 'DistinguishedName',
'MemberOf', 'HomeDirectory', 'ProfilePath', 'Description'
)
Get-ADUser -Filter * -Properties $Propiedades |
Select-Object @{N='Usuario';E={$_.SamAccountName}},
@{N='Nombre';E={$_.DisplayName}},
@{N='Email';E={$_.EmailAddress}},
@{N='Departamento';E={$_.Department}},
@{N='Cargo';E={$_.Title}},
@{N='Manager';E={ if($_.Manager){(Get-ADUser $_.Manager).SamAccountName} }},
@{N='Habilitado';E={$_.Enabled}},
@{N='PasswordCaduca';E={-not $_.PasswordNeverExpires}},
@{N='UltimoCambioPass';E={$_.PasswordLastSet}},
@{N='UltimoLogin';E={$_.LastLogonDate}},
@{N='ExpiracionCuenta';E={$_.AccountExpirationDate}},
@{N='Bloqueado';E={$_.LockedOut}},
@{N='Creado';E={$_.Created}},
@{N='OU';E={ ($_.DistinguishedName -split ',',2)[1] }},
@{N='Grupos';E={ ($_.MemberOf | ForEach-Object { (Get-ADGroup $_).Name }) -join '; ' }} |
Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "Informe exportado: $OutputPath" -ForegroundColor Cyan
}
#!/usr/bin/env bash
# =============================================================================
# Script: gestionar_usuarios.sh
# Descripción: Gestión completa de usuarios Linux
# Uso: ./gestionar_usuarios.sh [crear|modificar|eliminar|listar|bloquear|informe]
# Requiere: root o sudo
# =============================================================================
set -euo pipefail # Salir en error, variables no definidas, pipelines
IFS=$'\n\t'
# ── Colores ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
# ── Configuración ──────────────────────────────────────────────────────────────
LOG_FILE="/var/log/gestion_usuarios.log"
BACKUP_DIR="/root/backups/usuarios"
GRUPOS_BASE="usuarios,cdrom,plugdev" # Grupos secundarios por defecto
# ── Logging ────────────────────────────────────────────────────────────────────
log() {
local nivel="$1"; shift
local mensaje="$*"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$nivel] $mensaje" | tee -a "$LOG_FILE"
}
log_info() { log "INFO " "$@"; echo -e "${GREEN}[✓] $*${NC}"; }
log_warn() { log "WARN " "$@"; echo -e "${YELLOW}[!] $*${NC}"; }
log_error() { log "ERROR" "$@"; echo -e "${RED}[✗] $*${NC}" >&2; }
# ── Verificar root ─────────────────────────────────────────────────────────────
verificar_root() {
if [[ $EUID -ne 0 ]]; then
log_error "Este script debe ejecutarse como root"
exit 1
fi
}
# ── Crear usuario ──────────────────────────────────────────────────────────────
crear_usuario() {
local usuario="${1:-}"
local nombre_completo="${2:-}"
local grupo_principal="${3:-usuarios}"
local shell="${4:-/bin/bash}"
local expiracion="${5:-}" # Formato YYYY-MM-DD, vacío = nunca
# Validar nombre de usuario
if [[ -z "$usuario" ]]; then
read -rp "Nombre de usuario: " usuario
fi
if ! echo "$usuario" | grep -qE '^[a-z_][a-z0-9_-]{0,31}$'; then
log_error "Nombre de usuario inválido: '$usuario' (solo minúsculas, números, _ y -)"
return 1
fi
# Verificar si ya existe
if id "$usuario" &>/dev/null; then
log_warn "El usuario '$usuario' ya existe"
return 1
fi
# Solicitar datos faltantes
[[ -z "$nombre_completo" ]] && read -rp "Nombre completo: " nombre_completo
# Verificar/crear grupo principal
if ! getent group "$grupo_principal" &>/dev/null; then
groupadd "$grupo_principal"
log_info "Grupo '$grupo_principal' creado"
fi
# Crear usuario
local cmd_args="-m -s $shell -g $grupo_principal -c '$nombre_completo'"
[[ -n "$expiracion" ]] && cmd_args+=" -e $expiracion"
eval useradd $cmd_args "$usuario"
# Grupos secundarios
for grupo in ${GRUPOS_BASE//,/ }; do
if getent group "$grupo" &>/dev/null; then
usermod -aG "$grupo" "$usuario"
fi
done
# Establecer contraseña
local intentos=0
while [[ $intentos -lt 3 ]]; do
if passwd "$usuario"; then
break
fi
((intentos++))
[[ $intentos -eq 3 ]] && { log_error "No se pudo establecer contraseña"; return 1; }
done
# Forzar cambio de contraseña
chage -d 0 "$usuario"
# Establecer políticas de contraseña
chage -m 1 -M 90 -W 14 -I 7 "$usuario"
# Ajustar permisos del home
chmod 700 "/home/$usuario"
log_info "Usuario '$usuario' creado correctamente"
log_info " Home: /home/$usuario"
log_info " Shell: $shell"
log_info " Grupo principal: $grupo_principal"
[[ -n "$expiracion" ]] && log_info " Expira: $expiracion"
}
# ── Eliminar usuario ───────────────────────────────────────────────────────────
eliminar_usuario() {
local usuario="${1:-}"
[[ -z "$usuario" ]] && read -rp "Usuario a eliminar: " usuario
if ! id "$usuario" &>/dev/null; then
log_error "El usuario '$usuario' no existe"
return 1
fi
# Mostrar información antes de eliminar
echo -e "${YELLOW}Información del usuario '$usuario':${NC}"
id "$usuario"
echo "Home: $(getent passwd "$usuario" | cut -d: -f6)"
echo "Último login: $(lastlog -u "$usuario" | tail -1)"
read -rp "¿Eliminar usuario y su home? [s/N]: " confirmar
if [[ "$confirmar" =~ ^[Ss]$ ]]; then
# Backup del home antes de eliminar
mkdir -p "$BACKUP_DIR"
local home
home=$(getent passwd "$usuario" | cut -d: -f6)
if [[ -d "$home" ]]; then
tar czf "$BACKUP_DIR/${usuario}_$(date +%Y%m%d_%H%M%S).tar.gz" -C "$(dirname $home)" "$(basename $home)" 2>/dev/null || true
log_info "Backup del home guardado en $BACKUP_DIR"
fi
# Matar procesos del usuario
pkill -u "$usuario" 2>/dev/null || true
userdel -r "$usuario"
log_info "Usuario '$usuario' eliminado"
else
log_warn "Operación cancelada"
fi
}
# ── Bloquear/desbloquear ───────────────────────────────────────────────────────
toggle_usuario() {
local usuario="${1:-}"
[[ -z "$usuario" ]] && read -rp "Usuario: " usuario
if ! id "$usuario" &>/dev/null; then
log_error "El usuario '$usuario' no existe"
return 1
fi
# Ver estado actual
local estado
estado=$(passwd -S "$usuario" | awk '{print $2}')
if [[ "$estado" == "L" ]]; then
passwd -u "$usuario"
log_info "Usuario '$usuario' DESBLOQUEADO"
else
passwd -l "$usuario"
log_info "Usuario '$usuario' BLOQUEADO"
fi
}
# ── Listar usuarios ────────────────────────────────────────────────────────────
listar_usuarios() {
echo -e "\n${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} USUARIOS DEL SISTEMA (UID >= 1000)${NC}"
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
printf "%-20s %-6s %-20s %-10s %-15s\n" "USUARIO" "UID" "HOME" "SHELL" "ESTADO"
echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}"
while IFS=: read -r user pass uid gid gecos home shell; do
[[ $uid -lt 1000 || $uid -eq 65534 ]] && continue
local estado
estado=$(passwd -S "$user" 2>/dev/null | awk '{print $2}' || echo "?")
local color
case "$estado" in
P) color="$GREEN" ;;
L) color="$RED" ;;
*) color="$YELLOW" ;;
esac
printf "${color}%-20s %-6s %-20s %-10s %-15s${NC}\n" \
"$user" "$uid" "${home:0:19}" "${shell##*/}" "$estado"
done < /etc/passwd
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo " Estado: P=Activo, L=Bloqueado, NP=Sin contraseña"
}
# ── Informe de seguridad ───────────────────────────────────────────────────────
informe_seguridad() {
local output_file="/tmp/informe_seguridad_$(date +%Y%m%d_%H%M%S).txt"
{
echo "═══════════════════════════════════════════════════════════"
echo " INFORME DE SEGURIDAD DE USUARIOS"
echo " Generado: $(date '+%d/%m/%Y %H:%M:%S')"
echo " Servidor: $(hostname -f)"
echo "═══════════════════════════════════════════════════════════"
echo -e "\n── CUENTAS CON UID=0 (privilegio root) ──────────────────────"
awk -F: '$3==0 {print " [!] " $1}' /etc/passwd
echo -e "\n── CUENTAS SIN CONTRASEÑA ────────────────────────────────────"
awk -F: '($2==""|$2=="!"|$2=="*") && $3>=1000 && $3!=65534 {print " [!] " $1}' /etc/shadow
echo -e "\n── CUENTAS BLOQUEADAS ────────────────────────────────────────"
while IFS=: read -r user pass uid _; do
[[ $uid -lt 1000 || $uid -eq 65534 ]] && continue
[[ "$pass" =~ ^! ]] && echo " [-] $user (bloqueada)"
done < /etc/shadow
echo -e "\n── CUENTAS CON CONTRASEÑA CADUCADA ──────────────────────────"
while IFS=: read -r user _ uid _; do
[[ $uid -lt 1000 || $uid -eq 65534 ]] && continue
if chage -l "$user" 2>/dev/null | grep -q "password expired"; then
echo " [!] $user"
fi
done < /etc/passwd
echo -e "\n── SHELLS INUSUALES ──────────────────────────────────────────"
awk -F: '$3>=1000 && $3!=65534 && $7!="/bin/bash" && $7!="/bin/sh" && $7!="/usr/bin/zsh" {print " [?] " $1 " → " $7}' /etc/passwd
echo -e "\n── MIEMBROS DEL GRUPO SUDO/WHEEL ────────────────────────────"
getent group sudo wheel 2>/dev/null | awk -F: '{print " " $1 ": " $4}'
echo -e "\n── ÚLTIMOS LOGINS ────────────────────────────────────────────"
last -n 20 | head -25
echo -e "\n── USUARIOS CON SESIÓN ACTIVA AHORA ─────────────────────────"
who
} | tee "$output_file"
echo -e "\n${GREEN}Informe guardado en: $output_file${NC}"
}
# ── Menú principal ─────────────────────────────────────────────────────────────
main() {
verificar_root
mkdir -p "$(dirname $LOG_FILE)" 2>/dev/null || true
local accion="${1:-menu}"
case "$accion" in
crear) crear_usuario "${@:2}" ;;
eliminar) eliminar_usuario "${@:2}" ;;
listar) listar_usuarios ;;
bloquear) toggle_usuario "${@:2}" ;;
informe) informe_seguridad ;;
menu|*)
echo -e "\n${BLUE}Gestión de Usuarios Linux${NC}"
echo "1) Crear usuario"
echo "2) Eliminar usuario"
echo "3) Listar usuarios"
echo "4) Bloquear/desbloquear usuario"
echo "5) Informe de seguridad"
echo "0) Salir"
read -rp "Opción: " opcion
case "$opcion" in
1) crear_usuario ;;
2) eliminar_usuario ;;
3) listar_usuarios ;;
4) toggle_usuario ;;
5) informe_seguridad ;;
0) exit 0 ;;
*) log_error "Opción inválida" ;;
esac
;;
esac
}
main "$@"
#!/usr/bin/env bash
# =============================================================================
# Script: gestionar_permisos.sh
# Descripción: Auditoría y gestión de permisos en el sistema de ficheros
# =============================================================================
set -euo pipefail
# ── Auditar SUID/SGID/Sticky ───────────────────────────────────────────────────
auditar_permisos_especiales() {
local directorio="${1:-/}"
local output_file="/tmp/auditoria_permisos_$(date +%Y%m%d).txt"
{
echo "AUDITORÍA DE PERMISOS ESPECIALES"
echo "Fecha: $(date '+%d/%m/%Y %H:%M:%S')"
echo "Directorio: $directorio"
echo "═══════════════════════════════════════════"
echo -e "\n── Archivos con SUID ────────────────────"
find "$directorio" -xdev -perm -4000 -type f 2>/dev/null \
-exec ls -la {} \; | sort
echo -e "\n── Archivos con SGID ────────────────────"
find "$directorio" -xdev -perm -2000 2>/dev/null \
-exec ls -la {} \; | sort
echo -e "\n── Directorios con Sticky Bit ───────────"
find "$directorio" -xdev -perm -1000 -type d 2>/dev/null \
-exec ls -lad {} \; | sort
echo -e "\n── Archivos sin propietario ─────────────"
find "$directorio" -xdev -nouser -o -nogroup 2>/dev/null \
-exec ls -la {} \; | sort
echo -e "\n── Archivos con permisos 777 ────────────"
find "$directorio" -xdev -perm 777 2>/dev/null \
-exec ls -la {} \; | sort
echo -e "\n── Archivos world-writable (excl. sticky/sys) ──"
find "$directorio" -xdev -perm -o+w -not -perm -1000 \
-not -path "*/proc/*" -not -path "*/sys/*" 2>/dev/null \
-exec ls -la {} \; | sort
} | tee "$output_file"
echo -e "\nInforme guardado en: $output_file"
}
# ── Corregir permisos de directorio ───────────────────────────────────────────
corregir_permisos_web() {
local directorio="${1:-/var/www/html}"
local propietario="${2:-www-data}"
local grupo="${3:-www-data}"
echo "Corrigiendo permisos en: $directorio"
echo "Propietario: $propietario:$grupo"
# Propietario y grupo
chown -R "$propietario:$grupo" "$directorio"
# Directorios: 755
find "$directorio" -type d -exec chmod 755 {} \;
# Ficheros regulares: 644
find "$directorio" -type f -exec chmod 644 {} \;
# Scripts PHP/ejecutables: 755 (si los hubiera)
# find "$directorio" -name "*.php" -exec chmod 644 {} \;
echo "✓ Permisos corregidos"
}
# ── Configurar directorio compartido con SGID ─────────────────────────────────
setup_directorio_compartido() {
local directorio="$1"
local grupo="$2"
local permiso="${3:-2775}" # SGID + rwxrwxr-x
# Crear directorio si no existe
mkdir -p "$directorio"
# Crear grupo si no existe
if ! getent group "$grupo" &>/dev/null; then
groupadd "$grupo"
echo "✓ Grupo '$grupo' creado"
fi
# Asignar propietario
chown root:"$grupo" "$directorio"
# Aplicar permisos con SGID
chmod "$permiso" "$directorio"
# ACL por defecto para heredar grupo
if command -v setfacl &>/dev/null; then
setfacl -d -m g:"$grupo":rwx "$directorio"
setfacl -d -m o::0 "$directorio"
echo "✓ ACL heredadas configuradas"
fi
echo "✓ Directorio '$directorio' configurado para grupo '$grupo'"
ls -lad "$directorio"
}
# ── Backup de permisos y restauración ─────────────────────────────────────────
backup_permisos() {
local directorio="$1"
local backup_file="${2:-/root/backup_permisos_$(date +%Y%m%d).acl}"
# Guardar ACLs y permisos
getfacl -R "$directorio" > "$backup_file"
echo "✓ Permisos guardados en: $backup_file"
}
restaurar_permisos() {
local backup_file="$1"
if [[ ! -f "$backup_file" ]]; then
echo "Error: No existe el archivo $backup_file"
return 1
fi
setfacl --restore="$backup_file"
echo "✓ Permisos restaurados desde: $backup_file"
}
# ── Buscar archivos por propietario ───────────────────────────────────────────
buscar_archivos_usuario() {
local usuario="$1"
local directorio="${2:-/home}"
echo "Buscando archivos de '$usuario' en '$directorio'..."
find "$directorio" -user "$usuario" 2>/dev/null -exec ls -la {} \;
}
#!/usr/bin/env bash
# =============================================================================
# Script: crear_usuarios_csv.sh
# Uso: ./crear_usuarios_csv.sh usuarios.csv
# CSV: usuario,nombre,apellido,grupo,shell,expiracion
# =============================================================================
set -euo pipefail
CSV_FILE="${1:-}"
LOG_FILE="/var/log/creacion_masiva_$(date +%Y%m%d_%H%M%S).log"
CONTRASENA_TEMPORAL="Temporal@$(date +%Y)"
[[ -z "$CSV_FILE" ]] && { echo "Uso: $0 <fichero.csv>"; exit 1; }
[[ ! -f "$CSV_FILE" ]] && { echo "Error: Fichero no encontrado: $CSV_FILE"; exit 1; }
[[ $EUID -ne 0 ]] && { echo "Requiere root"; exit 1; }
CREADOS=0; ERRORES=0; OMITIDOS=0
while IFS=',' read -r usuario nombre apellido grupo shell expiracion; do
# Saltar cabecera o líneas vacías
[[ "$usuario" == "usuario" || -z "$usuario" ]] && continue
# Limpiar espacios y retornos de carro (Windows)
usuario=$(echo "$usuario" | tr -d '[:space:]' | tr -d '\r')
grupo=$(echo "$grupo" | tr -d '[:space:]' | tr -d '\r')
shell=$(echo "$shell" | tr -d '[:space:]' | tr -d '\r')
expiracion=$(echo "$expiracion" | tr -d '[:space:]' | tr -d '\r')
# Verificar si ya existe
if id "$usuario" &>/dev/null; then
echo "[OMITIDO] $usuario (ya existe)" | tee -a "$LOG_FILE"
((OMITIDOS++))
continue
fi
# Crear grupo si no existe
if ! getent group "$grupo" &>/dev/null; then
groupadd "$grupo"
fi
# Construir comando
CMD="useradd -m -g $grupo -s ${shell:-/bin/bash} -c '$nombre $apellido'"
[[ -n "$expiracion" ]] && CMD+=" -e $expiracion"
CMD+=" $usuario"
if eval "$CMD" 2>>"$LOG_FILE"; then
echo "$usuario:$CONTRASENA_TEMPORAL" | chpasswd
chage -d 0 -m 1 -M 90 -W 14 "$usuario"
echo "[OK] $usuario" | tee -a "$LOG_FILE"
((CREADOS++))
else
echo "[ERROR] $usuario" | tee -a "$LOG_FILE"
((ERRORES++))
fi
done < "$CSV_FILE"
echo ""
echo "══════════════════════════════"
echo " Resumen de creación masiva"
echo "══════════════════════════════"
echo " Creados: $CREADOS"
echo " Errores: $ERRORES"
echo " Omitidos: $OMITIDOS"
echo " Log: $LOG_FILE"
echo " Contraseña temporal: $CONTRASENA_TEMPORAL"
# Instalar paquetes (Debian/Ubuntu)
apt install -y sssd sssd-ad sssd-tools realmd adcli krb5-user packagekit
# Unir el equipo al dominio
realm discover empresa.local
realm join -U administrador empresa.local
# Verificar unión
realm list
# Obtener ticket Kerberos
kinit administrador@EMPRESA.LOCAL
klist
# Configurar acceso sudo a usuarios del dominio
echo "%domain\ admins@empresa.local ALL=(ALL) ALL" >> /etc/sudoers.d/dominio
# Archivo /etc/sssd/sssd.conf (configuración básica)
cat > /etc/sssd/sssd.conf << 'EOF'
[sssd]
domains = empresa.local
config_file_version = 2
services = nss, pam
[domain/empresa.local]
default_shell = /bin/bash
krb5_store_password_if_offline = True
cache_credentials = True
krb5_realm = EMPRESA.LOCAL
realmd_tags = manages-system joined-with-adcli
id_provider = ad
fallback_homedir = /home/%u@%d
ad_domain = empresa.local
use_fully_qualified_names = False
ldap_id_mapping = True
access_provider = ad
EOF
chmod 600 /etc/sssd/sssd.conf
systemctl restart sssd
#!/usr/bin/env bash
# Genera informe de seguridad completo del sistema
# Incluye: usuarios, permisos, GPOs aplicadas (si unido a AD), etc.
generar_informe_completo() {
local OUTPUT="/tmp/auditoria_completa_$(hostname)_$(date +%Y%m%d).txt"
{
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ AUDITORÍA DE SEGURIDAD COMPLETA DEL SISTEMA ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo " Servidor : $(hostname -f)"
echo " Fecha : $(date '+%d/%m/%Y %H:%M:%S')"
echo " SO : $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '"')"
echo " Kernel : $(uname -r)"
echo -e "\n══ USUARIOS DEL SISTEMA ══════════════════════════════════════"
awk -F: '$3>=1000 && $3!=65534 {printf " %-20s UID=%-6s GID=%-6s Home=%-25s Shell=%s\n", $1,$3,$4,$6,$7}' /etc/passwd
echo -e "\n══ GRUPOS Y MEMBRESÍAS ═══════════════════════════════════════"
while IFS=: read -r grupo _ gid miembros; do
[[ -n "$miembros" ]] && echo " $grupo (GID=$gid): $miembros"
done < /etc/group
echo -e "\n══ USUARIOS CON ACCESO SUDO ══════════════════════════════════"
grep -E '^\s*[^#]' /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -v "^#" || true
getent group sudo wheel 2>/dev/null | awk -F: '{print " Grupo " $1 ": " $4}'
echo -e "\n══ SERVICIOS EN ESCUCHA ══════════════════════════════════════"
ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null
echo -e "\n══ CONEXIONES ACTIVAS ════════════════════════════════════════"
who -a
echo -e "\n══ PERMISOS ESPECIALES (SUID/SGID) ══════════════════════════"
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null | sort
echo -e "\n══ ARCHIVOS WORLD-WRITABLE ═══════════════════════════════════"
find / -xdev -perm -o+w -not -path "*/proc/*" -not -path "*/sys/*" -not -perm -1000 2>/dev/null | sort
echo -e "\n══ ÚLTIMOS 20 ACCESOS ════════════════════════════════════════"
last -n 20
echo -e "\n══ INTENTOS DE ACCESO FALLIDOS ═══════════════════════════════"
lastb -n 20 2>/dev/null || grep "Failed password" /var/log/auth.log 2>/dev/null | tail -20
} | tee "$OUTPUT"
echo -e "\nInforme completo guardado en: $OUTPUT"
}
generar_informe_completo
# Usuarios
Get-ADUser -Filter * -Properties *
New-ADUser -Name "Nombre" -SamAccountName "usuario" ...
Set-ADUser -Identity "usuario" -Department "Ventas"
Disable-ADAccount -Identity "usuario"
Enable-ADAccount -Identity "usuario"
Unlock-ADAccount -Identity "usuario"
Remove-ADUser -Identity "usuario"
Set-ADAccountPassword -Identity "usuario" -Reset -NewPassword (Read-Host -AsSecureString)
# Grupos
Get-ADGroup -Filter * | Select Name, GroupScope, GroupCategory
Add-ADGroupMember -Identity "Grupo" -Members "usuario1","usuario2"
Remove-ADGroupMember -Identity "Grupo" -Members "usuario"
Get-ADGroupMember -Identity "Grupo" -Recursive
# GPOs
Get-GPO -All
New-GPO -Name "NuevaGPO" | New-GPLink -Target "OU=Ventas,DC=empresa,DC=local"
Get-GPOReport -Name "NombreGPO" -ReportType HTML -Path "C:\gpo.html"
Backup-GPO -Name "NombreGPO" -Path "C:\Backup"
# Dominio
Get-ADDomain
Get-ADForest
Get-ADDomainController -Filter *
Test-ComputerSecureChannel -Repair
# Usuarios
useradd -m -s /bin/bash -G sudo usuario
passwd usuario
usermod -aG grupo usuario
userdel -r usuario
chage -l usuario
# Permisos
chmod 755 fichero
chown usuario:grupo fichero
setfacl -m u:usuario:rwx fichero
getfacl fichero
# Información
id usuario
getent passwd usuario
getent group grupo
last; lastlog; who; w
# Búsqueda
find / -user usuario 2>/dev/null
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm -o+w -not -path "*/proc/*" # World-writable
Documento generado automáticamente. Revisado para: Windows Server 2019/2022, RHEL 8/9, Ubuntu 22.04/24.04