diff --git a/solvable/src/pipe_io_auxlib.py b/solvable/src/pipe_io_auxlib.py index 37bb1a8..75c831e 100644 --- a/solvable/src/pipe_io_auxlib.py +++ b/solvable/src/pipe_io_auxlib.py @@ -1,9 +1,67 @@ from json import dumps, loads + from tfw.crypto import KeyManager, sign_message, verify_message from tfw.components import PipeIOEventHandlerBase from tfw.components.pipe_io_event_handler import DEFAULT_PERMISSIONS + +class SignMessagePipeIOEventHandler(PipeIOEventHandlerBase): + """ + Signs a valid TFW message with HMAC. + Note that the running process needs root permissions in order to read + the authentication key. + When forwarding is true, it will send the signed message to the TFW + server before writing it into the output pipe. + """ + + def __init__( + self, in_pipe_path, out_pipe_path, + permissions=DEFAULT_PERMISSIONS, + forwarding=True + ): + self.forwarding = forwarding + self.auth_key = KeyManager().auth_key + super().__init__(None, in_pipe_path, out_pipe_path, permissions) + + def handle_event(self, message): + return + + def handle_pipe_event(self, message_bytes): + message = loads(message_bytes) + sign_message(self.auth_key, message) + if self.forwarding: + self.server_connector.send(message) + self.pipe_io.send_message(dumps(message).encode()) + + +class VerifyMessagePipeIOEventHandler(PipeIOEventHandlerBase): + """ + Verifies a signed TFW message. + This pipe also needs root permissions. Send the serialized JSON object + to the pipe, then wait for its boolean response. + """ + + def __init__(self, in_pipe_path, out_pipe_path, permissions=DEFAULT_PERMISSIONS): + self.auth_key = KeyManager().auth_key + super().__init__(None, in_pipe_path, out_pipe_path, permissions) + + def handle_event(self, message): + return + + def handle_pipe_event(self, message_bytes): + message = loads(message_bytes) + validity = verify_message(self.auth_key, message) + self.pipe_io.send_message(str(validity).lower().encode()) + + class DeployPipeIOEventHandler(PipeIOEventHandlerBase): + """ + Manages deployment in the IDE. + When you receive "deploy", then you have to answer with a "true" or + "false" depending whether you are satisfied with the result or not. + The @process parameter is the name of the supervised service. + """ + # pylint: disable=too-many-arguments def __init__( self, in_pipe_path, out_pipe_path, process, @@ -50,7 +108,18 @@ class DeployPipeIOEventHandler(PipeIOEventHandlerBase): f'{self.pipe_io.in_pipe}: Expected "true" or "false".' ) + class IdePipeIOEventHandler(PipeIOEventHandlerBase): + """ + Manipulates the content of the IDE. + You can observe a file, and when the user edits it, you will receive + the new contents where newlines are escaped as "\\n". + In order to overwrite the file, send an escaped text back to the pipe. + Since the pipe doesn't know if the file is selected initially in the IDE, + you have to provide this information by yourself with @selected, + but it will track it later on. + """ + # pylint: disable=too-many-arguments def __init__( self, in_pipe_path, out_pipe_path, filename, @@ -103,7 +172,15 @@ class IdePipeIOEventHandler(PipeIOEventHandlerBase): } }) + class FSMPipeIOEventHandler(PipeIOEventHandlerBase): + """ + Handles FSM steps. + When the FSM enters the next state, you will receive a line containing + its name. To trigger a state change, send the name of the transition to + the pipe. + """ + def __init__(self, in_pipe_path, out_pipe_path, permissions=DEFAULT_PERMISSIONS): super().__init__( ['fsm', 'fsm_update'], @@ -119,36 +196,3 @@ class FSMPipeIOEventHandler(PipeIOEventHandlerBase): 'key': '', 'trigger': message_bytes.decode() }) - -class MsgSignPipeIOEventHandler(PipeIOEventHandlerBase): - def __init__( - self, in_pipe_path, out_pipe_path, - permissions=DEFAULT_PERMISSIONS, - forwarding=True - ): - self.forwarding = forwarding - self.auth_key = KeyManager().auth_key - super().__init__(None, in_pipe_path, out_pipe_path, permissions) - - def handle_event(self, message): - return - - def handle_pipe_event(self, message_bytes): - message = loads(message_bytes) - sign_message(self.auth_key, message) - if self.forwarding: - self.server_connector.send(message) - self.pipe_io.send_message(dumps(message).encode()) - -class MsgVerifyPipeIOEventHandler(PipeIOEventHandlerBase): - def __init__(self, in_pipe_path, out_pipe_path, permissions=DEFAULT_PERMISSIONS): - self.auth_key = KeyManager().auth_key - super().__init__(None, in_pipe_path, out_pipe_path, permissions) - - def handle_event(self, message): - return - - def handle_pipe_event(self, message_bytes): - message = loads(message_bytes) - validity = verify_message(self.auth_key, message) - self.pipe_io.send_message(str(validity).lower().encode()) diff --git a/solvable/src/pipe_io_main.py b/solvable/src/pipe_io_main.py index bef89a9..61fb547 100644 --- a/solvable/src/pipe_io_main.py +++ b/solvable/src/pipe_io_main.py @@ -31,50 +31,23 @@ if __name__ == '__main__': permissions=0o666 ) - ''' - Signs a valid TFW message with HMAC. - Note that this process needs root permissions in order to read the - authentication key. - When forwarding is true, it will send the signed message to the TFW - server before writing it into the output pipe. - ''' sign_pipe = MsgSignPipeIOEventHandler( '/tmp/tfw_sign_send', '/tmp/tfw_sign_recv', forwarding=True ) - ''' - Verifies a signed TFW message. - This pipe also needs root permissions. Send the serialized JSON object - to the pipe, then wait for its boolean response. - ''' verify_pipe = MsgVerifyPipeIOEventHandler( '/tmp/tfw_verify_send', '/tmp/tfw_verify_recv' ) - ''' - Manages deployment in the IDE. - When you receive "deploy", then you have to answer with a "true" or - "false" depending whether you are satisfied with the result or not. - The third parameter is the name of the supervised service. - ''' deploy_pipe = DeployPipeIOEventHandler( '/tmp/tfw_deploy_send', '/tmp/tfw_deploy_recv', 'webservice' ) - ''' - Manipulates the content of the IDE. - You can observe a file, and when the user edits it, you will receive - the new contents where newlines are escaped as "\\n". - In order to overwrite the file, send an escaped text back to the pipe. - Since the pipe doesn't know if the file is selected initially in the IDE, - you have to provide this information by yourself, but it will track it - later on. - ''' ide_pipe = IdePipeIOEventHandler( '/tmp/tfw_ide_send', '/tmp/tfw_ide_recv', @@ -82,12 +55,6 @@ if __name__ == '__main__': selected=True ) - ''' - Handles FSM steps. - When the FSM enters the next state, you will receive a line containing - its name. - To trigger a state change, send the name of the transition to the pipe. - ''' fsm_pipe = FSMPipeIOEventHandler( '/tmp/tfw_fsm_send', '/tmp/tfw_fsm_recv'