Monday, December 28, 2009

Mi primer script en powershell


Bueno, primer post después de un mes y medio de inactividad. Para volver a escribir voy a comenzar con algo que tiene que ver con la seguridad en forma tangencial.

Uno de los trabajos que realice tiempo atras fue el envio del backup diario de una base de datos SqlServer hacia un idrive que provee Iplan.

De esta manera, todas las noches se realiza el backup de la base de datos y unos minutos mas tarde, se dispara una tarea programada que ejecuta un script en powershell, el cual comprime y encripta el backup del dia, realiza un ftp hacia el idrive y luego borra el backup del mismo dia de la semana anterior.

Luego del ftp, el script envia un mail con el log del proceso de transferencia.

Dado que el idrive no cuenta con mucho espacio, se mantiene solo una semana.

Desde el punto de vista de la seguridad, esta no es una solucion óptima, ya que utiliza un medio publico y con la password en claro para la transferencia.
La encripcion del archivo transmitido mediante AES256 actua como una mitigacion del riesgo en caso que se obtenga el usuario/password de transmision del archivo.


Las personas que pidieron esto midieron los riesgos y encontraron la solucion aceptable.


La tarea desde la que se ejecuta el script :

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "& {E:\BACKUP\putftp.ps1}"


El script :

# Script que comprime y envia mediante ftp un backup de SQL Server al server destino
# luego borra el backup de la semana anterior.
# Por ultimo envia un email con el log del ftp realizado
#
# J.J 01/10/09

#
# Esta funcion envia el mail con el log del ftp adjunto.
#
# $filename : Archivo que se adjuntara
# $msg.From : Remitente
# $msg.To.Add : Destinatario
# $msg.Body : Texto del mail
# $smtpserver : Direccion smtp server
# $msg.Subject : Encabezado del mail, en este caso el texto indica la fecha del backup
#
function smtp-status{

$filename = "backup.log"
$smtpserver = "XXX.XXX.XXX.XXX"
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($filename)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "backup@xxxxxxxx.com.ar"
$msg.To.Add("jaime.julio.a@gmail.com")
$msg.Body = "El log del backup se encuentra adjunto "
$msg.Attachments.Add($att)
$msg.Subject = "Backup Iplan " + $today
$smtp.Send($msg);

}


# Borramos el archivo de log del backup anterior y creamos un nuevo archivo de logs
# De otra manera el log del backup se incrementara.

Remove-Item backup.log
New-Item backup.log -type file -force

# Calculamos la fecha del backup realizado 7 dias atras y damos el formato de nombre
# Se utilizara como parametro para borrar el backup de la semana anterior

$lastday = get-date -uformat "%Y/%m/%d" ((get-date).adddays(-7))
$lastday = $lastday -replace "/",""
$lastday = "cur_db_"+$lastday+"2000.BAK"

# Calculamos la fecha del dia
# Se utilizara como parametro para comprimir el archivo del backup del dia.


$today = get-date -uformat "%Y/%m/%d" ((get-date).adddays(0))
$today = $today -replace "/",""
$today = "cur_db_"+$today+"2000.BAK"

# Buscamos en el directorio de backup todos los archivos de backup

$backFiles = Get-ChildItem "e:\Microsoft SQL Server\MSSQL\BACKUP\*.*" -Include *.BAK

# Realizamos una busqueda hasta encontrar el backup del dia
# Luego utilizamos el programa 7z.exe para comprimirlo encriptado y ponerle la extension #.7z

foreach ($backFile in $backFiles)
{
if ( $backfile.fullname -match $today )
{
& ./7z.exe a -mhe=on -ppasswordencriptcion -sfx7z.sfx ($backFile.FullName + ".7z") $backFile.FullName
}
}

#
# Ejecutamos el programa winscp.exe y pasamos como parametros el archivo de log,
# el archivo de script y las fechas de los backups a transmitir
#


& ./winscp.exe /console /log='backup.log' /script=scriptftp.txt /parameter $today".7z" $lastday".7z" -eq 1

#
# Dado que el proceso del winscp se ejecuta y el script continua al siguiente
# paso, debemos esperar a que termine para enviar el mail con el log
# Por lo tanto asignamos a una variable el numero de proceso del winscp y esperamos
# que termine para continuar.

$np = get-process winscp
$np.waitforexit()

# Ejecutamos la funcion que envia el mail con el log.

