#!/bin/python from os import path, walk import sys import argparse import yaml import re def parse_data_models_from_search(search): match = re.search(r'from\sdatamodel\s?=\s?([^\s.]*)', search) if match is not None: return match.group(1) return False def pretty_yaml_detections(REPO_PATH, VERBOSE, content_part): manifest_files = [] types = ["endpoint", "application", "cloud", "deprecated", "experimental", "network", "web"] for t in types: for root, dirs, files in walk(REPO_PATH + "/" + content_part + '/' + t): for file in files: if file.endswith(".yml"): manifest_files.append((path.join(root, file))) for manifest_file in manifest_files: pretty_yaml = dict() if VERBOSE: print("processing manifest {0}".format(manifest_file)) with open(manifest_file, 'r') as stream: try: object = list(yaml.safe_load_all(stream))[0] except yaml.YAMLError as exc: print(exc) print("Error reading {0}".format(manifest_file)) error = True continue pretty_yaml['name'] = object['name'] pretty_yaml['id'] = object['id'] pretty_yaml['version'] = object['version'] pretty_yaml['date'] = object['date'] pretty_yaml['author'] = object['author'] pretty_yaml['type'] = object['type'] pretty_yaml['datamodel'] = object['datamodel'] pretty_yaml['description'] = object['description'] pretty_yaml['search'] = object['search'] if 'how_to_implement' in object: pretty_yaml['how_to_implement'] = object['how_to_implement'] else: pretty_yaml['how_to_implement'] = '' pretty_yaml['known_false_positives'] = object['known_false_positives'] if 'references' in object: pretty_yaml['references'] = object['references'] else: pretty_yaml['references'] = [] pretty_yaml['tags'] = {key: value for key, value in sorted(object['tags'].items())} with open(manifest_file, 'w') as file: documents = yaml.dump(pretty_yaml, file, sort_keys=False) return manifest_files def pretty_yaml_baselines(REPO_PATH, VERBOSE, content_part): manifest_files = [] for root, dirs, files in walk(REPO_PATH + "/" + content_part + '/'): for file in files: if file.endswith(".yml"): manifest_files.append((path.join(root, file))) for manifest_file in manifest_files: pretty_yaml = dict() if VERBOSE: print("processing manifest {0}".format(manifest_file)) with open(manifest_file, 'r') as stream: try: object = list(yaml.safe_load_all(stream))[0] except yaml.YAMLError as exc: print(exc) print("Error reading {0}".format(manifest_file)) error = True continue pretty_yaml['name'] = object['name'] pretty_yaml['id'] = object['id'] pretty_yaml['version'] = object['version'] pretty_yaml['date'] = object['date'] pretty_yaml['author'] = object['author'] pretty_yaml['type'] = object['type'] pretty_yaml['datamodel'] = object['datamodel'] pretty_yaml['description'] = object['description'] pretty_yaml['search'] = object['search'] if 'how_to_implement' in object: pretty_yaml['how_to_implement'] = object['how_to_implement'] else: pretty_yaml['how_to_implement'] = '' if 'references' in object: pretty_yaml['references'] = object['references'] else: pretty_yaml['references'] = [] pretty_yaml['tags'] = {key: value for key, value in sorted(object['tags'].items())} with open(manifest_file, 'w') as file: documents = yaml.dump(pretty_yaml, file, sort_keys=False) return manifest_files def pretty_yaml_baselines(REPO_PATH, VERBOSE, content_part): manifest_files = [] for root, dirs, files in walk(REPO_PATH + "/" + content_part + '/'): for file in files: if file.endswith(".yml"): manifest_files.append((path.join(root, file))) for manifest_file in manifest_files: pretty_yaml = dict() if VERBOSE: print("processing manifest {0}".format(manifest_file)) with open(manifest_file, 'r') as stream: try: object = list(yaml.safe_load_all(stream))[0] except yaml.YAMLError as exc: print(exc) print("Error reading {0}".format(manifest_file)) error = True continue pretty_yaml['name'] = object['name'] pretty_yaml['id'] = object['id'] pretty_yaml['version'] = object['version'] pretty_yaml['date'] = object['date'] pretty_yaml['author'] = object['author'] pretty_yaml['type'] = object['type'] pretty_yaml['datamodel'] = object['datamodel'] pretty_yaml['description'] = object['description'] pretty_yaml['search'] = object['search'] if 'how_to_implement' in object: pretty_yaml['how_to_implement'] = object['how_to_implement'] else: pretty_yaml['how_to_implement'] = '' if 'references' in object: pretty_yaml['references'] = object['references'] else: pretty_yaml['references'] = [] pretty_yaml['tags'] = {key: value for key, value in sorted(object['tags'].items())} with open(manifest_file, 'w') as file: documents = yaml.dump(pretty_yaml, file, sort_keys=False) return manifest_files def pretty_yaml_deployments(REPO_PATH, VERBOSE, content_part): manifest_files = [] for root, dirs, files in walk(REPO_PATH + "/" + content_part + '/'): for file in files: if file.endswith(".yml"): manifest_files.append((path.join(root, file))) for manifest_file in manifest_files: pretty_yaml = dict() if VERBOSE: print("processing manifest {0}".format(manifest_file)) with open(manifest_file, 'r') as stream: try: object = list(yaml.safe_load_all(stream))[0] except yaml.YAMLError as exc: print(exc) print("Error reading {0}".format(manifest_file)) error = True continue pretty_yaml['name'] = object['name'] pretty_yaml['id'] = object['id'] pretty_yaml['date'] = object['date'] pretty_yaml['author'] = object['author'] pretty_yaml['description'] = object['description'] pretty_yaml['scheduling'] = object['scheduling'] if 'alert_action' in object: pretty_yaml['alert_action'] = object['alert_action'] pretty_yaml['tags'] = {key: value for key, value in sorted(object['tags'].items())} with open(manifest_file, 'w') as file: documents = yaml.dump(pretty_yaml, file, sort_keys=False) return manifest_files def pretty_yaml_stories(REPO_PATH, VERBOSE, content_part): manifest_files = [] for root, dirs, files in walk(REPO_PATH + "/" + content_part + '/'): for file in files: if file.endswith(".yml"): manifest_files.append((path.join(root, file))) for manifest_file in manifest_files: pretty_yaml = dict() if VERBOSE: print("processing manifest {0}".format(manifest_file)) with open(manifest_file, 'r') as stream: try: object = list(yaml.safe_load_all(stream))[0] except yaml.YAMLError as exc: print(exc) print("Error reading {0}".format(manifest_file)) error = True continue pretty_yaml['name'] = object['name'] pretty_yaml['id'] = object['id'] pretty_yaml['version'] = object['version'] pretty_yaml['date'] = object['date'] pretty_yaml['author'] = object['author'] pretty_yaml['type'] = object['type'] pretty_yaml['description'] = object['description'] pretty_yaml['narrative'] = object['narrative'] if 'references' in object: pretty_yaml['references'] = object['references'] else: pretty_yaml['references'] = [] pretty_yaml['tags'] = {key: value for key, value in sorted(object['tags'].items())} with open(manifest_file, 'w') as file: documents = yaml.dump(pretty_yaml, file, sort_keys=False) return manifest_files def pretty_yaml(REPO_PATH, VERBOSE, content_part): #for root, dirs, files in walk(REPO_PATH + "/"): manifest_files = [] if content_part == 'detections': manifest_files = pretty_yaml_detections(REPO_PATH, VERBOSE, content_part) elif content_part == 'baselines': manifest_files = pretty_yaml_baselines(REPO_PATH, VERBOSE, content_part) elif content_part == 'deployments': manifest_files = pretty_yaml_deployments(REPO_PATH, VERBOSE, content_part) elif content_part == 'stories': manifest_files = pretty_yaml_stories(REPO_PATH, VERBOSE, content_part) return len(manifest_files) def main(args): parser = argparse.ArgumentParser(description="keeps yamls in security_content sorted and pretty printed with custom sort keys, \ meant to run quitely for CI, use -v flag to make it bark") parser.add_argument("-p", "--path", required=True, help="path to security_content repo") parser.add_argument("-v", "--verbose", required=False, default=False, action='store_true', help="prints verbose output") # parse them args = parser.parse_args() REPO_PATH = args.path VERBOSE = args.verbose output = [] pretty_yaml_objects = ['macros','lookups','stories','detections','baselines','response_tasks','responses','deployments'] for pretty_yaml_object in pretty_yaml_objects: touch_count = pretty_yaml(REPO_PATH, VERBOSE, pretty_yaml_object) if VERBOSE: output.append("made {0} {1} pretty".format(touch_count, pretty_yaml_object)) for o in output: print(o) print("finished successfully!") if __name__ == "__main__": main(sys.argv[1:])