Files
kube-hunter/events/handler.py
daniel_sagi 290f87de70 1. added log/
2. Started adding kubelet scanning.
3. Changed events architecture. All events are inheriting from "Event" class. when instantiating and defining a new event class, attributes other than what is important for that perticular event are not needed. the event handler will be stacking the events, so that each event will have all the attributes of its successors.
This proccess is invisible to the developer, but needs to be acknowledged.
*note: from now on, all executors needs to set self.event to given arg on init*
Example (pseudo):

@subscribe(NewHostEvent)
def PortScan(event):
		publish(OpenPortEvent(port="8080"))

@subscribe(OpenPortEvent)
def print(event):
		print(event.host)

publish(NewHostEvent(host="0.0.0.0"))
>> output: 0.0.0.0

the print function recieves an open port event. even though when publishing the OpenPortEvent we did not specify a host, the print function can access the "host" attribute, as the OpenPortEvent successor was NewHostEvent. if "host" was not defined on the succesors, it is "None"
2018-05-24 15:39:31 +03:00

66 lines
2.2 KiB
Python

import inspect
import logging
from abc import ABCMeta
from collections import defaultdict
from Queue import Queue
from threading import Lock, Thread
# Inherits Queue object, handles events asynchronously
class EventQueue(Queue, object):
def __init__(self, num_worker=10):
super(EventQueue, self).__init__()
self.hooks = defaultdict(list)
self.running = True
for i in range(num_worker):
t = Thread(target=self.worker)
t.daemon = True
t.start()
# decorator wrapping for easy subscription
def subscribe(self, event, hook=None, predicate=None):
def wrapper(hook):
self.subscribe_event(event, hook=hook, predicate=predicate)
return hook
return wrapper
# getting uninstantiated event object
def subscribe_event(self, event, hook=None, predicate=None):
logging.debug('{} subscribed to {}'.format(event.__name__, hook))
if hook not in self.hooks[event.__name__]:
self.hooks[event.__name__].append((hook, predicate))
# getting instantiated event object
def publish_event(self, event):
logging.debug('Event {} got published with {}'.format(event.__class__.__name__, event))
event_name = event.__class__.__name__
if event_name in self.hooks:
for hook, predicate in self.hooks[event_name]:
if predicate and not predicate(event):
continue
# access to stack frame, can also be implemented by changing the function call to recieve self.
# TODO: decide whether invisibility to the developer is the best approach
last_frame = inspect.stack()[1][0]
if "self" in last_frame.f_locals:
event.previous = last_frame.f_locals["self"].event
self.put(hook(event))
# executes callbacks on dedicated thread as a daemon
def worker(self):
while self.running:
hook = self.get()
hook.execute()
self.task_done()
# stops execution of all daemons
def free(self):
self.running = False
with self.mutex:
self.queue.clear()
handler = EventQueue(800)