Problema

En entornos Azure con Windows Server VMs se suele habilitar la extensión AADLoginForWindows para que los usuarios de Entra (Azure AD) inicien sesión mediante RDP. Cuando la automatización necesita ejecutar comandos dentro de la máquina –por ejemplo, Ansible, pipelines de CI/CD o scripts de mantenimiento– el método tradicional (WinRM/WinSSH con credenciales locales) deja de ser viable. Crear y gestionar usuarios locales en cada VM rompe la escalabilidad y aumenta la superficie de ataque. El desafío es encontrar una forma de autenticarse desde herramientas externas sin depender de cuentas locales y sin reescribir flujos que asumen estar “dentro” de la VM.

Causa

  1. Extensión AADLoginForWindows solo cubre RDP/SSH
    La extensión registra la VM como Azure AD‑joined, lo que permite autenticación de escritorio, pero no expone un token que WinRM o WinSSH puedan consumir directamente.

  2. WinRM/WinSSH requieren credenciales de tipo NTLM/Kerberos
    Los protocolos de gestión remota de Windows esperan un nombre de usuario y una contraseña (o un ticket Kerberos). Un service principal de Entra no genera esos artefactos de forma nativa.

  3. Ausencia de un dominio interno
    Sin Azure AD Domain Services (Azure AD DS) o un AD híbrido, no hay un controlador de dominio que emita tickets Kerberos para los service principals.

  4. Expectativas de los agentes de automatización
    Herramientas como Ansible o Azure Pipelines asumen que pueden conectarse mediante WinRM usando credenciales estáticas o un archivo de clave. Cuando esas credenciales no existen, el flujo se rompe.

Solución

1. Utilizar Azure VM Run Command como puente

Azure VM Run Command permite ejecutar scripts PowerShell o Bash dentro de la VM sin necesidad de abrir puertos ni disponer de credenciales locales. La llamada se hace a través de Azure CLI o SDK, autenticándose con un service principal de Entra. El flujo típico es:

  1. Crear o reutilizar un service principal con permisos Microsoft.Compute/virtualMachines/runCommand/action sobre el recurso VM.
  2. Invocar Run Command con el script que necesite ejecutarse (por ejemplo, un módulo de Ansible o un comando PowerShell).
  3. Recoger la salida y continuar la pipeline.

Esta técnica elimina la dependencia de usuarios locales y mantiene todo bajo el control de Azure RBAC.

2. Habilitar Azure AD DS para Kerberos‑based WinRM

Si la organización ya cuenta con Azure AD DS, las VMs pueden unirse a ese dominio gestionado. Azure AD DS expone Kerberos y NTLM, por lo que un service principal puede obtener un ticket mediante el flujo Azure AD OAuth → Kerberos (preview). Con el ticket, WinRM acepta la autenticación y Ansible puede usar el módulo winrm sin credenciales locales.

Pasos resumidos:

  1. Provisionar Azure AD DS y sincronizar los usuarios o grupos de Entra que necesiten acceso.
  2. Unir la VM a Azure AD DS (puede hacerse con la extensión DomainJoin).
  3. Configurar WinRM para Kerberos (winrm quickconfig -transport:https).
  4. Obtener un ticket Kerberos usando kinit con el client ID y secret del service principal.
  5. Ejecutar Ansible apuntando a la VM con ansible_user vacío y ansible_connection=winrm.

3. Emplear Managed Identity + Azure Automation Runbooks

Cuando la automatización se ejecuta dentro de Azure (por ejemplo, Azure DevOps o GitHub Actions), se puede asignar una System‑Assigned Managed Identity a la VM o al agente de ejecución. Un Runbook de Azure Automation, ejecutado bajo esa identidad, llama a Invoke-AzVMRunCommand. El script se mantiene en el propio Runbook, lo que evita cualquier credencial estática.

4. Alternativa rápida: Azure Bastion con RDP/SSH y PowerShell Direct

Si la única necesidad es lanzar scripts puntuales y no se requiere una sesión persistente, Azure Bastion permite abrir una conexión RDP/SSH basada en Azure AD y, desde allí, usar PowerShell Direct (cuando la VM está en el mismo host) o Invoke‑Command sobre la sesión RDP. Esta opción es menos automatizable pero útil para tareas ad‑hoc.

Cuándo aplicar esta solución

Señal Solución recomendada
Necesitas ejecutar scripts desde CI/CD sin exponer contraseñas Azure VM Run Command + Service Principal
Tu organización ya usa Azure AD DS o planea migrar a un dominio gestionado Kerberos‑based WinRM con Azure AD DS
La automatización se ejecuta dentro de Azure y puedes usar Managed Identities Automation Runbooks + Managed Identity
Solo necesitas accesos ocasionales y no quieres cambiar la arquitectura Bastion + PowerShell Direct

No apliques estas técnicas si la VM está aislada en una red sin conectividad a Azure Resource Manager (por ejemplo, VNet sin salida a Internet) o si la política de la empresa prohíbe el uso de Azure AD DS.

Código

# 1. Crear service principal (si no existe)
az ad sp create-for-rbac --name "ansible-runner" \
    --role "Virtual Machine Contributor" \
    --scopes "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Compute/virtualMachines/<vm-name>" \
    --years 2

# 2. Ejecutar un script PowerShell dentro de la VM
az vm run-command invoke \
    --resource-group <rg> \
    --name <vm-name> \
    --command-id RunPowerShellScript \
    --scripts "Write-Host 'Hello from Azure VM'; Get-Service | Where-Object {$_.Status -eq 'Running'}" \
    --parameters '' \
    --output json

Para Kerberos con Azure AD DS:

# Obtener token OAuth para el SP
az account get-access-token --resource https://kerberos.windows.net/ --query accessToken -o tsv > token.txt

# Convertir token a ticket Kerberos (requiere kinit de la versión preview)
kinit -i <client-id> -s <client-secret> -t token.txt

# Probar WinRM con Kerberos
ansible -i <ip>, -m win_ping all -e "ansible_connection=winrm ansible_winrm_transport=kerberos"

Verificación

  1. Run Command: La salida del comando az vm run-command invoke debe contener el texto Hello from Azure VM y la lista de servicios en ejecución. Un código de salida 0 indica éxito.
  2. Kerberos WinRM: Ejecuta ansible -m win_ping contra la VM. Si la respuesta es SUCCESS, la autenticación Kerberos está funcionando.
  3. Automation Runbook: Revisa el historial del Runbook en el portal; debe mostrar RunCommand completado sin errores.

En caso de fallos, verifica que el service principal tenga los permisos Microsoft.Compute/virtualMachines/runCommand/action y que la VM tenga la extensión AADLoginForWindows actualizada a la última versión.

Notas adicionales

  • Rotación de secretos: Cuando uses client secret en el service principal, programa una rotación automática (Azure Key Vault + Azure Automation) para evitar expiraciones inesperadas.
  • Limitaciones de Run Command: El script se ejecuta con privilegios de administrador local, pero no persiste cambios de configuración del sistema que requieran reinicio.
  • Auditoría: Todas las llamadas a Run Command quedan registradas en Azure Activity Log; úsalo para trazabilidad y cumplimiento.
  • Redes privadas: Si la VM está en una red sin salida a Internet, habilita Private Link para Azure Resource Manager o usa Azure Bastion como fallback.
  • Compatibilidad: La funcionalidad Kerberos‑based WinRM está en preview; revisa la documentación oficial antes de adoptarla en producción.