Foro QNAP en español
Escritura registros en MariaDB desde powershell - Versión para impresión

+- Foro QNAP en español (https://www.qnapclub.es)
+-- Foro: GENERAL (https://www.qnapclub.es/forumdisplay.php?fid=3)
+--- Foro: Firmware, Aplicaciones y Tutoriales (https://www.qnapclub.es/forumdisplay.php?fid=39)
+--- Tema: Escritura registros en MariaDB desde powershell (/showthread.php?tid=5192)



Escritura registros en MariaDB desde powershell - Ganekogorta - 19-01-2024

Hola

Este post es un poco distinto de los habituales que vemos por el foro, pero creo que puede ser interesante para mas de uno y puede dar nuevas ideas de uso.

Hasta hace poco tenía una nas de Qnap integrada como miembro de un directorio activo.
Es decir sus carpetas compartidas podían ser accedidas por usuarios del directorio activo que no son de locales de la nas.
Básicamente el servidor y los equipos de la red accedían a la nas con los privilegios del directorio activo.
Una de las ventajas es que en el log de la nas se veía en todo momento las acciones de los usuarios hacia el recurso compartido (quien y que archivo se leía y borraba).
Debido a que esa nas está orientada a ser de almacenamiento (discos SATA y agrupación de tarjetas), el acceso se veía penalizado y se hacia lento cuando muchos usuarios lo hacían de forma simultánea.
Al final optamos por poner un almacenamiento externo a la nas y gestionado directamente por el servidor del directorio activo.
El servidor también tiene su "log", en este caso es un visor de eventos, pero no es tan útil y no quería tener unas reglas de auditoría excesivas que lo lastrasen.

Así que pensé en una forma de trasladar esa información a la nas. 
Lo forma en que la que lo he hecho es la siguiente:
-activo una auditoria en servidor que me cree determinados registros en el visor de eventos.
-mediante una tarea programada lanzo mediante powershell esos registros y no otros hacia la nas.
-la nas acepta esos registros en un base de datos creada en MariaDB.

1-Creación de la BBDD en MariaDB en la NAS

Primero debemos tener MariaDB 10 operativa en la Nas. Si no lo está, la agregamos desde el el App Center.


Podemos hacerlo ayudándonos de phpMyAdmin  o bien de forma manual mediante la consola de comandos.
Los pasos básicos son crear una BBDD de nombre "eventos_servidor" y en su interior una tabla que llama "items_alterados".
Luego un usuario que he llamado "administrador" con permisos a esa BBDD.

Por consola los comando en MariaDB serían:
Código:
mysql> CREATE DATABASE eventos_servidor;


Ahora damos privilegios al usuario "administrador" a la ip de nuestra nas, con clave "clave_de_la_BBDD" en todas la tablas de la  BBDD "eventos_server"
Código:
GRANT ALL PRIVILEGES ON eventos_servidor.* TO administrador@'ip_local_de_nuestra_nas' IDENTIFIED BY 'clave_de_la_BBDD' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;

Ahora nos identificamos como ese usuario "administrador" en la mariaDB:
Código:
USE administrador;

Y ahora creamos la tabla "items_alterados"y sus campos:
Código:
CREATE TABLE items_alterados (id INT NOT NULL AUTO_INCREMENT, servidor VARCHAR(100), archivo VARCHAR(255), fecha  DATETIME, usuario VARCHAR(100), accion VARCHAR(20), , tipo VARCHAR(20), PRIMARY KEY (ID));
Los campos de la tabla son : ID, servidor, archivo, fecha, usuario y acción .

Si todo ha ido bien tendremos en nuestra mariaDB un usuario con accesos a la BBDD, una tabla en su interior y los campos antes mencionados.

2- trabajo en el servidor

Creamos una política local en el servidor para que se registren los cambios.
   

En el servidor de Windows hemos de instalar el conector adecuado para que sepa comunicarse con la mariaDB. En el momento que lo hice era el "mysql-connector-net-8.2.0.msi", pero muy posible que haya nuevas versiones del mismo.

Ahora en la carpeta compartida hemos de auditar esos accesos. Vamos a la carpeta, hacemos clic con el botón secundario, pedimos propiedades y pulsamos sobre la lengüeta de "Seguridad", después pulsamos sobre el botón inferior de "opciones avanzadas". Seleccionamos la lengüeta de "Auditoria" y pulsamos sobre el botón de "Agregar".
   

Luego seleccionamos la entidad
   

podemos todos
   

Y ahora pulsamos sobre "mostrar permisos avanzados"
   

Aquí elegimos los permisos que nos interesan que son los de creación y eliminación.
   

Si agregamos muchos o innecesarios, el sistema trabaja mas y el log del visor de eventos aumenta mucho.
Dependiendo de nuestra actividad podríamos tener que aumentar el tamaño del archivo del visor de eventos (yo recomiendo tenerlo ciclíco).

3-Scrip de transferencia de datos a la NAS

Ahora sólo queda crear un script en PowerShell que mande los registros que nos interesan a la nas.
El archivo ha de tener extensión .ps1 y un contenido similar a el siguiente:
Código:
#Add-Type -Path 'C:\Program Files (x86)\MySQL\MySQL Connector NET 8.2.0\MySql.Data.dll'
[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")
$Connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString='server=ip_local_de_la_nas;port=3306;uid=administrador;pwd=clave_de_la_BBDD;database=eventos_servidor'}
$Connection.Open()
$sql = New-Object MySql.Data.MySqlClient.MySqlCommand
$sql.Connection = $Connection
$contador = 0

#Obtengo limite de las 3 horas anteriores 3, 6, 9, 12, 15, 18, 21 y 24
$Date = Get-Date
#$Date = Get-Date -Year 2023 -Month 11 -Day 02 -Hour 07 -Minute 05 -Second 00 -format "yyyy-MM-dd HH:mm:ss"
$dia = $Date.day -as [int]
$mes = $Date.Month -as [int]
$anoini = $Date.Year -as [int]
$mesini = $Date.Month -as [int]
$diaini = $Date.Day -as [int]
$mesfin = $mesini
$diafin = $diaini
$anofin = $anoini

if (( $Date.hour -ge "6" ) -and  ($Date.hour -lt "9") ){
    write-host "estamos entre 6 y 9, transmito datos entre 3 y 6"
    $mensaje = "estamos entre 6 y 9, transmito datos entre 3 y 6."
    $horaini = "03"
    $horafin = "05"
    }
elseif (( $Date.Hour -ge "9" ) -and  ($Date.hour -lt "12") ){
    write-host "estamos entre 9 y 12, transmito datos entre 6 y 9"
    $mensaje = "estamos entre 9 y 12, transmito los datos entre 6 y 9."
    $horaini = "06"
    $horafin = "08"
    }
elseif (( $Date.Hour -ge "12" ) -and  ($Date.hour -lt "15") ){
    write-host "estamos entre 12 y 15, transmito datos entre 9 y 12"
    $mensaje = "estamos entre 12 y 15, transmito los datos entre 9 y 12."
    $horaini = "09"
    $horafin = "11"
    }
elseif (( $Date.Hour -ge "15" ) -and  ($Date.hour -lt "18") ){
    write-host "estamos entre 15 y 18, transmito datos entre 12 y 15"
    $mensaje = "estamos entre 15 y 18, transmito los datos entre 12 y 15."
    $horaini = "12"
    $horafin = "14"
    }    
elseif (( $Date.hour -ge "18" ) -and  ($Date.hour -lt "21") ){
    write-host "estamos entre 18 y 21, transmito datos entre 15 y 18"
    $mensaje = "estamos entre 18 y 21, transmito los datos entre 15 y 18."
    $horaini = "15"
    $horafin = "17"
    }
elseif (( $Date.hour -ge "21" ) -and  ($Date.hour -le "23") ){
    write-host "estamos entre 21 y 24, transmito datos entre 18 y 21"
    $mensaje = "estamos entre 21 y 24, transmito los datos entre 18 y 21."
    $horaini = "18"
    $horafin = "20"
    }
elseif (( $Date.hour -ge "3" ) -and  ($Date.hour -lt "6") ){
    write-host "estamos entre 3 y 6, transmito datos entre 0 y 3"
    $mensaje = "estamos entre 3 y 6, transmito los datos entre 0 y 3."
    $horaini = "00"
    $horafin = "5"
    }
else {
    write-host "estamos entre 0 y 3, trasnmito datos entre 21 y 24"
    $mensaje = "estamos entre 0 y 3, trasnmito los datos entre 21 y 24."
    $horaini = "21"
    $horafin = "23"
    #compruebo si es dia 1 de enero, entonces he de trabajar con en el dia anterior que es el 31 de diciembre del año anterior
    if ( $dia -eq 1 -and $mes -eq 1){
        write-host "dia primero del anyo"
        $dia
        $mes
        $mensaje = "estamos entre 0 y 3 primer dia del año."
        $anoini = (Get-Date).AddMonths(-1).AddMonths(1).AddDays(-1).ToString("yyyy")
        $mesini = (Get-Date).AddMonths(-1).AddMonths(1).AddDays(-1).ToString("MM")
        $diaini = (Get-Date).AddMonths(-1).AddMonths(1).AddDays(-1).ToString("dd")
        $anofin = $anoini
        $mesfin = $mesini
        $diafin = $diaini
        }
    #compruebo si es dia 1 pero NO de enero y he de trabajar con el dia último del mes anterior
    elseif ( $dia -eq 1 -and $mes -ne 1) {
        write-host "dia primero del mes no de enero"
        $mensaje = "estamos entre 0 y 3 primer dia del mes que no es enero."
        $dia
        $mes
        $mesini = (Get-Date).AddMonths(-1).AddMonths(1).AddDays(-1).ToString("MM")
        $diaini = (Get-Date).AddMonths(-1).AddMonths(1).AddDays(-1).ToString("dd")
        $anofin = $anoini
        $mesfin = $mesini
        $diafin = $diaini
        }
    else {
        write-host "cualquier dia distinto del primero de mes"
        $mensaje = "estamos entre 0 y 3 de cualquier dia NO 1 del mes."
        $dia
        $mes
        $diaini = $diaini = (Get-Date).AddDays(-1).ToString("dd")
        $anofin = $anoini
        $mesfin = $mesini
        $diafin = $diaini
        $anoini
        $mesini
        $diaini
        }
    }
#defino las fechas de trabajo
$Fini = Get-Date -Year $anoini -Month $mesini -Day $diaini -Hour $Horaini -Minute 00 -Second 00 -format "yyyy-MM-dd HH:mm:ss"
$Ffin = Get-Date -Year $anofin -Month $mesfin -Day $diafin -Hour $Horafin -Minute 59 -Second 59 -format "yyyy-MM-dd HH:mm:ss"

#proceso de enviar todos los datos del visor de eventos entre los rangos de fechas anteriores
$Eventos = 0
Get-WinEvent -Oldest -FilterHashTable @{LogName="Security";starttime=$Fini;endtime=$Ffin;id=4659,4663}| Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$contador = $contador + 1
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$File = $event.Event.EventData.Data[6]."#text"
$archivo = $File
$File = $File.Replace("\","/")
$User = $event.Event.EventData.Data[1]."#text"
$id = $_.id
if ( $id -match "4659" ) {
    $Accion = "Borrado"
    #$Accion = $event.Event.EventData.Data[10]."#text"
    }
if ( $id -match "4663" ) {
    $Accion = $event.Event.EventData.Data[9]."#text"
    if ( $Accion -match "0x10000" ) {
        $Accion = "Renombrado"
    }
    if ( $Accion -match "0x2" ) {
        $Accion = "Creado o modificado"
    }
    if ( $Accion -match "0x4" ) {
        $Accion = "otro"
    }
    if ( $Accion -match "0x6" ) {
        $Accion = "Agregando datos"
    }
    }
$Computer = $event.Event.System.computer
$sql.CommandText = "INSERT INTO deleted_items (servidor,archivo,fecha,usuario,accion,tipo) VALUES ('$Computer','$File','$Time','$User','$Accion','$id')"
$Eventos = $Eventos + 1
$sql.ExecuteNonQuery()
}
}
$Reader.Close()
$Connection.Close()
$Eventos
Write-host "Total de Eventos $Eventos"
$mensaje = $mensaje + " Numero de eventos = " + $Eventos
#Se puede enviar la cadena $mensaje en un correo o incluso Telegram

Lo he comentado bastante pero la idea es ejecutarlo cada tres horas (podemos modificarlo para hacerlo con periodos mas cortos o largos).
La idea es ejecutarlo sobre las 00:10, 3:10, 6:10, ... cada tres horas para que envíe los datos relativos a las tres horas anteriores.
Es decir si lo ejecuto a las 6:10, transmite los eventos entre las 3:00 y las 5:59.
La gracia del script es cuando se lanza a las 0:10, que ha calcular el rango del día anterior entre las 21:00 y  23:59.
Y se complica un poco cuando estamos a día uno del mes (no se ve afectado por bisiestos) y caso especial de día uno de enero que además de ir al último día del mes anterior ha de ir al año anterior :-O

En el programador de tareas del servidor se ejecuta C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe y con parámetros -command "C:\ruta del archivo en el servidor\nombre_del_script.ps1"

El script puede completarse con mas comandos para que nos envíe un correo electrónico con el número de registros, y/o que nos lo envíe por Telegram.

4-Explotación de datos

Si queremos revisar los datos podemos hacerlo vía phpMyAdmin, la base de datos de Libreoffice, clientes hechos con MSAccess, PowerBi o incluso con scripts hechos en PowerShell.

Yo lo he puesto en practica con un servidor de dominio, pero al ser una política local, podemos hacerlo con nuestros equipos Smile

Se que este post se sale un poco de la norma, pero a fin de cuentas no deja de ser algo mas que podemos gestionar en nuestra Qnap y espero que os sirve para ver como las nas de Qnap son un buen complemento para otras cosas  Smile