PowerShell para la administración automática de Dynamics AX 2012 (PS-II)

En la primera entrega de esta serie sobre PowerShell y DevOps para Microsoft Dynamics AX 2012  hablábamos sobre los principios más básicos de PowerShell y su sintaxis. También vimos en post anteriores como PowerShell se puede usar de formas bastante creativas.

Keyboard

Esta vez vamos a ver los comandlets específicos para la administración de Microsoft Dynamics AX 2012, que podemos separar en varias familias:

Gestión de Modelos y la Model Store

Estos comandlets son muy importantes y van a ser la base de nuestra estrategia DevOps, combinada con los procesos builds automáticos que tendremos configurados en nuestro TFS, si es que los utilizamos.

La combinación de estos componentes va a permitirnos diseñar procesos que actualicen automáticamente nuestros entornos, orientando nuestros procesos hacia la integración o el despliegue continuo de nuestros entornos, especialmente entornos de desarrollo y/o pruebas. Hablaremos sobre esto en los siguientes posts de esta serie.

Estos son los que normalmente utilizamos para estas tareas, aunque vale la pena echar un vistazo a la referencia completa porque todos pueden ser útiles para tareas concretas o para scripts que automaticen tareas más completas:

Modelos

Comando Descripción
New-AXModel  Crea un nuevo modelo en la Model Store
Uninstall-AXModel  Elimina un modelo de la Model Store
Install-AXModel  Importa un modelo (desde un fichero) en la Model Store
Export-AXModel  Exporta un model de la Model Store a un fichero .axmodel
Move-AXModel  Mueve los objetos de un modelo a otro modelo, combinando todos los objetos en este último.

Continue Reading…

HOWTO: Exponer servicios de Microsoft Dynamics AX 2012 en un IIS externo

Para exponer los servicios web de Microsoft Dynamics AX 2012 fuera de nuestra red, es necesario instalar un servicio IIS que maneje las conexiones y la seguridad con “el mundo exterior“. La instalación de este servicio dependerá de nuestra red y lo ideal es que sea realizado por personal especializado en estas tareas (normalmente en un departamento de sistemas). Una vez instalado, la conexión de este servicio IIS con nuestra instancia de AX es muy sencilla.

Antes de empezar la instalación en sí, comprobamos algunos pre-requisitos.

  • El servicio IIS debe estar instalado y funcionando previamente. Si no lo está, para instalarlo hacemos lo siguiente:
    • La mayoría de pre-requisitos se pueden instalar directamente desde el instalador de Microsoft Dynamics AX 2012, pero si esto falla será necesario instalarlo manualmente.
    • Activar el rol Web Services en nuestro servidor y seguir el asistente.
    • Un reinicio es necesario al final del proceso.
    • Las opciones por defecto son suficientes para la instalación de Dynamics AX, pero probablemente será necesario realizar ajustes extra para adaptarlo a la seguridad que deseamos implementar en nuestra empresa, según el caso. No hay que olvidar que la finalidad de esta instalación es exponer este servicio a internet.
    • Puesto que el ejemplo es un servidor de pruebas, mantenemos las opciones por defecto, lo que implementará la seguridad nativa de Windows con Active Directory, solicitando un usuario válido durante la conexión.
  • Una vez instalado y asegurado nuestro servicio IIS, iniciamos el asistente de instalación de Dynamics AX 2012 en el mismo servidor y elegimos la opción Web Services on IIS, y seguimos las instrucciones. Durante el asistente, se nos solicita diversa información sobre nuestra instancia de AOS y las credenciales utilizadas para la conexión, como son:
    • Información sobre la instancia de AOS en sí: Nombre y puertos TCP/IP y WDSL
    • Cuenta de servicio configurada en AX (Business connector proxy)
    • Pool de IIS donde se instalarán y expondrán los servicios de AX
    • Las cuentas de servicio utilizadas para ejecutar nuestras instancias de AOS
  • El propio instalador configura la seguridad por defecto de la aplicación recién instalada en el pool de IIS seleccionado, pero podemos revisarla y configurarla manualmente si es necesario:
    • Se ha creado la aplicación MicrosoftDynamicsAXAif60 en el pool de IIS indicado
    • Se ha creado un nuevo grupo de usuarios local llamado Microsoft Dynamics AX Web Service Administrator incluyendo los usuarios que ejecutan los servicios AOS, según indicamos en el instalador.
    • Se le ha otorgado permiso a este grupo en la carpeta local AifWebServices del servidor IIS

También se ha creado un nuevo servicio en Microsoft Dynamics AX que podemos revisar en Administración del sistema > Configurar > AIF > Sitios web. Utilizaremos este sitio web para asociarlo a un puerto de entrada para poder exponer métodos en nuestros servicios, de esta forma:

  • Crear un nuevo puerto de entrada y seleccionar
    • Adaptador: HTTP
    • URL: Seleccionar la aplicación recién creada de la lista
  • Añadir las operaciones de servicio que se desean exponer mediante el botón Service operations
  • Realizar el resto de configuraciones requeridas en el puerto de entrada, como validaciones o restricciones que vayamos a necesitar. En mi caso voy a limitar las conexiones a un grupo de usuario de AX y a una sola empresa.

