HowTo: Tomar El Control De Un Backup De AX 2012 Mediante PowerShell
Hace unos días hacía un comentario en twitter acerca de las posibilidades de PowerShell que me trajo mucho feedback.
Installed a complete AX development server from a fresh Windows in 20 min, fully unattended, with a powershell script.
— José Antonio Estevan² (@jaestevan) February 26, 2015
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.
I'm so in love with powershell that I think I'm gonna cry =) This deserves some blog posts.
— José Antonio Estevan² (@jaestevan) February 26, 2015
Más sobre PowerShell en los próximos días! :)