Ejemplo n.º 1
0
 def test_succeeds_with_agent_token(self, test_client, agent, session):
     session.add(agent)
     session.commit()
     assert agent.token
     headers = [('Authorization', 'Agent ' + agent.token)]
     res = test_client.post(
         '/v2/agent_websocket_token/',
         headers=headers,
     )
     assert res.status_code == 200
     decoded_agent = decode_agent_websocket_token(res.json['token'])
     assert decoded_agent == agent
Ejemplo n.º 2
0
 def onMessage(self, payload, is_binary):
     from faraday.server.web import app
     """
         We only support JOIN and LEAVE workspace messages.
         When authentication is implemented we need to verify
         that the user can join the selected workspace.
         When authentication is implemented we need to reply
         the client if the join failed.
     """
     if not is_binary:
         message = json.loads(payload)
         if message['action'] == 'JOIN_WORKSPACE':
             if 'workspace' not in message or 'token' not in message:
                 logger.warning('Invalid join workspace message: '
                                '{}'.format(message))
                 self.sendClose()
                 return
             signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'],
                                                   salt="websocket")
             try:
                 workspace_id = signer.unsign(message['token'], max_age=60)
             except itsdangerous.BadData as e:
                 self.sendClose()
                 logger.warning('Invalid websocket token for workspace '
                                '{}'.format(message['workspace']))
                 logger.exception(e)
             else:
                 with app.app_context():
                     workspace = Workspace.query.get(int(workspace_id))
                 if workspace.name != message['workspace']:
                     logger.warning(
                         'Trying to join workspace {} with token of '
                         'workspace {}. Rejecting.'.format(
                             message['workspace'], workspace.name
                         ))
                     self.sendClose()
                 else:
                     self.factory.join_workspace(
                         self, message['workspace'])
         if message['action'] == 'LEAVE_WORKSPACE':
             self.factory.leave_workspace(self, message['workspace'])
         if message['action'] == 'JOIN_AGENT':
             if 'token' not in message:
                 logger.warn("Invalid agent join message")
                 self.state = WebSocketProtocol.STATE_CLOSING
                 self.sendClose()
                 return False
             with app.app_context():
                 try:
                     agent = decode_agent_websocket_token(message['token'])
                 except ValueError:
                     logger.warn('Invalid agent token!')
                     self.state = WebSocketProtocol.STATE_CLOSING
                     self.sendClose()
                     return False
             # factory will now send broadcast messages to the agent
             return self.factory.join_agent(self, agent)
         if message['action'] == 'LEAVE_AGENT':
             with app.app_context():
                 (agent_id,) = [
                     k
                     for (k, v) in connected_agents.items()
                     if v == self
                 ]
                 agent = Agent.query.get(agent_id)
                 assert agent is not None  # TODO the agent could be deleted here
             self.factory.leave_agent(self, agent)
             self.state = WebSocketProtocol.STATE_CLOSING
             self.sendClose()
             return False
Ejemplo n.º 3
0
    def onMessage(self, payload, is_binary):
        from faraday.server.web import app # pylint:disable=import-outside-toplevel
        """
            We only support JOIN and LEAVE workspace messages.
            When authentication is implemented we need to verify
            that the user can join the selected workspace.
            When authentication is implemented we need to reply
            the client if the join failed.
        """
        if not is_binary:
            message = json.loads(payload)
            if message['action'] == 'JOIN_WORKSPACE':
                if 'workspace' not in message or 'token' not in message:
                    logger.warning('Invalid join workspace message: '
                                   '{}'.format(message))
                    self.sendClose()
                    return
                signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'],
                                                      salt="websocket")
                try:
                    workspace_id = signer.unsign(message['token'], max_age=60)
                except itsdangerous.BadData as e:
                    self.sendClose()
                    logger.warning('Invalid websocket token for workspace '
                                   '{}'.format(message['workspace']))
                    logger.exception(e)
                else:
                    with app.app_context():
                        workspace = Workspace.query.get(int(workspace_id))
                    if workspace.name != message['workspace']:
                        logger.warning(
                            'Trying to join workspace {} with token of '
                            'workspace {}. Rejecting.'.format(
                                message['workspace'], workspace.name
                            ))
                        self.sendClose()
                    else:
                        self.factory.join_workspace(
                            self, message['workspace'])
            if message['action'] == 'LEAVE_WORKSPACE':
                self.factory.leave_workspace(self, message['workspace'])
            if message['action'] == 'JOIN_AGENT':
                if 'token' not in message or 'executors' not in message:
                    logger.warning("Invalid agent join message")
                    self.sendClose(1000, reason="Invalid JOIN_AGENT message")
                    return False
                with app.app_context():
                    try:
                        agent = decode_agent_websocket_token(message['token'])
                        update_executors(agent, message['executors'])
                    except ValueError:
                        logger.warning('Invalid agent token!')
                        self.sendClose(1000, reason="Invalid agent token!")
                        return False
                    # factory will now send broadcast messages to the agent
                    return self.factory.join_agent(self, agent)
            if message['action'] == 'LEAVE_AGENT':
                with app.app_context():
                    (agent_id,) = [
                        k
                        for (k, v) in connected_agents.items()
                        if v == self
                    ]
                    agent = Agent.query.get(agent_id)
                    assert agent is not None  # TODO the agent could be deleted here
                return self.factory.leave_agent(self, agent)
            if message['action'] == 'RUN_STATUS':
                with app.app_context():
                    if 'executor_name' not in message:
                        logger.warning('Missing executor_name param in message: ''{}'.format(message))
                        return True

                    (agent_id,) = [
                        k
                        for (k, v) in connected_agents.items()
                        if v == self
                    ]
                    agent = Agent.query.get(agent_id)
                    assert agent is not None  # TODO the agent could be deleted here

                    execution_id = message.get('execution_id', None)
                    assert execution_id is not None
                    agent_execution = AgentExecution.query.filter(AgentExecution.id == execution_id).first()
                    if agent_execution:

                        if agent_execution.workspace.name not in \
                                [
                                    workspace.name
                                    for workspace in agent.workspaces
                                ]:
                            logger.exception(
                                ValueError(
                                    f"The {agent.name} agent has permission "
                                    f"to workspace {agent.workspaces} and "
                                    "ask to write to workspace "
                                    f"{agent_execution.workspace.name}"
                                )
                            )
                        else:
                            agent_execution.successful = message.get('successful', None)
                            agent_execution.running = message.get('running', None)
                            agent_execution.message = message.get('message','')
                            db.session.commit()
                    else:
                        logger.exception(
                            NoResultFound(f"No row was found for agent executor id {execution_id}"))
