Alertas en un Bot de Telegram con Powershell


Una de las necesidades de un Sysadmin, es  informarse en tiempo y forma de todos los errores y warnings de los servicios de misión crítica, ya que ellos implican tiempos muertos, en el peor de los casos, pero sobre todo de riesgos que se pueden remediar a través de acciones preventivas.

El visor de eventos de Windows Guindos tiene mucha información al respecto y en muchos de los casos nos da información clave para solventar un problema.

De ahí surgió la idea de enviar los eventos relevantes a través de un medio que me permitiera tenerlos ipso facto, intente primero por e-mail, pero no soy fan ni de enviar ni de recibir correos, además de que la cuenta de correo institucional, no la toco ni de chiste fuera de horas de trabajo y no quería llenarla de spam, para luego tener que depurarla.

Así que tenía instalado el Telegram y un Bot personal, que sabía que podía ocupar para eso, pero no tenía ni idea de como hacerlo, así que me puse a investigar y el resultado es el siguiente:

PRERREQUISITOS
  • Tener un Bot de telegram, sino saben como aquí está documentado
  • Tener la API Key de ese Bot
  • Tener el ChatID de un chat de tu cuenta con tu Bot, ese lo pueden obtener con un Bot que hay en Telegram, búsquenlo se llama @my_id_bot
  • Paciencia y un entorno de pruebas donde no puedas hacer mal a nadie.

A continuación el script, esta completamente documentado de manera clara, por lo que creo no debería haber dudas y si las hay, los leo en comentarios o al e-mail.

#Se declaran las variables
#Obtenemos el pool de eventos, seleccionamos el log, el origen y el ID del evento, luego se selecciona el primero (el último, más reciente)
$event = Get-EventLog -LogName System -Source "Microsoft-Windows-Directory-Services-SAM" | where {$_.eventID -eq 12294} | Select-Object -First 1
#Asiganos el valor del BotKey que nos da BotFather
$BotKey = "TUBOTKEY"
#Seleccionamos los parámetros de formato regional México
$culture = New-Object system.globalization.cultureinfo("es-MX")
#Extraemos la fecha del evento
$Fecha=Get-date $event.TimeGenerated -Format ($culture.DateTimeFormat.LongDatePattern)
#Extraemos la hora del evento
$Hora =Get-date $event.TimeGenerated -Format ($culture.DateTimeFormat.LongTimePattern)
##Extraemos el texto del evento
$mensaje = $event.Message
#Conectamos a la API de telegram con la key asignada
$GetChatID = Invoke-WebRequest -Uri "https://api.telegram.org/bot$BotKey/getUpdates"
#Se crea la función que manda el mensaje a telegram, recibiendo de parametros la BotKey, ChatID (como Array por si fueran varios) y el mensaje
function Send-TeleMessage([string] $BotKey , [array] $ChatIDs , [string] $Message)
{#Se cre la variable con la URL de la API que ejecuta el envío del mensaje
    $sendMsgLink = "https://api.telegram.org/bot$BotKey/sendMessage"
    #Se crea al bucle para cada elemento del Array
    foreach ($ID in $ChatIDs)
    {        
        try
        {#Se ejecuta el POST a la URL            
            $ExecuteInvokeWeb = Invoke-WebRequest -Uri "$sendMsgLink" -Method Post -ContentType "application/json;charset=utf-8" -Body (ConvertTo-Json -Compress -InputObject @{chat_id=$ID; text="$Message"}) -ErrorAction SilentlyContinue
            #Se recibe el resultado del POST
            $Status = (ConvertFrom-Json -InputObject $ExecuteInvokeWeb.Content)
            #Si el resultado, es ok, envia un mensaje satisfactorio, sino hace un catch del error y lo muestra.  
            if($Status.ok){Write-Host "El mensaje se envío correctamente al Chat ID : $ID (Type : $($Status.result.chat.type))" -ForegroundColor Green}
        }
        catch [Exception]
        {
            $exception = $_.Exception.ToString().Split(".")[2]
            Write-Host "Falló el envío del mensaje al Chat ID : $ID ($exception)" -ForegroundColor Red
        }
    }
}
#Se ejecuta la función con los parametros necesarios
Send-TeleMessage -BotKey $BotKey -ChatIDs "TUCHATID" -Message "$($Fecha) $($Hora) $($mensaje)"

Después de esto, hay que crear una tarea programada en windows, que ejecute este script cada que se genere un registro del evento, evidentemente el ID del evento debe coincidir para que informa de manera asertiva, el resto de las adecuaciones a sus necesidades deberían ser sencillas y el resultado es algo como esto:

Salu2, Emmanuel.