Azure Automation — Produccion

UserOnboarding
Runbook

Alta de usuario completamente automatizada desde una lista de SharePoint. Crea la cuenta en Active Directory, sincroniza con Microsoft 365, crea la VM Hyper-V si es necesario, y publica el resultado directamente en Jira.

👤 Autor: JM Fernandez + Claude (Anthropic)
📅 Fecha: Marzo 2026
☁️ Plataforma: Azure Automation + Hybrid Worker
Azure Automation Hybrid Runbook Worker PowerShell 7.2 Active Directory AD Connect Sync Hyper-V Cluster Jira REST API v2 Power Automate Cloud
9
pasos de alta
~200
altas / ano
~100h
ahorro anual
3
sistemas integrados

Flujo de ejecucion

Un nuevo elemento en la lista de SharePoint dispara Power Automate, que crea el job en Azure Automation y espera el resultado. El Hybrid Worker on-prem ejecuta el wrapper, que a su vez llama a los scripts de logica en el servidor.

📄
SharePoint
Trigger
Nueva entrada en la lista de SharePoint dispara Power Automate.
Power Automate
Cloud
Crea el job con los parametros del ticket. Espera resultado.
☁️
Azure Automation
Runbook Job
Enruta el job al Hybrid Worker Group on-prem.
💻
Hybrid Worker
sisscripts / on-prem
Ejecuta UserOnboarding.ps1 con acceso completo a AD y sistemas internos.
Thin wrapper: UserOnboarding.ps1 (en Azure) solo declara parametros. Toda la logica esta en onboarding.ps1 (en git, en el servidor).
VM opcional: Si CreateVM=true y el alta es exitosa llama a create_vm.ps1 via Start-Process aislado.
Jira directo: El wrapper publica el comentario wiki-formatted en el ticket via Jira REST API v2. Power Automate solo envia el mensaje de Teams con las credenciales.
JSON output: El runbook emite un JSON plano y estructurado que Power Automate parsea con Parse JSON.

Inputs del runbook

Todos los parametros se mapean directamente desde Power Automate al crear el job. Los parametros de solo wrapper (JiraTicket, CreateVM) se eliminan de PSBoundParameters antes de pasar al script de logica.

ParametroTipoObligatorioDescripcion
SourceUserSamAccountNamestringSiUsuario AD a clonar como plantilla
NewSamAccountNamestringSiLogin del nuevo usuario
GivenNamestringSiNombre
SurnamestringSiApellidos
UserPrincipalNamestringNoUPN si difiere del patron por defecto
CompanyName, Manager, Office...stringNoAtributos AD opcionales
PrimarySMTPstringNoSMTP primario del buzon
SecondarySMTPstring[]NoAliases de correo adicionales
ExtensionAttribute1..15stringNoAtributos extendidos AD (explicito > heredado de plantilla)
AdditionalGroupsstring[]NoGrupos adicionales mas alla de los de la plantilla
OUstring[]NoOU destino. Azure Automation fragmenta las comas — el wrapper rejunta el array en un string de ruta DN.
CreateVMboolNoSi true y el alta es exitosa, crea VM en cluster Hyper-V
PlatformstringNoPlataforma del usuario (Windows o Mac). Determina el grupo de licencias M365 a asignar.
JiraTicketstringNoClave del ticket donde publicar el comentario (ej: SYS-1234)

Proceso de alta

Ejecutado por onboarding.ps1 en el servidor on-prem. Cada paso con try/catch. El resultado de cada paso queda reflejado en el log JSON.

PasoAccionDetalle
1 Obtener plantilla Lectura del usuario de referencia con Get-ADUser -Properties *
2 Generar password RNG criptografico RNGCryptoServiceProvider. Formato Palabra##!Palabra con pool de 200 palabras espanolas. Facil de dictar por telefono.
3 Crear usuario AD New-ADUser con fusion de atributos: explicitos (parametros) > heredados de plantilla
4 ProxyAddresses SMTP primario + aliases secundarios. Respeta la politica de naming corporativa.
5 ExtensionAttributes Copia de extensionAttributes 1-15. Prioridad: valor explicito > heredado de plantilla.
6 Grupos de seguridad Clonacion de todos los grupos del usuario plantilla + grupos adicionales opcionales via Add-ADGroupMember.
7 AD Connect delta sync Trigger de sincronizacion incremental para propagacion inmediata a Azure AD / Microsoft 365.
8 Habilitar cuenta Enable-ADAccount tras completar la configuracion inicial.
9 Salida JSON Respuesta estructurada con Success, SamAccountName, UPN, Password y Log completo.

