PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/aff4_objects/timeline.py

https://code.google.com/
Python | 188 lines | 140 code | 25 blank | 23 comment | 0 complexity | cf579aecde3f92669a5f1d6c944e0bea MD5 | raw file
Possible License(s): Apache-2.0
  1. #!/usr/bin/env python
  2. # Copyright 2011 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. """A timeline AFF4 object implementation."""
  15. import heapq
  16. import struct
  17. from grr.lib import aff4
  18. from grr.lib.aff4_objects import aff4_grr
  19. from grr.lib.aff4_objects import standard
  20. from grr.proto import analysis_pb2
  21. class RDFEvent(aff4.RDFProto):
  22. _proto = analysis_pb2.Event
  23. rdf_map = dict(timestamp=aff4.RDFDatetime,
  24. stat=standard.StatEntry)
  25. class AFF4Event(aff4.AFF4Object):
  26. """An AFF4 representation of an Event."""
  27. class SchemaCls(aff4.AFF4Object.SchemaCls):
  28. TIMESTAMP = aff4.Attribute("aff4:timeline/timestamp", aff4.RDFDatetime,
  29. "The time of this event.", "timestamp")
  30. # The actual event protobuf
  31. EVENT = aff4.Attribute("aff4:timeline/event", RDFEvent,
  32. "The event protobuf", "event")
  33. def __init__(self, event):
  34. # This object is virtualized from the event.
  35. super(AFF4Event, self).__init__(urn=event.subject, mode="w",
  36. age=aff4.ALL_TIMES)
  37. self.event = event
  38. self.Set(self.Schema.TIMESTAMP(event.timestamp))
  39. self.Set(self.Schema.EVENT(event))
  40. # Ensure this virtual object is read only.
  41. self.mode = "r"
  42. def Flush(self):
  43. """We are a read only object and we do not write to the data store."""
  44. pass
  45. class TimelineView(aff4_grr.View):
  46. """A timeline view."""
  47. class GRRTimeSeries(standard.VFSDirectory):
  48. """A time series is a sequence of serialized Event protobufs."""
  49. _behaviours = set()
  50. class SchemaCls(standard.VFSDirectory.SchemaCls):
  51. """Attributes of the timeseries object."""
  52. # Total number of events here
  53. SIZE = aff4.AFF4Stream.SchemaCls.SIZE
  54. START = aff4.Attribute("aff4:timeline/start", aff4.RDFDatetime,
  55. "The timestamp of the first event in this series")
  56. END = aff4.Attribute("aff4:timeline/end", aff4.RDFDatetime,
  57. "The timestamp of the last event in this series")
  58. DESCRIPTION = aff4.Attribute("aff4:description", aff4.RDFString,
  59. "This collection's description", "description")
  60. TIMELINE = aff4.Attribute("aff4:timeline/view", TimelineView,
  61. "The columns that will be shown in the timeline.",
  62. default="")
  63. # Should we write new data on Close()?
  64. dirty = False
  65. def Initialize(self):
  66. super(GRRTimeSeries, self).Initialize()
  67. self.heap = []
  68. def AddEvent(self, event=None, **kw):
  69. """Add the event protobuf to the series.
  70. Args:
  71. event: An optional event object.
  72. """
  73. if event is None:
  74. event = analysis_pb2.Event(**kw)
  75. # Push the serialized event proto on the heap to save memory
  76. heapq.heappush(self.heap, (event.timestamp, event.SerializeToString()))
  77. self.dirty = True
  78. # Implement an iterated interface to the events
  79. def __iter__(self):
  80. """Iterate over all event protobufs.
  81. Yields:
  82. event protobufs in increasing time order.
  83. Raises:
  84. RuntimeError: if we are in write mode.
  85. """
  86. if self.mode == "w":
  87. raise RuntimeError("Can not read when in write mode.")
  88. count = 0
  89. storage = aff4.FACTORY.Open(self.urn.Add("Storage"), token=self.token)
  90. while True:
  91. try:
  92. length = struct.unpack("<i", storage.Read(4))[0]
  93. serialized_event = storage.Read(length)
  94. except struct.error:
  95. break
  96. event = analysis_pb2.Event()
  97. event.ParseFromString(serialized_event)
  98. event.id = count
  99. count += 1
  100. yield event
  101. def Query(self, filter_string="", filter_obj=None):
  102. # An empty filter string returns all the children.
  103. if not filter_string: return self.OpenChildren(mode=self.mode)
  104. # Parse the query string
  105. ast = aff4.AFF4QueryParser(filter_string).Parse()
  106. # Query our own data store
  107. filter_obj = ast.Compile(aff4.AFF4Filter)
  108. return filter_obj.Filter(self.OpenChildren(mode=self.mode))
  109. def Close(self):
  110. """Flush the events into the image stream."""
  111. if not self.dirty: return
  112. storage = aff4.FACTORY.Create(self.urn.Add("Storage"), "AFF4Image",
  113. token=self.token)
  114. storage.Truncate(0)
  115. if self.heap:
  116. first = last = self.heap[0][0]
  117. # Note our first event and size
  118. self.Set(self.Schema.SIZE(len(self.heap)))
  119. self.Set(self.Schema.START(first))
  120. while self.heap:
  121. # This pulls the smallest time from the heap
  122. last, serialized_event = heapq.heappop(self.heap)
  123. # Write the length and then the data
  124. storage.Write(struct.pack("<i", len(serialized_event)))
  125. storage.Write(serialized_event)
  126. # Note our last event and size
  127. self.Set(self.Schema.END(last))
  128. # We are done - flush and close the file.
  129. storage.Close()
  130. super(GRRTimeSeries, self).Close()
  131. def OpenChildren(self, children=None, mode="r"):
  132. if mode != "r":
  133. raise IOError("Events are always read only.")
  134. for event in self:
  135. result = AFF4Event(event)
  136. # Allow users to filter events
  137. if children is not None and str(result.urn) not in children:
  138. continue
  139. yield result