def TailLogs(self, request, context): """ Provides an infinite stream of logs to the client. The client can stop the stream by closing the connection. """ self._print_grpc(request) if request.service and \ request.service not in ServiceRegistry.list_services(): set_grpc_err( context, grpc.StatusCode.NOT_FOUND, 'Service {} not found'.format(request.service), ) return if not request.service: exec_list = ['sudo', 'tail', '-f', '/var/log/syslog'] else: exec_list = [ 'sudo', 'journalctl', '-fu', 'magma@{}'.format(request.service), ] logging.debug('Tailing logs') log_queue = queue.Queue() async def enqueue_log_lines(): # https://stackoverflow.com/a/32222971 proc = await asyncio.create_subprocess_exec( *exec_list, stdout=asyncio.subprocess.PIPE, preexec_fn=os.setsid, ) try: while context.is_active(): try: line = await asyncio.wait_for( proc.stdout.readline(), timeout=10.0, ) log_queue.put(line) except asyncio.TimeoutError: pass finally: logging.debug('Terminating log stream') os.killpg(os.getpgid(proc.pid), signal.SIGTERM) self._loop.create_task(enqueue_log_lines()) while context.is_active(): try: log_line = log_queue.get(block=True, timeout=10.0) yield magmad_pb2.LogLine(line=log_line) except queue.Empty: pass
def M5GDecryptImsiSUCIRegistration(self, request, context): """ M5GDecryptImsiSUCIRegistration """ print_grpc( request, self._print_grpc_payload, "M5GDecryptImsiSUCIRegistration Request:", ) aia = subscriberdb_pb2.M5GSUCIRegistrationAnswer() try: suciprofile = self.suciprofile_db.get(request.ue_pubkey_identifier) if suciprofile is None: set_grpc_err( context, StatusCode.NOT_FOUND, f"identifier {request.ue_pubkey_identifier} not found", ) return aia if suciprofile.protection_scheme == 0: profile = 'A' elif suciprofile.protection_scheme == 1: profile = 'B' home_network_info = ECIES_HN( suciprofile.home_net_private_key, profile, ) msin_recv = home_network_info.unprotect( request.ue_pubkey, request.ue_ciphertext, request.ue_encrypted_mac, ) aia.ue_msin_recv = msin_recv[:10] logging.info("Deconcealed IMSI: %s", aia.ue_msin_recv) return aia except SuciProfileNotFoundError as e: logging.warning("Suciprofile not found: %s", e) return aia finally: print_grpc( aia, self._print_grpc_payload, "M5GDecryptImsiSUCIRegistration Response:", )
def GenericCommand(self, request, context): """ Execute generic command. This method will run the command with params as specified in the command executor's command table, then return the response of the command. """ if 'generic_command_config' not in self._magma_service.config: set_grpc_err(context, grpc.StatusCode.NOT_FOUND, 'Generic command config not found') return magmad_pb2.GenericCommandResponse() params = json_format.MessageToDict(request.params) # Run the execute command coroutine. Return an error if it times out or # if an exception occurs. logging.info('Running generic command %s with parameters %s', request.command, params) future = asyncio.run_coroutine_threadsafe( self._command_executor.execute_command(request.command, params), self._loop) timeout = self._magma_service.config['generic_command_config']\ .get('timeout_secs', 15) response = magmad_pb2.GenericCommandResponse() try: result = future.result(timeout=timeout) logging.debug('Command was successful') response.response.MergeFrom( json_format.ParseDict(result, Struct())) except asyncio.TimeoutError: logging.error('Error running command %s! Command timed out', request.command) future.cancel() set_grpc_err(context, grpc.StatusCode.DEADLINE_EXCEEDED, 'Command timed out') except Exception as e: # pylint: disable=broad-except logging.error('Error running command %s! %s: %s', request.command, e.__class__.__name__, e) set_grpc_err(context, grpc.StatusCode.UNKNOWN, '{}: {}'.format(e.__class__.__name__, str(e))) return response