def testOverwriting(self): req = rdf_client_action.Iterator(client_state=rdf_protodict.Dict({"A": 1})) # There should be one element now. self.assertLen(list(req.client_state.items()), 1) req.client_state = rdf_protodict.Dict({"B": 2}) # Still one element. self.assertLen(list(req.client_state.items()), 1) req.client_state = rdf_protodict.Dict({}) # And now it's gone. self.assertEmpty(list(req.client_state.items()))
def FromLegacyResponses(cls, request=None, responses=None): """Creates a Responses object from old style flow request and responses.""" res = cls() res.request = request if request: res.request_data = rdf_protodict.Dict(request.data) dropped_responses = [] # The iterator that was returned as part of these responses. This should # be passed back to actions that expect an iterator. res.iterator = None if not responses: return res # This may not be needed if we can assume that responses are # returned in lexical order from the data_store. responses.sort(key=operator.attrgetter("response_id")) if request.HasField("request"): client_action_name = request.request.name action_registry = server_stubs.ClientActionStub.classes if client_action_name not in action_registry: raise RuntimeError("Got unknown client action: %s." % client_action_name) expected_response_classes = action_registry[ client_action_name].out_rdfvalues old_response_id = None # Filter the responses by authorized states for msg in responses: # Check if the message is authenticated correctly. if msg.auth_state != msg.AuthorizationState.AUTHENTICATED: logging.warning( "%s: Messages must be authenticated (Auth state %s)", msg.session_id, msg.auth_state) dropped_responses.append(msg) # Skip this message - it is invalid continue # Handle retransmissions if msg.response_id == old_response_id: continue old_response_id = msg.response_id # Check for iterators if msg.type == msg.Type.ITERATOR: if res.iterator: raise ValueError( "Received multiple iterator messages at once.") res.iterator = rdf_client_action.Iterator(msg.payload) continue # Look for a status message if msg.type == msg.Type.STATUS: # Our status is set to the first status message that we see in # the responses. We ignore all other messages after that. res.status = rdf_flows.GrrStatus(msg.payload) # Check this to see if the call succeeded res.success = res.status.status == res.status.ReturnedStatus.OK # Ignore all other messages break if msg.type == msg.Type.MESSAGE: if request.HasField("request"): # Let's do some verification for requests that came from clients. if not expected_response_classes: raise RuntimeError( "Client action %s does not specify out_rdfvalue." % client_action_name) else: args_rdf_name = msg.args_rdf_name if not args_rdf_name: raise RuntimeError( "Deprecated message format received: " "args_rdf_name is None.") elif args_rdf_name not in [ x.__name__ for x in expected_response_classes ]: raise RuntimeError( "Response type was %s but expected %s for %s." % (args_rdf_name, expected_response_classes, client_action_name)) # Use this message res.responses.append(msg.payload) if res.status is None: # This is a special case of de-synchronized messages. if dropped_responses: logging.error( "De-synchronized messages detected:\n %s", "\n".join( [utils.SmartUnicode(x) for x in dropped_responses])) res.LogFlowState(responses) raise ValueError("No valid Status message.") return res