Introducción

El agente de control (A86) tiene como finalidad controlar y automatizar tareas con computadores personales de la familia x86 de manera remota de manera segura. En particular, si se trata de la PC de un ATM, se puede utilizar para extraer archivos de log de journals de éstos, así como realizar el envío de archivos de imágenes de pantallas hacia éstos.

En general puede transferir cualquier archivo en ambos sentidos así como ejecutar comandos remotos (por ejemplo, para reiniciar el equipo.)

El agente es una aplicación muy ligera que se ejecuta en la PC (Windows o Linux.) Su contraparte es el "Switch de Agentes" en un servidor POSIX (por ejemplo, en Linux.)

Revisiones

  • 1.0 2013-09-09 Primera versión piloto

  • 1.1 2014-09-12 Corrección de erratas

Comunicación y encriptación

El agente inicia una conexión TCP hacia el puerto especificado en la línea de comandos.

Una vez establecida esta comunicación con el Switch de Agentes (que espera conexiones en dicho puerto), se procede a un proceso de autenticación.

De no establecerse la conexión, o de fallar la autenticación, el agente reintenta conectarse cada minuto.

La comunicación se realiza mediante paquetes TCP con dos bytes de header para delimitar la longitud de los mismos. El contenido viaja encriptado mediante Triple DES.

La llave compartida en el agente se almacena en un archivo de texto cifrada bajo una llave local.

Por omisión, el agente se inicia con una llave prefijada. Por seguridad, a la primera oportunidad las llaves deben ser regeneradas por el operador desde la consola (ver comando resetkeys.)

Ciclo de vida del agente

flujo auxiliar

Switch de Agentes

Es un programa que actua como servidor TCP, esperando a la conexión de los agentes.

Cuando llega una conexión de un Agente al Switch de Agentes, este último valida la dirección de origen de la conxión la cual debe estar prefijada en la configuración del mismo (archivo de texto de configuración.) Tras la conexión sigue un proceso de autenticación donde se valida esencialmente que el agente y el Switch de Agentes tengan la misma llave de seguridad compartida.

Una vez autenticado, el agente está listo para recibir comandos.

Los comandos se inician desde el Switch de Agentes y se dirigen hacia el agente (el cual debe responder.) Nunca en sentido inverso.

El Switch envía comandos al agente a solicitud de una consola de agentes. Las consolas de agentes se deben conectar a un puerto preestablecido en el que escucha el Switch de Agentes.

Arquitectura

Consola de agentes

Es un programa que se puede ejecutar en múltiples instancias, el cual se conecta al Switch de Agentes a fin de enviar comandos dirigidos a los agentes (y en algunos casos al mismo Switch de Agentes.)

Este programa debe ser ejecutado en un ambiente seguro. Por omisión el Switch sólo acepta conexiones de consola provenientes de "localhost".

Selección de agente

Una consola de agentes debe "seleccionar" un agente específico al cuál enviarle comandos (comando sel.) Dos consolas no pueden tener seleccionado a un mismo agente simultáneamente (el Switch de agentes no lo permitirá.)

La consola puede usarse de modo interactivo o en modo batch. En el segundo caso, se debe proporcionar un "script de consola" que contiene los mismos comandos que normalmente se emplean para el modo interactivo.

Por omisión, en modo "batch", la ejecución se cancela al primer error en los comandos ejecutados. Por ejemplo, no tiene caso seguir enviando comandos si la selección de un agente falla al inicio del script.

Comandos de la consola

La consola sólo opera cuando está conectada al "Switch de Agentes".

La consola envía comandos hacia el Switch de Agentes los cuales están dirigidos en su mayoría a los agentes, pero algunos están dirigidos exclusivamente al Switch de Agentes. Otros comandos auxiliares son internos a la consola.

Comandos internos de la consola

Obtención de ayuda: help

Este comando se emplea en modo interactivo para solicitar un listado de comandos disponibles. Cuando se ha seleccionado un agente exitosamente, los comandos disponibles se incrementan.

$ run-consola.sh
Bienvenido a A86-CON V8/9/13, tipear '?' para ayuda.
( )> help
[q]uit:                        terminar la consola
[l]ista [-ncu][KEY=VAL...]:    listar de base de datos de agentes
	-n: solo mostrar el ID de los agentes
	-c: solo conectados
	-u: solo desconectados
	KEY=VAL: filtrar por atributos (* en VAL es comodin)
lpwd:                          ver directorio local
ldir:                          listar directorio local
lcd <ruta>:                    cambiar directorio local
echo [texto]:                  mostrar en pantalla
for <var> [val...]:            loop sobre valores val asignados a var
done:                          cierre de for
[d]esconectar <id>:            desconectar agente del switch
reconfig:                      recargar la configuracion
let NOMBRE=TEXTO:              definir variable; obtener con ${NOMBRE}
decode X with val k1 v1...     asigna a X el primer vi tal que ki=val
on error <stop|continue>       en scripts que hacer cuando hay error
[s]el <term>:                  seleccionar agente

Salir de la consola: quit

Esto termina el proceso de la consola, lo cual se reporta en el log del Switch de Agentes.

En los scripts de consola, el fin de archivo tiene el mismo efecto.

Mostrar directorio de trabajo local: lpwd

Permite establecer el directorio de trabajo (working directory) del proceso de consola. Esto es útil cuando se desea transfererir archivos sin especificar sus rutas absolutas. Para cambiar el directorio de trabajo local, se debe usar lcd.

Cambiar el directorio de trabajo local: lcd

Permite modificar el directorio de trabajo del proceso de consola.

Listar directorio local: ldir

Permite mostrar el contenido del directorio de trabajo del proceso de consola. Otra forma obviamente consiste en ingresar al sistema desde otro terminal para ejecutar un comando del sistema operativo.

Emitir un mensaje: echo

Envia un texto a la salida estandar. Util para scripts de consola. Análogo al comando "echo" del sistema operativo.

Repetir un grupo de comandos: for...done

Permite repetir un conjunto de comandos en scripts de consola. Debe proporcionarse el nombre de una variable, y una lista de valores que ésta tomará.

Por ejemplo:

for K v1 v2 v3
echo repeticion: ${K}
done

Genera:

$ run-consola.sh prueba.a86
repeticion v1
repeticion v2
repeticion v3

Definir/modificar valor de una variable: let

Permite definir variables.

$ run-consola.sh
Bienvenido a A86-CON V8/9/13, tipear '?' para ayuda.
( )> let sodio=Na
( )> echo ${sodio}
Na

Decodificar a partir de un conjunto de valores: decode

Esto está inspirado en la función Oracle SQL DECODE. Por ejemplo:

let A=840
decode DESC with ${A} 604 Soles 840 Dolares Desconocido
echo Codigo ${A} es ${DESC}
let A=604
decode DESC with ${A} 604 Soles 840 Dolares Desconocido
echo Codigo ${A} es ${DESC}
let A=555
decode DESC with ${A} 604 Soles 840 Dolares Desconocido
echo Codigo ${A} es ${DESC}

Genera:

$ run-consola.sh deco.a86
Codigo 840 es Dolares
Codigo 604 es Soles
Codigo 555 es Desconocido

Accion en caso de error: on error

Está referido a scripts de consola. Determina la acción a tomar cuando un comando "falla" (por ejemplo, cuando no se puede realizar una transferencia de archivos.) Por omisión, el script termina (on error stop), pero se puede alterar este comportamiento con on error continue.

Comandos destinados al Switch de Agentes

Desconectar un agente: desconectar

Fuerza al Switch de Agentes a desconectar forzosamente al agente en cuestión. Esto puede ser utilizado como último recurso cuando no es posible ganar acceso al agente.

Recargar base de datos de agentes: reconfig