smtp-status;



El script que ejecuta el Winscp es el siguiente :

option batch on
option confirm off
open ftp://user:password@infosegura.iplanisp.com.ar -passive
option transfer binary
put %1%
rm %2%
close
exit



Donde %1% y %2% corresponden a los parametros que tienen los nombres de archivos a transmitir y el archivo a borrar.

Por ultimo el log del ftp es el siguiente :

. 2009-12-25 21:08:05.175 --------------------------------------------------------------------------
. 2009-12-25 21:08:05.175 WinSCP Version 4.2.4 (Build 610) (OS 5.2.3790 Service Pack 2)
. 2009-12-25 21:08:05.175 Login time: Viernes, 25 de Diciembre de 2009 09:08:05 p.m.
. 2009-12-25 21:08:05.175 --------------------------------------------------------------------------
. 2009-12-25 21:08:05.175 Session name: 1
. 2009-12-25 21:08:05.175 Host name: 1 (Port: 22)
. 2009-12-25 21:08:05.175 User name: (Password: No, Key file: No)
. 2009-12-25 21:08:05.175 Tunnel: No
. 2009-12-25 21:08:05.175 Transfer Protocol: SFTP (SCP)
. 2009-12-25 21:08:05.175 Ping type: -, Ping interval: 30 sec; Timeout: 15 sec
. 2009-12-25 21:08:05.175 Proxy: none
. 2009-12-25 21:08:05.175 SSH protocol version: 2; Compression: No
. 2009-12-25 21:08:05.175 Bypass authentication: No
. 2009-12-25 21:08:05.175 Try agent: Yes; Agent forwarding: No; TIS/CryptoCard: No; KI: Yes; GSSAPI: No
. 2009-12-25 21:08:05.175 Ciphers: aes,blowfish,3des,WARN,arcfour,des; Ssh2DES: No
. 2009-12-25 21:08:05.175 SSH Bugs: -,-,-,-,-,-,-,-,-
. 2009-12-25 21:08:05.175 SFTP Bugs: -,-
. 2009-12-25 21:08:05.175 Return code variable: Autodetect; Lookup user groups: Yes
. 2009-12-25 21:08:05.175 Shell: default, EOL: 0
. 2009-12-25 21:08:05.175 Clear aliases: Yes, Unset nat.vars: Yes, Resolve symlinks: Yes
. 2009-12-25 21:08:05.175 LS: ls -la, Ign LS warn: Yes, Scp1 Comp: No
. 2009-12-25 21:08:05.175 Local directory: default, Remote directory: home, Update: No, Cache: Yes
. 2009-12-25 21:08:05.175 Cache directory changes: Yes, Permanent: Yes
. 2009-12-25 21:08:05.175 DST mode: 1
. 2009-12-25 21:08:26.316 --------------------------------------------------------------------------
. 2009-12-25 21:08:26.331 Connecting to infosegura.iplanisp.com.ar ...
. 2009-12-25 21:08:26.410 Connected with infosegura.iplanisp.com.ar. Waiting for welcome message...
<> 2009-12-25 21:08:26.410 USER usuario
<> 2009-12-25 21:08:26.410 PASS ********
<> 2009-12-25 21:08:26.753 SYST
<> 2009-12-25 21:08:26.753 FEAT
<> 2009-12-25 21:08:26.753 PWD
<> 2009-12-25 21:08:26.769 TYPE A
<> 2009-12-25 21:08:26.769 PASV
<> 2009-12-25 21:08:26.769 LIST
<> 2009-12-25 21:08:26.972 TYPE I
<> 2009-12-25 21:08:26.972 PASV
<> 2009-12-25 21:08:26.972 STOR cur_db_200912252000.BAK.7z
<> 2009-12-25 21:12:05.317 DELE /cur_db_200912182000.BAK.7z


Consideraciones finales

Debemos instalar Winscp para el ftp y 7z para la compresion.

El script quedaría mucho mas limpio si utilizaramos funciones de ftp propias de powershell, pero tuve problemas entre el cliente y el server y las transmisiones nunca finalizaban.
Entre los puntos a mejorar, se encuentra el envio mediante SCP con autentificacion mediante certificados, este ultimo punto dependera del proveedor del idrive.

Como comente anteriormente, este es mi primer script en powershell, no soy un programador y seguramente hay detalles a mejorar ( por ejemplo: uso de variables globales ).

No comments: