# rm-rf.es | Administración de sistemas

Bitácora personal de un SysAdmin Gnu/Linux, Windows, BSD...

Arreglar usuarios huérfanos en SQL Server 2008 (Orphaned Login) tras migración

Cuando migramos bases de datos importando/exportando entre diferentes servidores Microsoft SQL Server es muy probable que nos encontremos con el problema de la imposibilidad de autenticar contra el servidor con los usuarios asignados a la base de datos. Aunque los usuarios estén bien creados en la instancia de SQL Server y asignados a la base de datos correspondiente, veremos que el atributo/campo “Login name” aparece vacío y sin posibilidad de modificarlo.

Lo primero que debemos hacer es verificar que es este el problema, para ello lanzaremos una query contra la base de datos que nos reportará los SID (security identifiers) que hay en la base de datos pero que no están asignados a ningún Login name/SQL Server Login:

USE <base_de_datos>;
GO;
     sp_change_users_login @Action='Report';
GO;

Una vez detectados, podemos ir uno a uno arreglándolos:

USE <base_de_datos>;
GO
EXEC sp_change_users_login 'Auto_Fix', 'nombre_de_usuario';
GO

Y recibiremos el log indicando el fix del problema:

The row for user 'nombre_de_usuario' will be fixed by updating its login link to a login
already in existence.
The number of orphaned users fixed by updating users was 1.
The number of orphaned users fixed by adding new logins and then updating users was 0.

Existe un script/Transact-SQL, disponible en el sitio web de Microsoft y que podéis ver a continuación que simplifica este proceso, permitiendo arreglar todos los login de una base de datos directamente. Como podéis ver, incorpora un switch en la variable autoFix que permite mediante TRUE/FALSE especificar si queremos únicamente un reporte del estado de la base de datos o si automáticamente reparar todos los Login. Antes de Microsoft SQL Server 2008 existía un procedimiento almacenado / stored procedure que permitía solventar este problema, pero está obsoleta (sys.sp_change_users_login)..

/*
When you restore a database on a different SQL Server, all SQL users become a "orphaned user" because the SQL logins have a different SID then on the source server.
In SQL Server 2005 you can fix this orphaned user with the stored procedure "sys.sp_change_users_login", but since version 2008 this SP is deprecated.
This Transact-SQL statement also links orphaned user to existing principals with same name.
In regard of security this script don't add a new principal if none with same name was found; as the SP with option AUTO_FIX do.

Works with SQL Server 2005 and higher versions in all editions.
Requires ALTER ANY USER permissions.

Links:
  sys.sp_change_users_login: http://msdn.microsoft.com/en-us/library/ms174378.aspx
  ALTER USER: http://msdn.microsoft.com/en-us/library/ms176060.aspx
*/
-- Secure Orphaned User AutoFix 
DECLARE @autoFix bit; 
SET @autoFix = 'FALSE';  -- FALSE = Report only those user who could be auto fixed. 
                         -- TRUE  = Report and fix !!! 

DECLARE @user sysname, @principal sysname, @sql nvarchar(500), @found int, @fixed int; 

DECLARE orphans CURSOR LOCAL FOR 
    SELECT QUOTENAME(SU.[name]) AS UserName 
          ,QUOTENAME(SP.[name]) AS PrincipalName 
    FROM sys.sysusers AS SU 
         LEFT JOIN sys.server_principals AS SP 
             ON SU.[name] = SP.[name] 
                AND SP.[type] = 'S' 
    WHERE SU.issqluser = 1          -- Only SQL logins 
          AND NOT SU.[sid] IS NULL  -- Exclude system user 
          AND SU.[sid] <> 0x0       -- Exclude guest account 
          AND LEN(SU.[sid]) <= 16   -- Exclude Windows accounts & roles 
          AND SUSER_SNAME(SU.[sid]) IS NULL  -- Login for SID is null 
    ORDER BY SU.[name]; 

SET @found = 0; 
SET @fixed = 0; 
OPEN orphans; 
FETCH NEXT FROM orphans 
    INTO @user, @principal; 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @principal IS NULL 
        PRINT N'Orphan: ' + @user; 
    ELSE 
    BEGIN 
        PRINT N'Orphan: ' + @user + N' => Autofix possible, principal with same name found!'; 
        IF @autoFix = 'TRUE' 
        BEGIN 
            -- Build the DDL statement dynamically. 
            SET @sql = N'ALTER USER ' + @user + N' WITH LOGIN = ' + @principal + N';'; 
            EXEC sp_executesql @sql; 
            PRINT N'        ' + @user + N' is auto fixed.'; 
            SET @fixed = @fixed + 1; 
        END 
    END 
    SET @found = @found + 1; 

    FETCH NEXT FROM orphans 
        INTO @user, @principal; 
