Esempio n. 1
0
    def on_rx(self, message):
        with self._lock:
            log.debug("on_rx: %s" % message)
            session_id = message['session_id']
            fqdn = message['fqdn']
            log.info("AgentRpcMessenger.on_rx: %s/%s" % (fqdn, session_id))

            if message['type'] == 'SESSION_CREATE':
                if fqdn in self._sessions:
                    old_session_id = self._sessions[fqdn]
                    self._abort_session(fqdn, "new session created", old_session_id, session_id)
                else:
                    self._sessions[fqdn] = session_id
            elif message['type'] == 'SESSION_TERMINATE':
                # An agent has timed out or restarted, we're being told its session is now dead
                if message['fqdn'] in self._sessions:
                    self._abort_session(fqdn, "session terminated", message['session_id'])
            elif message['type'] == 'SESSION_TERMINATE_ALL':
                # The http_agent service has restarted, all sessions are now over
                for fqdn, session in self._sessions.items():
                    self._abort_session(fqdn, "all sessions terminated", session)
            else:
                rpc_response = message['body']
                if rpc_response['type'] != 'ACTION_COMPLETE':
                    log.error("Unexpected type '%s'" % rpc_response['type'])
                    return

                if fqdn in self._sessions and self._sessions[fqdn] != session_id:
                    log.info("AgentRpcMessenger.on_rx: cancelling session %s/%s (replaced by %s)" % (fqdn, self._sessions[fqdn], session_id))
                    self._abort_session(fqdn, "session cancelled", self._sessions[fqdn])
                    HttpAgentRpc().reset_session(fqdn, AgentRpcMessenger.PLUGIN_NAME, session_id)
                elif fqdn in self._sessions:
                    log.info("AgentRpcMessenger.on_rx: good session %s/%s" % (fqdn, session_id))
                    # Find this RPC and complete it
                    try:
                        rpc = self._session_rpcs[session_id][rpc_response['id']]
                    except KeyError:
                        if rpc_response['id'] in self._cancelled_rpcs:
                            log.debug("Response received from a cancelled RPC (id: %s)", rpc_response['id'])
                        else:
                            log.error("Response received from UNKNOWN RPC of (id: %s)", rpc_response['id'])
                    else:
                        del self._session_rpcs[session_id][rpc_response['id']]
                        rpc.exception = rpc_response['exception']
                        rpc.result = rpc_response['result']
                        rpc.subprocesses = rpc_response['subprocesses']
                        log.info("AgentRpcMessenger.on_rx: completing rpc %s" % rpc.id)
                        rpc.complete.set()
                else:
                    log.info("AgentRpcMessenger.on_rx: unknown session %s/%s" % (fqdn, session_id))
                    # A session I never heard of?
                    HttpAgentRpc().reset_session(fqdn, AgentRpcMessenger.PLUGIN_NAME, session_id)
Esempio n. 2
0
    def run(self):
        try:
            HttpAgentRpc().reset_plugin_sessions(AgentRpcMessenger.PLUGIN_NAME)
        except RpcTimeout:
            # Assume this means that the http_agent service isn't running: this
            # is acceptable, as our goal of there not being any sessions is
            # already the case.
            log.warning("Unable to reset %s sessions" % AgentRpcMessenger.PLUGIN_NAME)

        self._action_runner_rx_queue.serve(session_callback = self.on_rx)
        log.info("AgentRpcMessenger.complete")
Esempio n. 3
0
    def test_revoked_cert(self):
        """Check that I'm bounced if my certificate is revoked"""

        # Initially should be able to to operations like open a session
        self._open_session()
        HttpAgentRpc().remove_host(self.host.fqdn)

        # After revokation any access should be bounced
        response = self._post([])
        self.assertEqual(response.status_code, 403)
        response = self._get()
        self.assertEqual(response.status_code, 403)
Esempio n. 4
0
    def on_message(self, message):
        with self._processing_lock:
            fqdn = message["fqdn"]
            assert message["plugin"] == self._plugin_name

            if message["type"] != "DATA":
                # We are session aware in that we check sequence numbers etc, but
                # we don't actually require any actions on SESSION_CREATE or
                # SESSION_TERMINATE.
                assert message["type"] in ("SESSION_CREATE",
                                           "SESSION_TERMINATE")
                return

            try:
                host = ManagedHost.objects.get(fqdn=fqdn)
            except ManagedHost.DoesNotExist:
                log.error("Received agent message for non-existent host %s" %
                          fqdn)
                return

            log.debug("Received agent message for %s/%s/%s" %
                      (fqdn, message["plugin"], message["session_id"]))

            existing_session = self._sessions.get(host.id, None)
            if existing_session is None:
                if message["session_seq"] == 0:
                    # No existing session, start a new one
                    log.info("New session")
                    self._sessions[host.id] = Session(
                        message["session_id"],
                        self._create_plugin_instance(host))
                else:
                    # Partway through a session, reset it
                    log.info(
                        "Nonzero counter for new (to me) session, resetting")
                    HttpAgentRpc().reset_session(fqdn, self._plugin_name,
                                                 message["session_id"])
                    return

            elif existing_session.id != message["session_id"]:
                if message["session_seq"] == 0:
                    # Existing session to be replaced with this one
                    log.info("Replacing session %s/%s with %s/%s" %
                             (self._plugin_name, existing_session.id,
                              self._plugin_name, message["session_id"]))
                    self._sessions[host.id] = Session(
                        message["session_id"],
                        self._create_plugin_instance(host))
                else:
                    # Existing session is dead, new session is not at zero, must send a reset
                    log.info(
                        "Nonzero counter for new (to me) replacement session, resetting"
                    )
                    del self._sessions[host.id]
                    HttpAgentRpc().reset_session(fqdn, self._plugin_name,
                                                 message["session_id"])
                    return
            else:
                if message["session_seq"] == existing_session.seq + 1:
                    # Continuation of session
                    pass
                else:
                    # Got out of sequence, reset it
                    log.info(
                        "Out of sequence message (seq %s, expected %s), resetting"
                        % (message["session_seq"], existing_session.seq + 1))
                    del self._sessions[host.id]
                    HttpAgentRpc().reset_session(fqdn, self._plugin_name,
                                                 message["session_id"])
                    return

            session = self._sessions.get(host.id, None)
            try:
                if message["session_seq"] == 0:
                    session.plugin.do_agent_session_start(message["body"])
                else:
                    session.seq += 1
                    session.plugin.do_agent_session_continue(message["body"])
            except Exception:
                exc_info = sys.exc_info()
                backtrace = "\n".join(
                    traceback.format_exception(*(exc_info or sys.exc_info())))
                log.error("Exception in agent session for %s from %s: %s" %
                          (self._plugin_name, host, backtrace))
                log.error("Data: %s" % message["body"])

                HttpAgentRpc().reset_session(fqdn, self._plugin_name,
                                             message["session_id"])