From 5f7ca5be15899116b71dfd41707a45284e2af24e Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 26 Jul 2024 10:45:02 +0200 Subject: [PATCH] refs #524 implement autoexecCliente() and its companion ejecutaArchivo() --- .../server/ogAdmClient/__init__.py | 160 ++++++++++++++---- 1 file changed, 130 insertions(+), 30 deletions(-) diff --git a/src/test_modules/server/ogAdmClient/__init__.py b/src/test_modules/server/ogAdmClient/__init__.py index 0d34e67..8a9021c 100644 --- a/src/test_modules/server/ogAdmClient/__init__.py +++ b/src/test_modules/server/ogAdmClient/__init__.py @@ -73,25 +73,6 @@ def check_secret(fnc): return wrapper -def interfaceAdmin (exe, parametros=[]): - devel_bash_prefix = ''' - PATH=/opt/opengnsys/scripts/:$PATH; - for I in /opt/opengnsys/lib/engine/bin/*.lib; do source $I; done; - for i in $(declare -F |cut -f3 -d" "); do export -f $i; done; - ''' - if 'nati' == os.environ['USER'] or 'nati' == os.environ['SUDO_USER']: ## DO NOT COMMIT - devel_bash_prefix = ''' - PATH=/home/nati/Downloads/work/opengnsys/opengnsys/client/shared/scripts:$PATH; - for I in /home/nati/Downloads/work/opengnsys/opengnsys/client/engine/*.lib; do source $I; done; - for i in $(declare -F |cut -f3 -d" "); do export -f $i; done; - ''' - if parametros: - proc = ['bash', '-c', '{} {} {}'.format (devel_bash_prefix, exe, ' '.join (parametros))] - else: - proc = ['bash', '-c', '{} {}'.format (devel_bash_prefix, exe)] - logger.debug ('subprocess.run ("{}", capture_output=True)'.format (proc)) - return subprocess.run (proc, capture_output=True).stdout.strip().decode ('utf-8') - class ogAdmClientWorker(ServerWorker): name = 'ogAdmClient' # Module name interface = None # Bound interface for OpenGnsys @@ -122,8 +103,8 @@ class ogAdmClientWorker(ServerWorker): #servidorAdm = self.service.config.get('ogAdmClient', 'servidorAdm') #puerto = self.service.config.get('ogAdmClient', 'puerto') self.pathinterface = self.service.config.get('ogAdmClient', 'pathinterface') - urlMenu = self.service.config.get('ogAdmClient', 'urlMenu') - urlMsg = self.service.config.get('ogAdmClient', 'urlMsg') + #urlMenu = self.service.config.get('ogAdmClient', 'urlMenu') + #urlMsg = self.service.config.get('ogAdmClient', 'urlMsg') logger.setLevel(loglevel) except NoOptionError as e: logger.error("Configuration error: {}".format(e)) @@ -170,9 +151,24 @@ class ogAdmClientWorker(ServerWorker): if (not self.tomaIPlocal()): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') + logger.info ('Inicio de sesion') + logger.info ('Abriendo sesión en el servidor de Administración') if (not self.inclusionCliente()): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') + logger.info ('Cliente iniciado') + logger.info ('Procesando caché') + if (not self.cuestionCache()): + raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') + + if (self.idproautoexec > 0): + logger.info ('Ejecución de archivo Autoexec') + if (not self.autoexecCliente()): + raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') + + #logger.info ('Procesa comandos pendientes') + #logger.info ('Acciones pendientes procesadas') + def onDeactivation(self): """ Sends OGAgent stopping notification to OpenGnsys server @@ -303,7 +299,11 @@ with open (subprocs_log, 'ab') as fd: ## TODO improve this logging @check_secret def process_popup(self, path, get_params, post_params, server): - logger.warn('in process_popup, should not happen') + logger.debug('in process_popup, path "{}" get_params "{}" post_params "{}" server "{}"'.format(path, get_params, post_params, server)) + logger.debug('type(post_params) "{}"'.format(type(post_params))) + ## in process_popup, should not happen, path "[]" get_params "{}" post_params "{'title': 'mi titulo', 'message': 'mi mensaje'}" server "" + ## type(post_params) "" + return {'debug':'test'} #def process_client_popup(self, params): # logger.warn('in process_client_popup') @@ -313,11 +313,23 @@ with open (subprocs_log, 'ab') as fd: ## TODO improve this logging ## process_client_* are invoked from opengnsys/service.py:123 "v.processClientMessage(message, json.loads(data))" (via opengnsys/workers/server_worker.py) + def interfaceAdmin (self, method, parametros=[]): + exe = '{}/{}'.format (self.pathinterface, method) + devel_bash_prefix = ''' + PATH=/opt/opengnsys/scripts/:$PATH; + for I in /opt/opengnsys/lib/engine/bin/*.lib; do source $I; done; + for i in $(declare -F |cut -f3 -d" "); do export -f $i; done; + ''' + if parametros: + proc = ['bash', '-c', '{} {} {}'.format (devel_bash_prefix, exe, ' '.join (parametros))] + else: + proc = ['bash', '-c', '{} {}'.format (devel_bash_prefix, exe)] + logger.debug ('subprocess.run ("{}", capture_output=True)'.format (proc)) + return subprocess.run (proc, capture_output=True).stdout.strip().decode ('utf-8') + def tomaIPlocal(self): - logger.debug (__name__) - interface = '{}/getIpAddress'.format (self.pathinterface) try: - self.IPlocal = interfaceAdmin (interface); + self.IPlocal = self.interfaceAdmin ('getIpAddress'); logger.info (self.IPlocal) except Exception as e: logger.error (e) @@ -326,7 +338,7 @@ with open (subprocs_log, 'ab') as fd: ## TODO improve this logging return True def LeeConfiguracion(self): - parametroscfg = interfaceAdmin ('{}/getConfiguration'.format (self.pathinterface)) ## Configuración de los Sistemas Operativos del cliente + parametroscfg = self.interfaceAdmin ('getConfiguration') ## Configuración de los Sistemas Operativos del cliente logger.debug ('parametroscfg ({})'.format (parametroscfg)) return (parametroscfg) @@ -346,11 +358,64 @@ with open (subprocs_log, 'ab') as fd: ## TODO improve this logging return res + def ejecutaArchivo(self,fn): + logger.debug ('fn ({})'.format (fn)) + + ## TODO hay que entender este codigo (ogAdmClient.c:2111) para poder traducirlo a python + ## en una funcion "ejecutaArchivo" esperaba que se ejecutara un archivo, pero solo hay una llamada a gestionaTrama() que no sé dónde termina + #char* buffer,*lineas[MAXIMAS_LINEAS]; + #int i,numlin; + #char modulo[] = "ejecutaArchivo()"; + + #buffer = leeArchivo(filecmd); + #if (buffer): + # numlin = splitCadena(lineas, buffer, '@'); + # initParametros(ptrTrama,0); + # for (i = 0; i < numlin; i++) { + # if(strlen(lineas[i])>0){ + # strcpy(ptrTrama->parametros,lineas[i]); + # if(!gestionaTrama(ptrTrama)){ // Análisis de la trama + # errorLog(modulo,39,FALSE); + # //return(FALSE); + # } + # } + # } + #liberaMemoria(buffer); + + ## voy a probar algo, asumiendo que en el archivo no hay simplemente un bash, sino secuencias de parametros tal que "nfn=Funcion\rparam1=foo\rparam2=bar" + buffer = subprocess.run (['cat', fn], capture_output=True).stdout.strip().decode ('utf-8') + logger.debug ('buffer ({})'.format (buffer.replace('\r', '\\r'))) ## sustituimos \r para que el log tenga sentido + if buffer: + for l in buffer.split('@'): + if not len(l): continue + logger.debug ('line ({})'.format (l)) + ## en este punto, una opción sería pegar un curl a localhost, pero también podemos parsear los parámetros y llamar localmente a la función que sea: + post_params = {} + for param in l.split("\r"): + k, v = param.split('=') + post_params[k] = v + logger.debug ('post_params "{}"'.format (post_params)) + + func_name = post_params.pop ('nfn', None) + if func_name is None: + logger.error ('Ha ocurrido algún problema al procesar la trama recibida') + break + func = getattr (self, 'process_' + func_name) + ## func ya es una referencia a self.func, de modo que ahora no hay que hacer self.func(...) ni tampoco func(self, ...) + + logger.debug ('calling function "{}" with post_params "{}"'.format (func_name, post_params)) + output = func ([], {}, post_params, None) + logger.debug ('output "{}"'.format (output)) + if not output: + logger.error ('Ha ocurrido algún problema al procesar la trama recibida') + break + def inclusionCliente(self): cfg = self.LeeConfiguracion() res = self.enviaMensajeServidor ('InclusionCliente', { 'cfg': cfg }) logger.debug ('res ({})'.format (res)) + ## RESPUESTA_InclusionCliente if (not res or 0 == res['res']) : logger.error ('Ha ocurrido algún problema en el proceso de inclusión del cliente') return False @@ -368,11 +433,46 @@ with open (subprocs_log, 'ab') as fd: ## TODO improve this logging return True - def process_RESPUESTA_AutoexecCliente(self, path, get_params, post_params, server): - logger.warn('in process_RESPUESTA_AutoexecCliente') + def cuestionCache(self): + return True ## ogAdmClient.c:425 + #>>>>>>>>>>>>>>>>>>>>>>>>>> + #try: + # self.interfaceAdmin ('procesaCache', [ self.cache ]); + #except Exception as e: + # logger.error ('Ha habido algún problerma al procesar la caché') + # return False + # + #return True - def process_RESPUESTA_InclusionCliente(self, path, get_params, post_params, server): - logger.warn('in process_RESPUESTA_InclusionCliente') + def autoexecCliente(self): + res = self.enviaMensajeServidor ('AutoexecCliente', { 'exe': self.idproautoexec }) + logger.debug ('res ({})'.format (res)) + + if (not res): + logger.error ('Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración') + logger.error ('Ha ocurrido algún problema al recibir una petición de comandos o tareas pendientes desde el Servidor de Administración') + return False + + ## RESPUESTA_AutoexecCliente + if (not res or 0 == res['res']) : + logger.error ('Ha ocurrido algún problema al procesar la trama recibida') + return False + + logger.info (res) + res = self.enviaMensajeServidor ('enviaArchivo', { 'nfl': res['nfl'] }) + if (not res): + logger.error ('Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración') + logger.error ('Ha ocurrido algún problema al recibir un archivo por la red') + return False + + fileautoexec = '/tmp/_autoexec_{}'.format (self.IPlocal) + logger.debug ('fileautoexec ({})'.format (fileautoexec)) + with open (fileautoexec, 'w') as fd: + fd.write (res['contents']) + + self.ejecutaArchivo (fileautoexec); + + return True def process_NoComandosPtes(self, path, get_params, post_params, server): logger.warn('in process_NoComandosPtes')