END; 

CLOSE orphans; 
DEALLOCATE orphans; 

PRINT ''; 
PRINT CONVERT(nvarchar(15), @found) + N' orphan(s) found, ' 
    + CONVERT(nvarchar(15), @fixed) + N' orphan(s) fixed.';

Copiar en Windows y mantener los permisos

Cuando copiamos o movemos ficheros y carpetas desde el explorador de Windows, no tenemos la certeza de que se vayan a mantener los permisos asignados. En el caso de que la copia se realice entre distintos sistemas de ficheros o volúmenes, menos aún.

Para estar seguros, lo mejor es utilizar el comando xcopy con los siguientes parámetros:

/E – copia carpetas y subcarpetas, incluyendo las vacías.
/H – copia ficheros ocultos y de sistema.
/K – copia atributos.
/O – copia ACLs y propietario de ficheros
/X – copia la configuración de auditoría

Así pues, accedemos a la línea de comandos (CMD) y ejecutamos el comando de este modo:

xcopy c:\ORIGEN c:\DESTINO /O /X /E /H /K

Revisad el resto de opciones de la ayuda ya que podéis elegir más opciones, como el modo verbose entre otras:

xcopy /?

Configurar el puerto TCP como estático en una instancia SQL Server 2008

Cuando instalamos un Cluster de SQL Server 2008 (o un SQL Server estándar) y especificamos la creación de una instancia distinta a la default, el puerto de escucha TCP se configura automáticamente para que sea dinámico, es decir, dentro de un rango determinado el puerto cambiará cada vez que arranquemos el servicio. En cambio, si utilizamos la instancia por defecto el puerto será el estándar (TCP 1433).

Para revertir esta situación, y poder especificar un puerto TCP concreto para cada estancia de SQL Server 2008, accedemos al Sql Server Configuration Manager, disponible en:

Start > All Programs > Microsoft SQL Server 2008 R2 > Configuration Tools

Una vez dentro, desplegamos Sql Server Network Configuration, donde veremos un listado con las instancias Sql Server disponibles. Simplemente pinchamos en TCP/IP, accedemos a la pestaña IP Adresses y al final del todo podemos especificar el puerto TCP estático (sección IPALL > TCP Port).

SQL Server puerto TCP estático

Para que los cambios surtan efecto hay que reiniciar la instancia SQL Server.

Añadir un Domain Controller Windows Server 2008 en Active Directory 2003

Hoy vamos a ver los pasos necesarios para añadir nuevos controladores de dominio Windows Server 2008 R2 dentro de una granja de servidores Windows 2003 Server que forman un directorio activo (Active Directory).

Lo primero que veremos al intentar añadir un Windows Server 2008 como Domain Controller es que recibimos un error:

ACtive Directory ADPREP 1

El error es suficientemente descriptivo. Básicamente tenemos que hacer uso de la utilidad adprep, disponible en el DVD de Windows Server 2008 R2.

Adprep.exe es una herramienta de línea de comandos que se incluye en el disco de instalación de todas las versiones de Windows Server. Adprep.exe realiza operaciones que se deben completar en un entorno de Active Directory existente antes de que se pueda agregar un controlador de dominio que ejecute dicha versión de Windows Server.

Por ejemplo, si la organización tiene controladores de dominio que ejecutan Windows 2000 Server o Windows Server 2003, antes de que se pueda agregar un nuevo controlador de dominio que ejecuta Windows Server 2008 R2 o actualizar uno de los controladores de dominio existentes a Windows Server 2008 R2, se debe ejecutar Adprep.exe desde la carpeta \Support\Adprep del DVD de instalación de Windows Server 2008 R2 en los controladores de dominio existentes.

Así pues, debemos insertar el DVD de Windows Server 2008 R2 en uno de los controladores de dominio del Active Directory. Por supuesto, es recomendable realizar un Backup con ntbackup del System State (que incluye todo lo referente a Active Directory).

Una vez realizada la copia, ejecutamos el comando adprep en uno de los controladores de dominio del AD. Nos aseguramos de ejecutar la versión de nuestra arquitectura (32 bits, 64 bits, etc). Primero ejecutamos la preparación del Forest. Atentos al aviso sobre la actualización del Service Pack:

E:\support\adprep>adprep.exe /forestprep

ADPREP WARNING:

Before running adprep, all Windows 2000 Active Directory Doma
he forest should be upgraded to Windows 2000 Service Pack 4 (

[User Action]
If ALL your existing Windows 2000 Active Directory Domain Con
requirement, type C and then press ENTER to continue. Otherwi
key and press ENTER to quit.

C
.
..
..
..................................
.............................................................
.............................................................
.............................................................
.............................................................
......
Adprep successfully updated the forest-wide information.

Si todo ha finalizado correctamente, e intentamos añadir ahora el nuevo controlador de dominio Windows Server 2008 recibiremos todavía un error. Además del Forest es necesario preparar también el dominio:

adprep preparacion dominio

Ejecutamos el comando, en este caso recibimos otro error:

E:\support\adprep>adprep.exe /domainprep
Running domainprep ...

Adprep detected that the domain is not in native mode
[Status/Consequence]
Adprep has stopped without making changes.
[User Action]
Configure the domain to run in native mode and re-run domainprep

Es necesario cambiar el dominio a modo nativo (en lugar de mixto en este caso) para poder hacer la preparación del dominio, sin cambiarlo no es posible añadir DC 2008. Para ello hacemos lo siguiente:

  1. Accedemos a “Active Directory Users and computers”
  2. Botón derecho en el dominio y “Raise Domain Functional Level”
  3. Cambiamos el nivel a 2000 Native mode.
  4. Pinchamos en Raise
Raise Functional Level Active Directory

Una vez realizado, volvemos a ejecutar el comando anterior. Se ejecuta correctamente:

E:\support\adprep>adprep.exe /domainprep
Running domainprep ...

Adprep successfully updated the domain-wide information.

The new cross domain planning functionality for Group Policy, RSOP Planning
Mode, requires file system and Active Directory Domain Services permissions
to be updated for existing Group Policy Objects (GPOs). You can enable this
functionality at any time by running "adprep.exe /domainprep /gpprep" on th
Active Directory Domain Controller that holds the infrastructure operations
master role.
This operation will cause all GPOs located in the policies folder of the
SYSVOL to be replicated once between the AD DCs in this domain.
Microsoft recommends reading KB Q324392, particularly if you have a large
number of Group policy Objects.

Esperamos un tiempo a que los cambios repliquen entre todos los controladores de dominio del Active Directory. Después ejecutamos el siguiente comando, que en caso de nos necesario nos avisará y no realizará ninguna acción:

E:\support\adprep>adprep.exe /domainprep /gpprep
Running domainprep ...

Domain-wide information has already been updated.
[Status/Consequence]
Adprep did not attempt to rerun this operation.

Y con esto hemos terminado, si intentamos añadir al Active Directory el Controlador de Dominio Windows 2008 Server no deberíamos tener ningún problema.

Sincronizar hora en Windows Server 2008 contra un servidor NTP

Vamos a ver como configurar un Windows Server 2008 R2 para sincronizar la hora con un servidor NTP externo en lugar de a través del sistema propio de Windows. Esto es útil cuando el servidor no tiene salida a internet pero sí dispone de servidores NTP en la red privada.

En este caso vamos a configurar un controlador de dominio (Active Directory) para que sincronice la hora contra un servidor NTP Linux. Accedemos al CMD y ejecutamos lo siguiente:

C:\Users\Administrator>w32tm /config /manualpeerlist:192.168.1.100,0x8 /syncfromflags:MANUAL

The command completed successfully.

El significado de la flag 0×8 es “mandar las solicitudes NTP como cliente”. Hemos configurado la sincronización contra el servidor NTP 192.168.1.100. Si quisieramos añadir varios:

C:\Users\Administrator>w32tm /config /manualpeerlist:"192.168.1.100 192.168.1.101 192.168.1.102",0x8 /syncfromflags:MANUAL

Reiniciamos el servicio w32tm:

C:\Users\Administrator>net stop w32time

The Windows Time service is stopping.
The Windows Time service was stopped successfully.

C:\Users\Administrator>net start w32time
The Windows Time service is starting.
The Windows Time service was started successfully.

Ahora ya podemos forzar la sincronización con el siguiente comando. Si la desincronización es muy amplia (+ de 5 horas) es recomendable cambiar la hora a mano para acercarnos a la real y luego sincronizar:

C:\Users\Administrator>w32tm /resync
Sending resync command to local computer
The command completed successfully.

Por último hay que asegurarse de tener el puerto 123 abierto en el firewall:

ntp firewall;

Configurar Multipath I/O (MPIO) en Windows 2008 Server

El otro día vimos como activar Multipath en Linux (RedHat y derivados). Ahora vamos a ver como hacerlo en Windows 2008 Server. Resulta muy sencillo, ya que únicamente hay que activar la característica “Multipath I/O” y hacer una búsqueda de los caminos.

Añadir soporte Multipath I/O MPIO

Abrimos el Server Manager (Administrative Tools > Server Manager) y pinchamos en añadir características (Add Features) dentro de la sección Features. En el asistente, seleccionamos Multipath I/O e instalamos.

Configurar los caminos

Antes de activar Multipath, si accedemos al gestor de storage/discos en el Server Manager veremos que cada camino es detectado como un disco. Lo que nos interesa es que detecte únicamente el disco real y que por debajo gestione todos los caminos. Ahora que hemos instalado la característica, accedemos a MPIO Properties desde el panel de control o desde MPIO en Administrative Tools del menú Inicio.

Ahora, para descubrir las LUN FC debería ser suficiente con ir a la pestaña “Discover Multi-Path” y pinchar en “Add”. Solicitará un reinicio del sistema y una vez realizado los caminos y discos debería haber sido detectados.

Nota: en esta imagen ya han sido detectadas, por eso no sale disponible el botón.

Multipath Windows 2008 Server

Podéis verificar la configuración de cada mapeo con la herramienta mpclaim.exe:

PS C:\Users\Administrator> mpclaim.exe -s -d 0

MPIO Disk0: 04 Paths, Round Robin with Subset, Implicit Only
   Controlling DSM: Microsoft DSM
   SN: 60A9800572D4275525A6939686A5063
   Supported Load Balance Policies: FOO RRWS LQD WP LB

   Path ID          State              SCSI Address      Weight
   ---------------------------------------------------------------------------
   0000000077020001 Active/Unoptimized 002|000|001|000   0
     TPG_State : Active/Unoptimized, TPG_Id: 1, : 1

   0000000077020000 Active/Optimized   002|000|000|000   0
     TPG_State : Active/Optimized  , TPG_Id: 0, : 257

   0000000077010001 Active/Unoptimized 001|000|001|000   0
     TPG_State : Active/Unoptimized, TPG_Id: 1, : 2

   0000000077010000 Active/Optimized   001|000|000|000   0
     TPG_State : Active/Optimized  , TPG_Id: 0, : 258

El último número hace referencia al mapeo/disco que queremos revisar,

Diferencias entre aplicación y directorio virtual en IIS

Una vez que creamos un Web  Site en IIS, tenemos la opción de crear directorios virtuales (Virtual Directory) o aplicaciones (Application). Vamos a ver las diferencias más significativas entre ambos y cuando elegir uno u otro.

Directorio virtual (Virtual directory)

Directorio virtual (Virtual directory)

Comenzamos con el directorio virtual ya que es más simple que una aplicación. Básicamente un directorio virtual es un mapeo a una ruta local del servidor o remota en un directorio de nuestro website. Un ejemplo:

  • Web Site: test.com (c:\inetpub\test.com\wwwroot)
  • Virtual Directory: /test
  • Mapeado a c:\test

En este ejemplo, cuando accedamos a www.test.com/test, en lugar de ir a su ruta lógica si no estuviera el directorio virtual creado, que sería c:\inetpub\test.com\wwwroot\test, accedemos a c:\test, gracias al mapeo del virtual directory. Esta es la característica principal del DV. A diferencia de lo que veremos a continuación con la aplicación, el directorio virtual se sirve a través del mismo application pool que el Web Site, y hereda por ello todas sus configuraciones a nivel de aplicación.

Aplicación (Application)

application IIS

Las diferencias con el Virtual Directory ya se intuyen. Cuando conviertes un directorio en aplicación, permites que se ejecute con un application pool independiente al del website. Esto permite añadir un mayor nivel de personalización, de seguridad y de configuración. Respecto a la configuración, por ejemplo es muy útil en ASP.NET, ya que se buscará el web.config en esta ruta en lugar de en el raíz del Web Site. Podríamos considerar entonces el directorio virtual un mero puntero/mapeo a una ruta de almacenamiento, la aplicación por contra permite aislar del resto del Web Site las aplicaciones que lo contienen.

A groso modo esta es la explicación más básica de las diferencias entre ambos, cualquier puntualización será bienvenida, no soy para nada un experto en IIS ;)

Windows Update por proxy en Windows 2008

Si ayer comentaba la forma de configurar rhn_register y yum para funcionar a través de un proxy hoy le toca a Windows 2008.

Es bastante sencillo, podemos hacerlo ejecutando directamente el siguiente comando en Start > Run

netsh winhttp set proxy 10.0.0.100:3128

Lo único que tendréis que modificar es la IP y el puerto del proxy. También se puede acceder a la shell de netsh y ejecutar desde ahí los comandos.

C:\Windows\system32>netsh
netsh>winhttp
netsh winhttp>set proxy 10.0.0.100:3128

Para desactivar el uso del proxy:

netsh winhttp>reset proxy

Y para ver el estado:

netsh winhttp>show proxy

Por otra parte, para activar Windows vía proxy tendréis que configurar el proxy en Internet Explorer.