Indica al Switch de Agentes que debe recargar la configuración de la base de datos configurada.

Seleccionar terminal: sel

Indica al Switch de Agentes que la consola desea tomar el control de un agente (para enviarle comandos.) Sólo una consola puede tomar el control de un agente a la vez (el Switch de Agentes valida esta condición.)

Si por algún motivo es impresindible tomar el control de un agente controlado por otra consola, y aquella consola no puede ser cancelada, es posible ganar el control forzando una desconexión (desconectar.)

De-seleccionar terminal: unsel

Anula la selección del agente actual. Útil si se desea que otra consola tenga la capacidad de seleccionar el mismo agente.

Esto ocurre automáticamente cuando se termina la consola o cuando se selecciona un nuevo agente.

Listar terminales list

También puede ser invocado como l o ls. Permite listar los agentes configurados en el Switch de Agentes, así como el estado de los mismos.

Puede emplearse el '*' como comodín (análogo al shell del sistema operativo.)

También se puede filtrar mediante la sintaxis KEY=VAL.

Asimismo, es posible especificar el ID de un terminal o de un grupo (mediante el comodín) directamente:

l ATM3*

Como puede verse en la ayuda, se disponde las opciones -n para mostrar sólo el ID de los agentes (esto es útil especialmente en los scripts para obtener listas según criterios), -c para mostrar sólo aquellos que están conectados, y -u para mostrar sólo aquellos que no están conectados.

Comandos destinados a los agentes

Mostrar directorio de trabajo del agente: pwd

Permite mostrar el directorio de trabajo del proceso con que se ejecuta el agente en el sistema operativo del terminal. Útil para transferir archivos sin especificar rutas.

Cambio de directorio de trabajo del agente: cd

Permite cambiar el directorio de trabajo del proceso con que se ejecuta el agente en el sistema operativo del terminal.

Listado de directorio de trabajo del agente: dir

Permite obtener un listado del directorio de trabajo del proceso con que se ejecuta el agente en el sistema operativo del terminal.

Ejecución de un comando remoto en el agente: !

Permite ejecutar un comando en el sistema operativo del agente. Este comando debe terminar en a lo mucho 60 segundos o será automáticamente detenido.

La salida estándar del comando es mostrada en la consola como resultado.

Ejemplo:

(ATM2)> !dir
 El volumen de la unidad C no tiene etiqueta.
 El numero de serie del volumen es: F062-7D6B

 Directorio de C:\CHRIS\CLIENTE

04/09/2013  02:33 p.m.    <DIR>          .
04/09/2013  02:33 p.m.    <DIR>          ..
07/08/2013  06:43 p.m.               104 a86.cfg
09/09/2013  03:36 p.m.            39,084 a86.log
07/08/2013  10:49 p.m.            78,848 agente.exe
08/09/2013  05:36 p.m.    <DIR>          borrar
07/08/2013  11:07 p.m.         1,164,288 prueba.tar
               4 archivos      1,361,172 bytes
               3 dirs  10,889,089,024 bytes libres

Truncar log remoto de agente: resetlog

Trunca el archivo log. El contenido actual se pierde si no es previamente salvado mediante una copia o una transferencia.

Resetear llaves de agente: resetkeys

Mediante este comando se genera un conjunto de llaves aleatório el cual es enviado al agente para su respectivo registro. De inmediato el agente se desconecta, y posteriormente se vuelve a intentar reconectar con las nuevas llaves.

Como procedimiento, esto deberá hacerse siempre para cada agente tras su instalación, dado que por omisión todos utilizan una llave "default" que puede ser riesgosa.

El Switch de Agentes sobre-escribe la base de datos tras este comando (si es exitoso.) Cualquier cambio que se hubiera hecho en la base de datos y que no esté presente en la memoria del Switch de Agentes es destruido.

Traer un archivo desde el agente: get