Ejemplo n.º 4
0
    def onMessage(self, payload, is_binary):
        from faraday.server.web import app  # pylint:disable=import-outside-toplevel
        """
            We only support JOIN and LEAVE workspace messages.
            When authentication is implemented we need to verify
            that the user can join the selected workspace.
            When authentication is implemented we need to reply
            the client if the join failed.
        """
        if not is_binary:
            message = json.loads(payload)
            if message['action'] == 'JOIN_WORKSPACE':
                if 'workspace' not in message or 'token' not in message:
                    logger.warning('Invalid join workspace message: '
                                   '{}'.format(message))
                    self.sendClose()
                    return
                signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'],
                                                      salt="websocket")
                try:
                    workspace_id = signer.unsign(message['token'], max_age=60)
                except itsdangerous.BadData as e:
                    self.sendClose()
                    logger.warning('Invalid websocket token for workspace '
                                   '{}'.format(message['workspace']))
                    logger.exception(e)
                else:
                    with app.app_context():
                        workspace = Workspace.query.get(int(workspace_id))
                    if workspace.name != message['workspace']:
                        logger.warning(
                            'Trying to join workspace {} with token of '
                            'workspace {}. Rejecting.'.format(
                                message['workspace'], workspace.name))
                        self.sendClose()
                    else:
                        self.factory.join_workspace(self, message['workspace'])
            if message['action'] == 'LEAVE_WORKSPACE':
                self.factory.leave_workspace(self, message['workspace'])
            if message['action'] == 'JOIN_AGENT':
                if 'token' not in message or 'executors' not in message:
                    logger.warn("Invalid agent join message")
                    self.state = WebSocketProtocol.STATE_CLOSING
                    self.sendClose()
                    return False
                with app.app_context():
                    try:
                        agent = decode_agent_websocket_token(message['token'])
                        update_executors(agent, message['executors'])
                    except ValueError:
                        logger.warn('Invalid agent token!')
                        self.state = WebSocketProtocol.STATE_CLOSING
                        self.sendClose()
                        return False
                    # factory will now send broadcast messages to the agent
                    return self.factory.join_agent(self, agent)
            if message['action'] == 'LEAVE_AGENT':
                with app.app_context():
                    (agent_id, ) = [
                        k for (k, v) in connected_agents.items() if v == self
                    ]
                    agent = Agent.query.get(agent_id)
                    assert agent is not None  # TODO the agent could be deleted here
                self.factory.leave_agent(self, agent)
                self.state = WebSocketProtocol.STATE_CLOSING
                self.sendClose()
                return False
            if message['action'] == 'RUN_STATUS':
                with app.app_context():
                    if 'executor_name' not in message:
                        logger.warning(
                            'Missing executor_name param in message: '
                            '{}'.format(message))
                        self.sendClose()
                        return

                    (agent_id, ) = [
                        k for (k, v) in connected_agents.items() if v == self
                    ]
                    agent = Agent.query.get(agent_id)
                    assert agent is not None  # TODO the agent could be deleted here
                    executor = Executor.query.filter(
                        Executor.name == message['executor_name'],
                        Executor.agent_id == agent_id).first()
                    if executor:
                        successful = message.get('successful', None)
                        running = message.get('running', None)
                        msg = message['message']
                        agent_execution = AgentExecution(
                            running=running,
                            successful=successful,
                            message=msg,
                            executor=executor,
                            workspace_id=executor.agent.workspace_id)
                        db.session.add(agent_execution)
                        db.session.commit()