HowTo: Tomar El Control De Un Backup De AX 2012 Mediante PowerShell

!
Warning: This post is over 365 days old. The information may be out of date.

Hace unos días hacía un comentario en twitter acerca de las posibilidades de PowerShell que me trajo mucho feedback.

Supongo que hay mucho interés en conocer más sobre las bondades de PowerShell aplicadas a Microsoft Dynamics AX, y estoy preparando un artículo largo (probablemente una serie de varios artículos) sobre el tema que estarán terminados en las próximas semanas. PowerShell es una herramienta extremadamente potente y a la vez extraña. Los programadores habitualmente la consideran una herramienta de administración (es una consola) mientras que los sysadmin suelen verla como algo para programadores (es código). Curioso, ¿verdad?

Mientras termino el artículo, y para ir abriendo boca, un problema común en todas las versiones de AX es que, tras restaurar una copia de seguridad de AX de un entorno a otro, hay varias situaciones en las que no podremos acceder al sistema porque nuestro usuario no está dado de alta en esa aplicación. Casos típicos es que la copia es de un cliente lo restauramos en una máquina propia en otro dominio, o que nuestro usuario de desarrollo no está dado de alta en la aplicación de producción.

Sin importar mucho el por qué, la solución siempre ha sido ir a la base de datos manualmente, buscar en la tabla de usuarios y actualizar el SID del usuario administrador por el nuestro; o bien crear manualmente un nuevo usuario en la tabla. Esta es, de hecho, la única solución. Pero no siempre es fácil conocer nuestro SID y esta es una tarea que, por definición, podemos automatizar.

Para eso podemos utilizar un script PowerShell que podrá ser ejecutado cada vez que restauramos un backup, y nos permitirá tomar el control del usuario admin de ese entorno automáticamente (todo este código puede pegarse en un nuevo fichero con extensión .ps1 y utilizarse como un cmdlet):

[CmdletBinding()]
Param
(
    [Parameter()]
    [string] $dbInstance = "localhost",

    [Parameter(Mandatory=$True)]
    [string] $dbName,

    [Parameter()]
    [string] $adDomain = [Environment]::UserDomainName,

    [Parameter()]
    [string] $adUser = [Environment]::UserName
)

Import-Module sqlps -DisableNameChecking

$ntAccount = New-Object System.Security.Principal.NTAccount($adDomain, $adUser)
$adSID = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])

$params = "adDomain = $adDomain",
          "adUser = $adUser",
          "adSID = $adSID"

Invoke-Sqlcmd -Query "
    SELECT ID, NAME, SID, NETWORKDOMAIN, NETWORKALIAS
    FROM [dbo].[USERINFO]
    WHERE ID = 'admin';
    " -ServerInstance "$dbInstance" –Database "$dbName" | Format-Table

Invoke-Sqlcmd -Query "
    UPDATE [dbo].[USERINFO]
    SET NAME = 'Admin',
    SID = '\`$(adSID)',
    NETWORKDOMAIN = '\`$(adDomain)',
    NETWORKALIAS = '\`$(adUser)'
    WHERE ID = 'admin';
    " -ServerInstance "$dbInstance" –Database "$dbName" -Variable $params

Invoke-Sqlcmd -Query "
    SELECT ID, NAME, SID, NETWORKDOMAIN, NETWORKALIAS
    FROM [dbo].[USERINFO]
    WHERE ID = 'admin';
    " -ServerInstance "$dbInstance" –Database "$dbName" | Format-Table

El usuario nos permite pasar por parámetros los datos de nuestro usuario y la base de datos, y también asume valores por defecto. Si se utilizan los valores por defecto, el script utilizará el usuario actual. Después se utiliza el módulo PowerShell de SQL Server para lanzar el update necesario a la tabla, y nos mostrará por consola los datos antes y después de su ejecución para asegurarnos, o por si queremos guardarlo en un fichero de texto, por si acaso ;)

Este es el resultado:

Después de ejecutar el script ya puedo entrar en la aplicación correspondiente porque desde este momento mi usuario esta enlazado al usuario admin de esa aplicación.

Más sobre PowerShell en los próximos días! :)