Creacion de maquina virtual

Si el parametro CreateVM es true y el alta de usuario ha sido exitosa, el wrapper lanza create_vm.ps1 para crear la VM del usuario en el cluster Hyper-V.

📊

Cluster Hyper-V

Conecta al cluster hypervcolt.oficina.idealista, selecciona el nodo disponible y el CSV con mas espacio libre.

💾

Copia de plantilla

Copia el VHDX plantilla (w11plantilla.vhdx) al CSV seleccionado. Configura procesadores, memoria, red VLAN 25 y servicios de integracion.

☀️

Alta disponibilidad

Registra la VM como rol de cluster con Add-ClusterVirtualMachineRole y la arranca via Start-ClusterGroup.

Aislamiento de warnings: Los cmdlets de Failover Clustering escriben warnings directamente al proceso host, saltandose los streams de PowerShell. Para evitar que contaminen el JSON output del runbook, create_vm.ps1 escribe el resultado en $env:TEMP\create_vm_result.json y el wrapper lo lanza via Start-Process powershell.exe con stdout/stderr redirigidos a ficheros que se descartan. El resultado llega por el fichero temporal, que se elimina tras la lectura.

Group-based licensing automatico

Si se proporciona el parametro Platform, el wrapper asigna automaticamente al usuario a un grupo de licencias M365 en Azure AD via Microsoft Graph API. El mapeo se configura en config.psd1.

📋

Mapeo configurable

Tabla en config.psd1 → LicenseGroups con mapeo empresa + plataforma → grupo de licencias. Soporta fallback _default, wildcard * y exclusion con $null.

🔎

Verificacion de disponibilidad

Antes de asignar, consulta Get-MgSubscribedSku para comprobar si quedan licencias disponibles. Si alguna SKU esta agotada, asigna igualmente pero crea un ticket de aviso.

🎫

Ticket Jira automatico

Si las licencias estan agotadas, crea un ticket en Jira (proyecto SIS) con detalle de SKUs y lo enlaza al ticket de alta usando Add-JiraIssueLink.

Mapeo actual (config.psd1)

EmpresaWindowsMac
_default (cualquier empresa)LIC M365 E5LIC M365 Business Premium
Avaibook On-line, S.L.U.LIC M365 E3LIC M365 Business Premium
ColaboradorLIC M365 F1 (cualquier plataforma)
ExternoExcluido (sin licencia)
Retry para ADConnect: El usuario se crea en AD on-prem y tarda unos segundos en sincronizarse a Azure AD. El wrapper reintenta Get-MgUser hasta 3 veces con 15s de espera entre cada intento para encontrar al usuario antes de asignarlo al grupo.

Comentario automatico en el ticket

Si se proporciona JiraTicket, el wrapper publica un comentario wiki-formatted directamente en el ticket via Jira REST API v2. Power Automate solo envia el mensaje de Teams con las credenciales.

Formato del comentario: Tabla wiki-markup con estado, SamAccountName, UPN, nombre completo y — si CreateVM=true — el resultado de la VM. Seguido del log completo del proceso en bloque {noformat}.

Alta completada

Tabla con (/) COMPLETADO, credenciales de acceso y fila de VM Hyper-V si fue solicitada.

Alta con error

Tabla con (x) ERROR y el log del proceso para diagnostico. El campo success: false en el JSON permite a Power Automate crear un ticket de incidencia adicional.

💬

Modulo JiraComments.psm1

Autenticacion Basic Auth (email:token en Base64). Funcion Add-JiraComment. El Write-Host del modulo se suprime con 6>$null para no contaminar el JSON output.

Schema de salida

El runbook emite un unico JSON compacto al final. Power Automate lo parsea con la accion Parse JSON usando el schema siguiente.

{
  "success": boolean      // true si el alta en AD fue exitosa
  "samAccountName": string
  "upn": string
  "displayName": string
  "password": string      // NO incluido en el comentario de Jira
  "jiraCommentPosted": boolean
  "vmCreated": boolean      // false si CreateVM=false o si el alta fallo
  "vmLog": array<string>
  "licenseGroupAssigned": boolean   // true si se asigno grupo de licencias
  "licenseAvailable": boolean|null // false si SKU agotado, null si no aplica
  "jiraLicenseTicket": string|null  // ticket Jira si licencias agotadas
  "log": array<string>  // log paso a paso del alta
}
Contrato limpio: El wrapper construye su propio JSON ordenado — no pasa el JSON interno de onboarding.ps1 directamente. Esto desacopla el schema de Power Automate de la estructura interna del script y evita rotura del Parse JSON ante cambios internos.