Permite traer un archivo especificando su nombre hacia el directorio en que se ejecuta la consola. Permite además especificar un nombre alternativo para la versión local (esto es opcional.)

Traer un conjunto de archivos desde el agente: mget

Análogo a get pero permite especificar un patrón de archivos usando el '*' como comodín, similar al caso de FTP.

El comando smget es una variante que sólo trae archivos que no existen en el directorio local.

Al respecto, si se define la variable A86_FILE_INDEX igual a un conjunto de archivos separados por comas, dichos archivos son "obviados" durante la transferencia.

Si dicha variable tiene un valor de la forma @texto, entonces texto debe corresponder a un archivo de texto cuyas líneas corresponden a los archivos que son obviados durante la transferencia. Adicionalmente, la consola sobreescribirá este mismo archivo "índice" con una nueva lista que contiene:

I(nuevo) = ( I(actual) interseccion Lista(remoto) ) union Lista(transferidos)

Esto permite mantener el archivo índice actualizado con el fin de transferir regularmente sólo aquellos archivos que no han sido previamente transferidos.

Llevar un archivo hacia el agente: put

Permite enviar un archivo especificando su nombre desde el directorio en que se ejecuta la consola hacia el directorio en que se ejecuta el proceso del agente. Permite además especificar un nombre alternativo para la versión remota (esto es opcional.)

Llevar un conjunto de archivos hacia el agente: mput

Análogo a put pero permite especificar un patrón de archivos usando el '*' como comodín, similar al caso de FTP.

El comando smput es una variante que sólo lleva archivos que no existen en el directorio remoto.

Base de datos de agentes

Corresponde a un archivo de texto con campos delimitados por comas. Sus campos son ID,KEY,HOSTNAME/IP, y otros a criterio del implementador.

El campo ID es la identificación única de cada terminal/agente. Es un texto simple, normalmente en mayúsculas (no se diferencia el case.)

El campo KEY es la llave para comunicaciones entre el Switch de agentes y cada agente. Corresponde a 24 bytes (48 caracteres hexadecimales) los cuales a su vez comprenden dos llaves K1 y K2, y un vector de inicialización IV, todos de 8 bytes (8x3=24.)

El campo HOSTNAME o IP es la identificación del terminal donde se ejecuta el agente. Cuando se trata de HOSTNAME, los terminales deben poderse resolver inversamente por el "resolver" (/etc/hosts o DNS.) Si esto no es posible, debe emplearse la identificación por dirección IP.

Los campos de la base de datos se deben especificar al momento de arranque del Switch de Agentes, por ejemplo:

export CLASSPATH=...
java com.americati.a86.sw.A86Switch terminales 22000 21000 \
	ID,SKEY,HOSTNAME,PORT,UBIC,MARCA,MODELO,INST,DIRP,DIRJ \
	$RUTA/database HOSTNAME

Si se va a emplear identificación por nombre de host, los campos deben iniciarse con ID,SKEY,HOSTNAME, y el último argumento debe ser HOSTNAME. Si la identificación es por dirección IP, los campos deben iniciarse con ID,SKEY,IP y el último argumento debe ser IPADDR.

El primer argumento de la línea de comandos del Switch de Agentes corresponde al archivo de base de datos. El penúltimo es el directorio donde se ubica dicha base de datos.

En la base de datos a partir del cuarto campo se tiene datos opcionales para cada terminal. Por ejemplo, PORT se emplea de modo informativo para indicar a qué puerto se conectan los terminales en el Switch de Agentes (es siempre el mismo.) Otros campos son útiles en la programación de los scripts de terminales.

Tomar en cuenta que el comando de consola reconfig permite indicar al Switch de Agentes que debe recargar su configuración (sin necesidad de reiniciarlo.)

Los agentes que están en memoria y que son eliminados de la base de datos, se mantienen en memoria hasta que el Switch de Agentes es terminado.

Todos los valores de los campos de un terminal seleccionado están disponibles como variables para consola de agentes.