From aa25e83a990a491a12e6f84d4f375ff532d88205 Mon Sep 17 00:00:00 2001 From: daniel_sagi Date: Thu, 21 Jun 2018 19:47:10 +0300 Subject: [PATCH] moved report generation functions to inner functions, also added token flag, and the lambda url sending function --- kube-hunter.py | 6 ++- report/reporter.py | 103 +++++++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/kube-hunter.py b/kube-hunter.py index 5c38da0..a1ee10f 100644 --- a/kube-hunter.py +++ b/kube-hunter.py @@ -13,6 +13,7 @@ parser.add_argument('--mapping', action="store_true", help="outputs only a mappi parser.add_argument('--remote', nargs='+', metavar="HOST", default=list(), help="one or more remote ip/dns to hunt") parser.add_argument('--active', action="store_true", help="enables active hunting") parser.add_argument('--log', type=str, metavar="LOGLEVEL", default='INFO', help="set log level, options are: debug, info, warn, none") +parser.add_argument('--token', type=str, metavar="AQUA_TOKEN", help="specify the token retrieved from Aqua, after finished executing, the report will be visible on kube-hunter's site") config = parser.parse_args() try: @@ -38,7 +39,10 @@ def main(): finally: handler.free() logging.debug("Cleaned Queue") - reporter.print_tables() + if config.token: + reporter.send_report(token=config.token) + else: + reporter.print_tables() if config.pod: while True: time.sleep(5) diff --git a/report/reporter.py b/report/reporter.py index 544f3ee..d0abd93 100644 --- a/report/reporter.py +++ b/report/reporter.py @@ -21,6 +21,8 @@ EVIDENCE_PREVIEW = 40 MAX_WIDTH_VULNS = 70 MAX_WIDTH_SERVICES = 60 +AQUA_PUSH_URL = "https://qlyscbqwl7.execute-api.us-east-1.amazonaws.com/Prod?token={}" + @handler.subscribe(Service) @handler.subscribe(Vulnerability) class Reporter(object): @@ -52,12 +54,34 @@ class Reporter(object): def print_tables(self): """generates report tables and outputs to stdout""" - print_nodes() - if not config.mapping: - print_services() - print_vulnerabilities() + if len(services): + print_nodes() + if not config.mapping: + print_services() + print_vulnerabilities() + else: + print "\nKube Hunter couldn't find any clusters" + # print "\nKube Hunter couldn't find any clusters. {}".format("Maybe try with --active?" if not config.active else "") def build_sub_services(self, services_list): + # correlation functions + def get_insights_by_service(service): + """generates list of insights related to a given service""" + insights = list() + for insight_type, insight in self.insights_by_id[service.event_id]: + if service in insight.history: + insights.append((insight_type, insight)) + return insights + + def get_services_by_service(parent_service): + """generates list of insights related to a given service""" + services = list() + for service in self.services_by_id[parent_service.event_id]: + if service != parent_service and parent_service in service.history: + services.append(service) + self.services_by_id[parent_service.event_id].remove(service) + return services + current_list = list() for service in services_list: current_list.append( @@ -69,7 +93,7 @@ class Reporter(object): }, "description": service.explain() }) - next_services = self.get_services_by_service(service) + next_services = get_services_by_service(service) if next_services: current_list[-1]["services"] = self.build_sub_services(next_services) current_list[-1]["insights"] = [{ @@ -77,58 +101,37 @@ class Reporter(object): "name": insight.get_name(), "description": insight.explain(), "evidence": insight.evidence if insight_type == Vulnerability else "" - } for insight_type, insight in self.get_insights_by_service(service)] - + } for insight_type, insight in get_insights_by_service(service)] return current_list - def generate_report(self): - """function generates report structure, for""" - for service in services: - self.services_by_id[service.event_id].append(service) - for insight_type, insight in insights: - self.insights_by_id[insight.event_id].append((insight_type, insight)) - - report = defaultdict(list) - # building first layer of services (nodes) - for _, services_list in self.services_by_id.items(): - service_report = defaultdict(list) - service_report["type"] = "Node" - service_report["metadata"] = { - "host": str(services_list[0].host) - } - # building all sub layers. - service_report["services"] = self.build_sub_services(services_list) - report["services"].append(service_report) - return json.dumps(report, indent=4) - def send_report(self, token): + def generate_report(): + """function generates a report corresponding to specifications of the frontend of kubehunter""" + for service in services: + self.services_by_id[service.event_id].append(service) + for insight_type, insight in insights: + self.insights_by_id[insight.event_id].append((insight_type, insight)) + + # building first layer of services (nodes) + report = defaultdict(list) + for _, services_list in self.services_by_id.items(): + service_report = { + "type": "Node", # on future, determine if slave or master + "metadata": { + "host": str(services_list[0].host) + }, + # then constructing their sub services tree + "services": self.build_sub_services(services_list) + } + report["services"].append(service_report) + return report report = { - 'results': self.generate_report(), + 'results': generate_report(), 'metadata': {} } - r = requests.put("https://pnmhh30s1b.execute-api.us-east-1.amazonaws.com/v02?token={}".format(token), json=report) - # if r.status_code == 200: - - print "{}: {}".format(r.status_code, r.text) - - # correlating - def get_insights_by_service(self, service): - """generates list of insights related to a given service""" - insights = list() - for insight_type, insight in self.insights_by_id[service.event_id]: - if service in insight.history: - insights.append((insight_type, insight)) - return insights + r = requests.put(AQUA_PUSH_URL.format(token), json=report) - def get_services_by_service(self, parent_service): - """generates list of insights related to a given service""" - services = list() - for service in self.services_by_id[parent_service.event_id]: - if service != parent_service and parent_service in service.history: - services.append(service) - self.services_by_id[parent_service.event_id].remove(service) - return services - + print "{}: {}".format(r.status_code, r.text) reporter = Reporter()