PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/client/actions.py

https://code.google.com/
Python | 182 lines | 97 code | 25 blank | 60 comment | 10 complexity | 302b41dfb7aebbb12c97cc449fe36a78 MD5 | raw file
Possible License(s): Apache-2.0
  1. #!/usr/bin/env python
  2. # Copyright 2010 Google Inc.
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """This file contains common grr jobs."""
  15. import logging
  16. import pdb
  17. import traceback
  18. from grr.client import conf as flags
  19. from grr.lib import registry
  20. from grr.lib import utils
  21. from grr.proto import jobs_pb2
  22. FLAGS = flags.FLAGS
  23. # Our first response in the session is this:
  24. INITIAL_RESPONSE_ID = 1
  25. class ActionPlugin(object):
  26. """Baseclass for plugins.
  27. An action is a plugin abstraction which receives a protobuf and
  28. sends a protobuf in response.
  29. The code is specified in the Run() method, while the data is
  30. specified in the in_protobuf and out_protobuf classes.
  31. """
  32. # The protobuf that will be used to encode this message
  33. in_protobuf = None
  34. # The protobuf type we send
  35. out_protobuf = None
  36. # Authentication Required for this Action:
  37. _authentication_required = True
  38. __metaclass__ = registry.MetaclassRegistry
  39. def __init__(self, message, grr_context=None, **proto_args):
  40. """Initialises our protobuf from the keywords passed.
  41. Args:
  42. message: The GrrMessage that we are called to process.
  43. grr_context: The grr context object which may be used to
  44. e.g. send new actions on.
  45. **proto_args: Field initializers for the protobuf in self._protobuf.
  46. """
  47. self.grr_context = grr_context
  48. self.message = message
  49. self.response_id = INITIAL_RESPONSE_ID
  50. if self.in_protobuf:
  51. self.buff = self.in_protobuf()
  52. for k, v in proto_args.items():
  53. setattr(self.buff, k, v)
  54. def Execute(self, message):
  55. """This function parses the protobuf from the server.
  56. The Run method will be called with the unserialised protobuf.
  57. Args:
  58. message: The encoded protobuf which will be decoded
  59. by the plugin.
  60. Returns:
  61. Upon return a callback will be called on the server to register
  62. the end of the function and pass back exceptions.
  63. """
  64. if self.in_protobuf:
  65. args = self.in_protobuf()
  66. args.ParseFromString(message.args)
  67. else:
  68. args = None
  69. self.status = jobs_pb2.GrrStatus()
  70. self.status.status = jobs_pb2.GrrStatus.OK # Default status.
  71. try:
  72. # Only allow authenticated messages in the client
  73. if (self._authentication_required and
  74. message.auth_state != jobs_pb2.GrrMessage.AUTHENTICATED):
  75. raise RuntimeError("Message for %s was not Authenticated." %
  76. message.name)
  77. self.Run(args)
  78. # We want to report back all errors and map Python exceptions to
  79. # Grr Errors.
  80. except Exception, e:
  81. self.SetStatus(jobs_pb2.GrrStatus.GENERIC_ERROR, "%r: %s" % (e, e),
  82. traceback.format_exc())
  83. if FLAGS.debug:
  84. pdb.post_mortem()
  85. if self.status.status != jobs_pb2.GrrStatus.OK:
  86. logging.info("Job Error (%s): %s", self.__class__.__name__,
  87. self.status.error_message)
  88. if self.status.backtrace:
  89. logging.debug(self.status.backtrace)
  90. # This returns the error status of the Actions to the flow.
  91. self.SendReply(self.status, message_type=jobs_pb2.GrrMessage.STATUS)
  92. def Run(self, unused_args):
  93. """Main plugin entry point.
  94. This function will always be overridden by real plugins.
  95. Args:
  96. unused_args: An already initialised protobuf object.
  97. Raises:
  98. KeyError: if not implemented.
  99. """
  100. raise KeyError("Action %s not available on this platform." %
  101. self.message.name)
  102. def SetStatus(self, status, message="", backtrace=None):
  103. """Set a status to report back to the server."""
  104. self.status.status = status
  105. self.status.error_message = utils.SmartUnicode(message)
  106. if backtrace:
  107. self.status.backtrace = utils.SmartUnicode(backtrace)
  108. def SendReply(self, protobuf=None, message_type=jobs_pb2.GrrMessage.MESSAGE,
  109. **kw):
  110. """Send response back to the server."""
  111. if protobuf is None:
  112. protobuf = self.out_protobuf(**kw)
  113. self.grr_context.SendReply(protobuf,
  114. session_id=self.message.session_id,
  115. response_id=self.response_id,
  116. request_id=self.message.request_id,
  117. message_type=message_type)
  118. self.response_id += 1
  119. class IteratedAction(ActionPlugin):
  120. """An action which can restore its state from an iterator.
  121. Implement iterating actions by extending this class and overriding the
  122. Iterate() method.
  123. """
  124. def Run(self, request):
  125. """Munge the iterator to the server and abstract it away."""
  126. # Pass the client_state as a dict to the action. This is often more
  127. # efficient than manipulating a protobuf.
  128. client_state = utils.ProtoDict(request.iterator.client_state).ToDict()
  129. # Derived classes should implement this.
  130. self.Iterate(request, client_state)
  131. # Update the iterator client_state from the dict.
  132. request.iterator.client_state.CopyFrom(
  133. utils.ProtoDict(client_state).ToProto())
  134. # Return the iterator
  135. self.SendReply(request.iterator, message_type=jobs_pb2.GrrMessage.ITERATOR)
  136. def Iterate(self, request, client_state):
  137. """Actions should override this."""