Como se puede ver en las imágenes a continuación, las operaciones expuestas de este modo pueden ser consumidas desde una aplicación externa en Visual Studio, a través de la aplicación creada en nuestro IIS:

Espero que este manual paso a paso haya sido útil y pueda servir de referencia para futuras instalaciones 😉

[HOWTO] Impersonar otro usuario para ejecutar código en X++

A pesar de que esto no es habitual y va contra unas cuentas Best Practices, en algunos casos muy específicos podemos necesitar ejecutar un framento de X++ (una llamada a un método) en el contexto de un usuario que no es el que está ejecutando la sesión actual, ya sea una sesión de cliente o un proceso Batch. Para ejecutar una llamada a un método con un usuario concreto, usamos este código:

// ...

// Usuario que va a ejecutar el método
UserId postingUserId = parms.PostingUserId != '' ? parms.PostingUserId : curUserId();

new RunAsPermission(postingUserId).assert();

// Llamada a: MyClass.myClassMethod(methodParm1, methodParm2)

// BP Deviation Documented
runAs(postingUserId, classNum(MyClass), 'myClassMethod', [methodParm1, methodParm2]);

CodeAccessPermission::revertAssert();

// ...

Insisto en que esto no es habitual y tiene, como siempre que hacemos estas cosas, algunos riesgos de seguridad. Pero dejo aquí el código para buscarlo la próxima vez que lo necesite 😉

[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.

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:

Restore-AXAdminUser

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! 🙂

Consultar roles de seguridad desde SQL en AX 2012

No es algo común pero en algún caso nos puede venir bien consultar qué roles de seguridad tiene un usuario consultando la base de datos. Lo ideal sería utilizar servicios web o algo parecido, utilizando un código X++ parecido al siguiente (código extraído del capítulo 10: “Licencia, Configuración y Seguridad” de mi libro):

static void QueryRoles(Args _args)
{
    SecurityRole            securityRole;
    SecurityUserRole        securityUserRole;

    while select securityUserRole
            where securityUserRole.User == 'admin'
        join securityRole
            where securityRole.RecId == securityUserRole.SecurityRole
    {
        info(strFmt("%1", SysLabel::labelId2String(securityRole.Name)));
    }
}

Si insistimos en hacer esta consulta desde SQL Server nos vamos a llevar una sorpresa. La tabla SecurityUserRole que almacena los roles asignados a cada usuario existe en la base de datos transaccional de AX, pero la tabla SecurityRole, que almacena los roles en si, no existe. Sería lógico pensar que, a lo mejor, la tabla existe en la base de datos modelo (_model), pero tampoco la encontramos ahí.

Tras recurrir al truco que comentaba unos cuantos post atrás, nos encontramos con que la tabla está efectivamente en la base de datos modelo, pero abstraída tras un procedimiento almacenado, y tiene esta pinta:

SELECT T1.NAME, T1.ALLOWPASTRECORDS, ...
FROM [XXXX_model].[dbo].SECURITYROLE_INLINEFUNC(N'en_us') T1

Por tanto, jugando un poco con la consulta, podemos obtener el mismo resultado que consultando desde X++:

SecurityUserRole X++

Pero desde SQL Server, y por tanto desde cualquier aplicación externa:

SecurityUserRole SQL

Utilizar con cuidado 😉

 

Configurar Firewall en instalaciones Microsoft Dynamics AX 2012Microsoft Dynamics AX 2012 Firewall Setup

Complementando el artículo que publiqué hace unas semanas, recopilando los datos para configurar la seguridad de instalaciones Microsoft Dynamics AX 2012, el siguiente cuadro detalla la información necesaria para configurar el Firewall de Windows en cada una de las máquinas implicadas en una de estas instalaciones.

Componente Equipo Configuración del Firewall Notas
Setup Permitir conexiones HTTP salientes Para acceder a la documentacion disponible durante el wizard de instalación, es necesario tener acceso a Internet desde el equipo que ejecuta el setup.
Base de Datos Servidor SQL Server Excluir el puerto utilizado por SQL Server (1433 por defecto) Más información en la guía de instalación de SQL Server.
Application Object Server (AOS) Servidor AOS
  • Excluir el puerto TCP/IP utilizado por el AOS (2712 por defecto). La instalación crea una regla de entrada automáticamente para este puerto (Dynamics AX 6.0 -MicrosoftDynamicsAX (RPC)).
  • Excluir el puerto de los servicios WSDL utilizado por el AOS (8101 por defecto). La instalación crea una regla de entrada automáticamente para este puerto (Dynamics AX 6.0 -MicrosoftDynamicsAX (WSDL)).
  • Excluir el puerto del endpoint de los servicios utilizado por el AOS (8201 por defecto). La instalación crea una regla de entrada automáticamente para este puerto (Dynamics AX 6.0 -MicrosoftDynamicsAX (NetTCP)).
El Firewall de Windows debe estar activado en el equipo. Cada instancia de AOS utiliza un puerto diferente.

NOTA: Por defecto, cada vez que se instala una instancia de AOS en un equipo, el número de puerto TCP/IP y los puertos de los endpoint de sus servicios se incrementan en uno. Por ejemplo, la segunda instancia de AOS en un equipo debe ser asignada al puerto TCP/IP 2713 por defecto.

Cliente Equipo cliente Excluir Ax32.exe. El cliente utiliza un puerto TCP para conectar al AOS.
Business Intelligence Reporting Server Excluir el puerto utilizado por el directorio virtual de Reporting Services si no es el 80.
Intelligence Components Analysis Server
  • Excluir el puerto utilizado por Analysis Services (2383 por defecto).
  • Si se utiliza el SQL Server Browser, debe excluir también el puerto 2382.
Más información en la guía de instalación de SQL Server.
Debugger Equipo de desarrollador Excluir AxDebug.exe y sus aplicaciones de destino como Ax32.exe y AxServ32.exe. El depurador utiliza un puerto TCP asignado dinámicamente.
Enterprise Portal Servidor web
  • Activar Web Server (HTTP).
  • Excluir el puerto utilizado por el sitio de Enterprise Portal si no es el 80.
Si no se activa el Web server en el Firewall de Windows, sólo se podrá acceder al sitio desde el servidor local.
Servidor de ayuda Servidor web Excluir el puerto utilizado por el sitio de Help Server, si no es el 80.
Enterprise Search Servidor web Excluir el puerto utilizado por el sitio de Búsqueda, si no es el 80.
Web Services Servidor web Excluir el puerto utilizado por el sitio de los servicios web, si no es el 80. Aplicaciones externas utilizan este puerto para consumir los servicios web de Microsoft Dynamics AX basados en IIS.

Se recomienda obtener información actualizada en la siguiente página de TechNet.

If you use Windows Firewall to help protect your computers, Microsoft Dynamics AX components require the settings in the following table. For updated detail, see this page on TechNet

Component Computer Firewall Setting Notes
Setup Any Allow outbound HTTP connections To access the documentation that is available from the Setup wizard, you must be able to connect to the Internet from the computer where you are running Setup.
Database or Model Store Database Server Exclude the port used by SQL Server (1433 by default) For more information, refer to the SQL Server documentation.
Application Object Server (AOS) AOS Server
  • Exclude the TCP/IP port used by the AOS (2712 by default)

Setup automatically creates the inbound rule “Dynamics AX 6.0 -MicrosoftDynamicsAX (RPC)” for the TCP/IP port.

  • Exclude the services WSDL port used by the AOS (8101 by default)

Setup automatically creates the inbound rule “Dynamics AX 6.0 -MicrosoftDynamicsAX (WSDL)” for the WSDL port.

  • Exclude the services endpoint port used by the AOS (8201 by default)

Setup automatically creates the inbound rule “Dynamics AX 6.0 -MicrosoftDynamicsAX (NetTCP)” for the services endpoint port.

Windows Firewall must be enabled on the computer. Each AOS instance must use a different port number. NOTE: By default, each time you install an additional AOS instance on a computer, the TCP/IP port number and the Services endpoint port numbers increment by one. For example, the second AOS instance on a computer would be assigned to TCP/IP port 2713 by default.
Client Client Workstation Exclude Ax32.exe. The client uses a TCP port to connect to the AOS.
Business Intelligence Components Reporting Server Exclude the port used by Reporting Services virtual directories, if other than port 80.
Business Intelligence Components Analysis Server
  • Exclude the port used by Analysis Services (2383 by default)
  • If you are using SQL Server Browser, you must also exclude port 2382.
For more information about configuring access to Analysis Services through Windows Firewall, refer to the SQL Server documentation on MSDN.
Debugger Developer Workstation Exclude AxDebug.exe and its target applications, such as Ax32.exe and AxServ32.exe. The debugger uses a dynamically allocated TCP port.
Enterprise Portal Web Server
  • Activate Web Server (HTTP)
  • Exclude the port used by the Enterprise Portal Web site, if other than port 80.
If you do not activate the Web server in Windows Firewall, you will only be able to view the site from the local server.
Help Server Web Server Exclude the port used by the Help Server web site, if other than port 80.
Enterprise Search Web Server Exclude the port used by the Search web site, if other than port 80.
Web Services Web Server Exclude the port used by the services web site, if other than port 80. External applications use this port to consume the IIS-based Microsoft Dynamics AX web services.