from __future__ import absolute_import import sys from splunk.appserver.mrsparkle.lib.util import make_splunkhome_path def add_to_sys_path(paths, prepend=False): for path in paths: if prepend: if path in sys.path: sys.path.remove(path) sys.path.insert(0, path) elif not path in sys.path: sys.path.append(path) add_to_sys_path([make_splunkhome_path(['etc', 'apps', 'Splunk_Security_Essentials', 'lib', 'py23', 'splunklib'])], prepend=True) # We should not rely on core enterprise packages: add_to_sys_path([make_splunkhome_path(['etc', 'apps', 'Splunk_Security_Essentials', 'lib', 'py3'])], prepend=True) # Common libraries like future add_to_sys_path([make_splunkhome_path(['etc', 'apps', 'Splunk_Security_Essentials', 'lib', 'py23'])], prepend=True) from six.moves import reload_module try: if 'future' in sys.modules: import future reload_module(future) except Exception: '''noop: future was not loaded yet''' import traceback import os import json import re import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error, six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse import time import csv splunk_home = os.getenv('SPLUNK_HOME') sys.path.append(splunk_home + '/etc/apps/Splunk_Security_Essentials/bin/') sys.path.append(splunk_home + '/etc/apps/Splunk_Security_Essentials/bin/splunklib/') from bs4 import BeautifulSoup import traceback import splunk.rest as rest import splunk.entity, splunk.Intersplunk from splunk.clilib.cli_common import getConfKeyValue, getConfStanza, getConfStanzas from io import open from six.moves import range if sys.platform == "win32": import msvcrt # Binary mode is required for persistent mode on Windows. msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) from splunk.persistconn.application import PersistentServerConnectionApplication import splunklib.client as client from splunklib.client import ConfigurationFile import logging as logger logger.basicConfig(filename=splunk_home + '/var/log/showcaseInfo.log', level=logger.DEBUG) class ShowcaseInfo(PersistentServerConnectionApplication): def __init__(self, command_line, command_arg): PersistentServerConnectionApplication.__init__(self) def handle(self, in_string): input = {} payload = {} caching = "requireupdate" sessionKey = "" owner = "" app = "Splunk_Security_Essentials" includeSSEFilter = True settings = dict() base_url ="" bookmarks = dict() kvstore_usernames = dict() kvstore_conversion = dict() # kvstore_data_status = dict() eventtypes_data_status = dict() # eventtypes_coverage_level = dict() eventtype_names = {} dsc_to_ds_name = {} eventtype_to_legacy_names = {} myApps = [app] globalSourceList = dict() debug = [] globalSearchList = dict() mitre_attack_blob = dict() mitre_names = {"attack": {}} mitre_refs_to_names = {} mitre_refs_to_refs = {} mitre_techniques_to_groups = {} mitre_techniques_to_software = {} # mitre_techniques_to_group_objs = {} # group_ref_technique_ref_to_details = {} mitre_group_name_to_description = {} mitre_group_name_to_id = {} mitre_software_name_to_id = {} mitre_refs_to_ids = {} mitre_technique_descriptions = {} mitre_sub_technique_descriptions = {} mitre_keywords = {} mitre_platforms = {} desired_locale = "" valid_locales = ["ja-JP", "en-DEBUG"] custom_content = [] channel_exclusion = {} ignore_channel_exclusion = False channel_to_name = {} dsc_to_productIds = {} dsc_to_da_scores = {} product_details = {} popularity_threshold = 5 popularTechniques = {} field_list_version = "all" summary_id = "" mini_fields = ["id", "includeSSE", "examples", "mitre_keywords", "dashboard", "bookmark_status", "bookmark_status_display", "bookmark_notes", "icon", "name", "description", "usecase", "category", "mitre_id", "mitre_technique_combined", "mitre_technique_display", "mitre_sub_technique_display", "mitre_tactic_display", "data_source_categories_display", "channel", "displayapp", "journey", "highlight", "alertvolume", "domain", "mitre_threat_groups","mitre_platforms","mitre_software", "data_available", "enabled", "killchain", "hasSearch", "SPLEase", "advancedtags", "released", "searchKeywords", "datasource", "datamodel","search_title","hasContentMapping", "industryMapping", "escu_nist", "escu_cis", "soarPlaybookAvailable","analytic_story", "risk_object_type", "threat_object_type", "risk_score", "risk_message", "s2m2"] start_time = time.time() search_mappings = {} #bookmark_display_names = { "none": "Not On List", "bookmarked": "Bookmarked", "inQueue": "Ready for Deployment", "needData": "Waiting on Data", "issuesDeploying": "Deployment Issues", "needsTuning": "Needs Tuning", "successfullyImplemented": "Successfully Implemented" } bookmark_display_names = {"none": "Not On List", "bookmarked": "Bookmarked", "successfullyImplemented": "Successfully Implemented"} throwErrorMessage = False pathToShowcaseInfoMini = os.environ['SPLUNK_HOME'] + "/etc/apps/" + app + "/appserver/static/components/localization/" key_checking = { "app": "text", "analytic_story": "text", "bookmark_notes": "text", "bookmark_status": "text", "bookmark_status_display": "text", "bookmark_user": "text", "datasource": "text", "create_data_inventory": "boolean", "datasources": "text", "datamodel": "text", "name": "text", "inSplunk": "text", "journey": "text", "usecase": "text", "highlight": "text", "alertvolume": "text", "severity": "text", "category": "text", "description": "text", "displayapp": "text", "domain": "text", "gdpr": "text", "gdprtext": "text", "hasSearch": "text", "hasContentMapping": "text", "industryMapping": "text", "escu_nist": "text", "escu_cis": "text", "soarPlaybookAvailable": "text", "mitre": "text", "released": "text", "killchain": "text", "SPLEase": "text", "searchkeywords": "text", "advancedtags": "text", "printable_image": "text", "icon": "text", "company_logo": "text", "company_logo_width": "text", "company_logo_height": "text", "company_name": "text", "company_description": "text", "company_link": "text", "dashboard": "text", "relevance": "text", "help": "text", "howToImplement": "text", "knownFP": "text", "operationalize": "text", "search": "spl", "data_source_categories": "text", "mitre_technique": "text", "mitre_sub_technique": "text", "mitre_tactic": "text", "additional_context": "array", "additional_context.title": "text", "additional_context.search_label": "text", "additional_context.detail": "text", "additional_context.link": "text", "additional_context.search_lang": "text", "additional_context.search": "spl", "additional_context.open_panel": "boolean", "open_search_panel": "boolean" } debug.append("Stage -5 Time Check:" + str(time.time() - start_time) ) try: input = json.loads(in_string) sessionKey = input['session']['authtoken'] owner = input['session']['user'] if "query" in input: for pair in input['query']: if pair[0] == "app": app = pair[1] elif pair[0] == "hideExcludedContent": if pair[1] == "false": includeSSEFilter = False elif pair[0] == "ignoreChannelExclusion": if pair[1] == "true": ignore_channel_exclusion = True elif pair[0] == "fields": if pair[1] == "mini": field_list_version = "mini" elif pair[0] == "summaryId": summary_id = pair[1] # elif pair[0] == "caching": # if pair[1] == "cached": # caching = "cached" # if pair[1] == "requireupdate": # caching = "requireupdate" # if pair[1] == "updateonly": # caching = "updateonly" elif pair[0] == "locale": if pair[1] in valid_locales: desired_locale = "." + pair[1] except: return {'payload': json.dumps({"response": "Error! Couldn't find any initial input. This shouldn't happen."}), 'status': 500 # HTTP status code } #caching = "cached" debug.append("Stage -4 Time Check:" + str(time.time() - start_time) ) try: # Getting configurations mgmtHostname, mgmtHostPort = getConfKeyValue('web', 'settings', 'mgmtHostPort').split(":") base_url = "https://" + mgmtHostname + ":" + mgmtHostPort except Exception as e: debug.append(json.dumps({"status": "ERROR", "description": "Error getting the base_url configuration!", "message": str(e), "traceback": traceback.format_exc()})) throwErrorMessage = True debug.append("Stage -3 Time Check:" + str(time.time() - start_time) ) try: service = client.connect(host=mgmtHostname, port=mgmtHostPort, token=sessionKey) service.namespace['owner'] = 'nobody' service.namespace['app'] = 'Splunk_Security_Essentials' except Exception as e: debug.append(json.dumps({"status": "ERROR", "description": "Error grabbing a service object", "message": str(e), "traceback": traceback.format_exc()})) throwErrorMessage = True debug.append("Stage -4 Time Check:" + str(time.time() - start_time) ) def clean_content(obj, key_checking, path=""): for field in list(obj.keys()): try: if path + field not in key_checking: del obj[field] debug.append({"status": "WARN", "msg": "clean_content, deleting field not in key_checking", "path": path, "field": field, "key_checking": key_checking}) elif obj[field] == None: del obj[field] debug.append({"status": "WARN", "msg": "clean_content, deleting field set to None", "field": field}) elif key_checking[path + field] == "text": obj[field] = BeautifulSoup(obj[field], "lxml").text elif key_checking[path + field] == "boolean": if not isinstance(obj[field], bool): debug.append({"status": "WARN", "msg": "clean_content, deleting field because it's not actually a bool", "path": path, "field": field, "value": obj[field]}) del obj[field] elif key_checking[path + field] == "number": obj[field] = BeautifulSoup(obj[field], "lxml").text elif key_checking[path + field] == "object": obj[field] = clean_content(obj[field], key_checking, path + field + ".") elif key_checking[path + field] == "array": debug.append({"status": "INFO", "msg": "clean_content, found an array field", "field": field}) for i in list(range(0, len(obj[field]) )): debug.append({"status": "INFO", "msg": "clean_content, looking at an array row", "field": field, "row": obj[field][i], "isInstance": isinstance(row, object)}) if isinstance(obj[field][i], object): obj[field][i] = clean_content(obj[field][i], key_checking, path + field + ".") debug.append({"status": "INFO", "msg": "clean_content, got my final row", "field": field, "row": obj[field][i], "isInstance": isinstance(row, object)}) # obj[field] = clean_content(obj[field], key_checking, path + field + ".") elif key_checking[path + field] == "spl": nochecking = True # We handle this in javascript by doing $("
").text(summary.search) -- jquery strips out invalid characters.
                except Exception as e:
                    del obj[field]
                    debug.append({"status": "ERROR", "msg": "clean_content, error'd while trying to clean content", "error": str(e), "path": path, "field": field, "key_checking": key_checking})

            # debug.append({"status": "INFO", "msg": "clean_content, final obj", "obj": obj})
            return obj
        def isSPLDangerous(spl):
            try: 
                total_url = "/services/search/jobs"
                request = six.moves.urllib.request.Request(total_url,
                    headers = { 'Authorization': ('Splunk %s' % sessionKey)})
                search_results = six.moves.urllib.request.urlopen(request)
            except:
                return true

        def getKVStoreById(store, id):

            try:
                # service = client.connect(token=sessionKey)
                # service.namespace['owner'] = 'nobody'
                # service.namespace['app'] = 'Splunk_Security_Essentials'
                kvstore_output = service.kvstore[store].data.query_by_id(id)
                debug.append({"message": "I got a kvstorebyid request", "store": store, "id": id, "returningkey": kvstore_output["_key"]})
            except Exception as e:
                #request = urllib2.Request(base_url + '/servicesNS/nobody/' + app + '/storage/collections/data/sse_json_doc_storage/?query={"_key":"' + "sseshowcase" + desired_locale + '"}',
                total_url = base_url + '/servicesNS/nobody/' + app + "/storage/collections/data/" + store + "/" + id
                debug.append({"status": "Failed to do primary method, reverting to old", "url": total_url, "error": str(e)})
                request = six.moves.urllib.request.Request(total_url,
                    headers = { 'Authorization': ('Splunk %s' % sessionKey)})
                search_results = six.moves.urllib.request.urlopen(request)

                kvstore_output = json.loads(search_results.read())
                debug.append({"message": "I got a kvstorebyid request", "store": store, "id": id, "returningkey": kvstore_output["_key"]})
            
            return kvstore_output

        def getKVStore(store):
            debug.append({"message": "I got a kvstore request", "store": store})
            try:
                # service = client.connect(token=sessionKey)
                # service.namespace['owner'] = 'nobody'
                # service.namespace['app'] = 'Splunk_Security_Essentials'
                kvstore_output = service.kvstore[store].data.query()
            except Exception as e:
                total_url = base_url + '/servicesNS/nobody/' + app + "/storage/collections/data/" + store
                debug.append({"status": "Failed to do primary method, reverting to old", "url": total_url, "traceback": traceback.format_exc(), "error": str(e)})
                request = six.moves.urllib.request.Request(total_url,
                    headers = { 'Authorization': ('Splunk %s' % sessionKey)})
                search_results = six.moves.urllib.request.urlopen(request)

                kvstore_output = json.loads(search_results.read())
            return kvstore_output
        debug.append({"localecheck": desired_locale})
        # if caching == "cached":
        #     total_url = ""
        #     try:
        #         # Now to grab kvstore collection data
        #         kvstore_output = getKVStoreById("sse_json_doc_storage", "sseshowcase" + desired_locale)

        #         debug.append("We're using a kvstore cache for this page load")
        #         # debug.append(kvstore_output)
        #         if kvstore_output:
        #             globalSourceList = json.loads(kvstore_output['json'])
        #             debug.append("I found a kvstore cache for the showcase")
        #             #debug.append(kvstore_output['json'])

        #             try:
        #                 debug.append("Time to render:" + str(time.time() - start_time) )
        #             except:
        #                 debug.append("Couldn't add the time taken")

                    
        #             globalSourceList['debug'] = debug
        #             globalSourceList['throwError'] = throwErrorMessage
        #             return {'payload': globalSourceList,  
        #                     'status': 200          # HTTP status code
        #             }

        #     except Exception as e:
        #         debug.append(json.dumps({"status": "ERROR", "description": "Failed to grab cached sseshowcase", "backup_url": total_url, "desired_locale": desired_locale, "message": str(e), "traceback": traceback.format_exc()}))
        #         throwErrorMessage = False
        # else:
        #     debug.append("Not going cached! Prepare for a long ride.")


        debug.append("Stage -1 Time Check:" + str(time.time() - start_time) )
        try: 
            conf_Stanzas = getConfStanzas("essentials_updates")
            debug.append({"msg": "Channels Configuration Stanzas", "output": conf_Stanzas})
            # standardObjects = ["ES", "ESCU", "UBA", "SSE"]
            for cfg in conf_Stanzas:
                # cfg = getConfStanza('essentials_updates', stanza)
                # setting = cfg.get('disabled')
                # channel = cfg.get('channel')
                # debug.append({"msg": "Channels - got config", "cfg": cfg})
                setting = None 
                if "disabled" in conf_Stanzas[cfg]:
                    setting = conf_Stanzas[cfg]["disabled"]
                channel = None 
                if "channel" in conf_Stanzas[cfg]:
                    channel = conf_Stanzas[cfg]['channel']    
                name = channel 
                if "name" in conf_Stanzas[cfg]:
                    name = conf_Stanzas[cfg]['name']    
                # debug.append({"msg": "Channels - got stanza", "stanzaName": cfg, "disabled": setting, "channel": channel})
                if channel is not None and channel != "":    
                    channel_to_name[channel] = name
                    if setting is None or setting == "" or setting == 0 or setting == False or setting == "false" or setting == "FALSE":
                        channel_exclusion[channel] = False
                    else:
                        channel_exclusion[channel] = True
            debug.append({"msg": "Final Channel Exclusion", "channel_exclusion": channel_exclusion, "override": ignore_channel_exclusion})
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error grabbing config objects", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        debug.append("Stage 0 Time Check:" + str(time.time() - start_time) )

        from MitreAttackInfo import MitreAttackInfo
        info = MitreAttackInfo(sessionKey)
        mitre_attack_blob = info.returnMitreAttackBlob()
        debug.append("Stage 1 Time Check:" + str(time.time() - start_time) )
            

        debug.append("Stage 2 Time Check:" + str(time.time() - start_time) )
        try:
            # Now to grab kvstore collection data
            kvstore_output = getKVStore("bookmark") #service.kvstore['bookmark'].data.query()
            for i in kvstore_output:
                bookmarks[i['_key']] = i

        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing bookmark kvstore", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        # convert the ids to the actual display names from the kvstore
        try: 
            bookmark_names = getKVStore("bookmark_names")
            bookmark_content = json.loads(json.dumps(bookmark_names))

            for i in bookmark_content:
                if i["referenceName"] == "":
                    s = i["name"].title().replace(" ", "")
                    s = s[0].lower() + s[1:]
                    i["referenceName"] = s

                bookmark_display_names[i["referenceName"]] = i["name"]
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing bookmark_names kvstore", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        debug.append("Stage 3 Time Check:" + str(time.time() - start_time) )
        try:
            kvstore_output = getKVStore("local_search_mappings")# service.kvstore['local_search_mappings'].data.query()
            for i in kvstore_output:
                if ('showcaseId' in i and i['showcaseId']!="" and i['showcaseId'] not in search_mappings):
                    search_mappings[i['showcaseId']] = []
                if ('showcaseId' in i and i['showcaseId']!=""):
                    search_mappings[i['showcaseId']].append(i['search_title'])
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing local_search_mappings", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        debug.append("Stage 4 Time Check:" + str(time.time() - start_time) )
        # try:
            # kvstore_output = getKVStore("data_source_check") # service.kvstore['data_source_check'].data.query()
            # for i in kvstore_output:
            #     if " - Demo" in i['searchName'] or ( i['showcaseId'] in kvstore_data_status and kvstore_data_status[ i['showcaseId'] ] == "Good" ):
            #         continue
            #     kvstore_data_status[i['showcaseId']] = i['status']

        # except Exception as e:
        #     debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing data_source_check", "message": str(e), "traceback": traceback.format_exc()}))
        #     throwErrorMessage = True
        
        debug.append("Stage 5 Time Check:" + str(time.time() - start_time) )
        
        try:
            kvstore_output = getKVStore("data_inventory_products") # service.kvstore['data_inventory_products'].data.query()
            # debug.append({"msg": "Got my kvstore output", "output": kvstore_output})
            for row in kvstore_output:
                if "eventtypeId" in row and row["eventtypeId"] != "" and row["eventtypeId"] != None:
                    eventtypes = row['eventtypeId'].split("|")
                    # debug.append({"msg": "Product Prep", "product": row['productId'], "dsc_string": row['eventtypeId'], "dsc": eventtypes, "stage": row['stage'], "status": row['status'], "row": row })
                    for eventtype in eventtypes:
                        if eventtype not in dsc_to_productIds:
                            dsc_to_productIds[eventtype] = []
                            dsc_to_da_scores[eventtype] = []
                            
                        dsc_to_productIds[eventtype].append(row['productId'])
                        
                        if row['stage'] in ['all-done', 'step-review', 'step-eventsize', 'step-volume', 'manualnodata']:
                            if 'coverage_level' in row and row['coverage_level'] != "" and int(row['coverage_level']) != -1:
                                dsc_to_da_scores[eventtype].append(int(row['coverage_level']))
                                # debug.append({"msg": "ADDED PRODUCT W/ Real Coverage", "product": row['productId'], "dsc": eventtype, "stage": row['stage'], "status": row['status'], "coverage_level": row['coverage_level'], "row": row })
                            else: 
                                dsc_to_da_scores[eventtype].append(100)
                                # debug.append({"msg": "ADDED PRODUCT but made up coverage", "product": row['productId'], "dsc": eventtype, "stage": row['stage'], "status": row['status'], "row": row })
                        # else:
                        #     debug.append({"msg": "DID NOT ADD PRODUCT", "product": row['productId'], "dsc": eventtype, "stage": row['stage'], "status": row['status'], "row": row })
                        product_details[row['productId']] = row
            for eventtype in dsc_to_productIds:
                dsc_to_productIds[eventtype] = "|".join(dsc_to_productIds[eventtype])
            # debug.append({"step": "genningProductIdFinal", "list": dsc_to_productIds})

        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing data_inventory_products", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        debug.append("Stage 6 Time Check:" + str(time.time() - start_time) )
        try:
            custom_content_input = getKVStore('custom_content')
            for row in custom_content_input:
                try:
                    row['json'] = json.dumps(clean_content(json.loads(row['json']), key_checking))
                    custom_content.append(row)
                    # debug.append({"msg": "successfully added cleaned custom content", "showcaseId": row['showcaseId'], "obj": row})
                except Exception as e:
                    debug.append({"msg": "Got an error when trying to clean custom content", "obj": row, "error": str(e)})
                # for field in custom_content:
            #     debug.append(i)
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing custom_content", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        # debug.append("Stage 7 Time Check:" + str(time.time() - start_time) )
        # try:
        #     kvstore_output = getKVStore('data_inventory_eventtypes')
        #     for i in kvstore_output:
        #         eventtypes_data_status[i['eventtypeId']] = i['status']
        #         if "coverage_level" in i and i["coverage_level"] != "" and i['status'] == "complete":
        #             eventtypes_coverage_level[i['eventtypeId']] = i['coverage_level']
        # except Exception as e:
        #     debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing data_inventory_eventtypes", "message": str(e), "traceback": traceback.format_exc()}))
        #     throwErrorMessage = True
        
            
        debug.append("Stage 8 Time Check:" + str(time.time() - start_time) )
        try:
            # Now to grab files off the filesystem
            for myApp in myApps:                
                # Getting Showcaseinfo using pullJSON endpoint
                try:
                    # Getting configurations
                    url = base_url + '/services/pullJSON?config=showcaseinfo&locale=' + desired_locale
                    request = six.moves.urllib.request.Request(url,
                        headers = { 'Authorization': ('Splunk %s' % sessionKey)})
                    search_results = six.moves.urllib.request.urlopen(request)

                    data = json.loads(search_results.read())
                    
                except Exception as e:
                    debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while grabbing mitre attack", "url": url, "message": str(e), "traceback": traceback.format_exc()}))
                    throwErrorMessage = True
                
                if "summaries" not in globalSourceList:
                    globalSourceList = data 
                else:
                    for summaryName in data['summaries']:
                        if summaryName not in globalSourceList['summaries']:
                            data['summaries'][summaryName]['channel'] = "Splunk_Security_Essentials"
                            data['summaries'][summaryName]['showcaseId'] = summaryName
                            globalSourceList['summaries'][summaryName] = data['summaries'][summaryName]
                            globalSourceList['roles']['default']['summaries'].append(summaryName)
        except Exception as e:
                debug.append(json.dumps({"status": "ERROR", "description": "Fatal Error grabbing ShowcaseInfo", "message": str(e), "traceback": traceback.format_exc()}))
                throwErrorMessage = True

        debug.append("Stage 9 Time Check:" + str(time.time() - start_time) )
        try: 
            # debug.append("# of summaries: " + str(len(globalSourceList['roles']['default']['summaries'])))
            for content in custom_content:
                showcase = json.loads(content['json'])
                if "create_data_inventory" in showcase: 
                    showcase["data_source_categories"] = "VendorSpecific-" + content['channel']
                showcase['custom_user'] = content['user']
                showcase['custom_time'] = content['_time']
                showcase['includeSSE'] = "Yes"
                if "search" in showcase and showcase["search"] != "" and "hasSearch" not in showcase:
                    showcase['hasSearch'] = "Yes"
                showcase['channel'] = content['channel']
                if content['channel'] in channel_to_name:
                    showcase['displayapp'] = channel_to_name[content['channel']]
                    showcase['app'] = content['channel']
                elif content['channel'].startswith('custom_'):
                    showcase['displayapp'] = content['channel'].split("_")[1]
                    showcase['app'] = 'custom'
                    showcase['channel'] = 'custom'
                else:
                    showcase['displayapp'] = content['channel']
                    showcase['app'] = content['channel']
                if 'icon' not in showcase or showcase['icon'] == "" and content['channel'].startswith('custom_') and content['channel'].split('custom_')[1][0].isalpha():
                    showcase['icon'] = showcase['displayapp'][0].lower()+".png"
                elif 'icon' not in showcase or showcase['icon'] == "" or showcase['icon'] == ".png":
                    showcase['icon'] = "custom_content.png"
                if 'showcaseId' in content and content['showcaseId'] != "" and 'dashboard' not in showcase or showcase['dashboard'] == "":
                    showcase['dashboard'] = "showcase_custom?showcaseId=" + content['showcaseId']
                globalSourceList['roles']['default']['summaries'].append(content['showcaseId'])
                globalSourceList['summaries'][content['showcaseId']] = showcase
                debug.append("# of summaries: " + str(len(globalSourceList['roles']['default']['summaries'])))
            # debug.append("# of summaries: " + str(len(globalSourceList['roles']['default']['summaries'])))
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while enriching with custom content", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        
        debug.append("Stage 10 Time Check:" + str(time.time() - start_time) )

        try:
            # Getting configurations
            url = base_url + '/services/pullJSON?config=data_inventory'
            request = six.moves.urllib.request.Request(url,
                headers = { 'Authorization': ('Splunk %s' % sessionKey)})
            search_results = six.moves.urllib.request.urlopen(request)

            data_inventory = json.loads(search_results.read())
            for datasource in data_inventory:
                eventtype_names[datasource] = data_inventory[datasource]['name']
                for eventtype in data_inventory[datasource]['eventtypes']:
                    dsc_to_ds_name[eventtype] = data_inventory[datasource]['name'] 
                    eventtype_names[eventtype] = data_inventory[datasource]['eventtypes'][eventtype]['name']
                    if "legacy_name" in data_inventory[datasource]['eventtypes'][eventtype]:
                        eventtype_to_legacy_names[eventtype] = data_inventory[datasource]['eventtypes'][eventtype]["legacy_name"]
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error grabbing data_inventory.json", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 11 Time Check:" + str(time.time() - start_time) )

        try:
            myAssistants = ["showcase_first_seen_demo", "showcase_standard_deviation", "showcase_simple_search"]
            for assistant in myAssistants:
                with open(os.environ['SPLUNK_HOME'] + "/etc/apps/" + myApps[0] + "/appserver/static/components/data/sampleSearches/" + assistant + ".json") as f:
                    data = json.load(f)
                    globalSearchList.update(data)
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error grabbing showcase JSONs", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 12 Time Check:" + str(time.time() - start_time) )
        try:
            for obj in mitre_attack_blob['objects']:
                if "type" in obj and obj['type'] == "relationship":
                    if "intrusion-set" in obj['source_ref'] and "attack-pattern" in obj['target_ref'] and obj["relationship_type"] == "uses":
                        if obj['target_ref'] not in mitre_refs_to_refs:
                            mitre_refs_to_refs[obj['target_ref']] = []
                        mitre_refs_to_refs[obj['target_ref']].append(obj['source_ref'])
                    if "intrusion-set" in obj['target_ref'] and "attack-pattern" in obj['source_ref']:
                        if obj['source_ref'] not in mitre_refs_to_refs:
                            mitre_refs_to_refs[obj['source_ref']] = []
                        mitre_refs_to_refs[obj['source_ref']].append(obj['target_ref'])
                    if ("tool" in obj['source_ref'] or "malware" in obj['source_ref']) and "attack-pattern" in obj['target_ref'] and obj["relationship_type"] == "uses":
                        if obj['target_ref'] not in mitre_refs_to_refs:
                            mitre_refs_to_refs[obj['target_ref']] = []
                        mitre_refs_to_refs[obj['target_ref']].append(obj['source_ref'])
                    if ("tool" in obj['target_ref'] or "malware" in obj['target_ref']) and "attack-pattern" in obj['source_ref']:
                        if obj['source_ref'] not in mitre_refs_to_refs:
                            mitre_refs_to_refs[obj['source_ref']] = []
                        mitre_refs_to_refs[obj['source_ref']].append(obj['target_ref'])

                if "type" in obj and obj['type'] == "intrusion-set":
                    mitre_refs_to_names[obj['id']] = obj['name']
                    for reference in obj['external_references']:
                        if "url" in reference and "https://attack.mitre.org/groups/" in reference['url']:
                            mitre_refs_to_ids[obj['id']] = reference['external_id']
                    # if "description" in obj:
                    #     mitre_group_name_to_description[obj['name']] = obj['description']
                    mitre_group_name_to_id[obj['name']] = obj['id']
                if "type" in obj and (obj['type'] == "tool" or obj['type'] == "malware"):
                    mitre_refs_to_names[obj['id']] = obj['name']
                    for reference in obj['external_references']:
                        if "url" in reference and "https://attack.mitre.org/software/" in reference['url']:
                            mitre_refs_to_ids[obj['id']] = reference['external_id']
                    # if "description" in obj:
                    #     mitre_group_name_to_description[obj['name']] = obj['description']
                    mitre_software_name_to_id[obj['name']] = obj['id']
                if "external_references" in obj:
                    for reference in obj['external_references']:
                        if "type" in obj and obj["type"] == "attack-pattern" and "external_id" in reference and "." not in reference["external_id"] and "description" in obj and "url" in reference and "https://attack.mitre.org/techniques/" in reference['url']:
                            mitre_technique_descriptions[reference['external_id']] = obj['description']
                        if "type" in obj and obj["type"] == "attack-pattern"  and "description" in obj and "url" in reference and "https://attack.mitre.org/techniques/" in reference['url']:
                            keywords = list(set(re.findall( r'\[([^\]]*)\]\(', obj['description'])))
                            if keywords:
                                mitre_keywords[reference['external_id']] = keywords
                            if "x_mitre_platforms" in obj:
                                mitre_platforms[reference['external_id']] = obj['x_mitre_platforms']
                        if "url" in reference and "type" in obj and (obj["type"] == "attack-pattern" or obj["type"] == "x-mitre-tactic") and ( "https://attack.mitre.org/techniques/" in reference['url'] or "https://attack.mitre.org/tactics/" in reference['url'] ):
                            mitre_names['attack'][reference['external_id']] = obj['name']
                            mitre_refs_to_names[obj['id']] = reference['external_id']
                            
            for ref in mitre_refs_to_refs:
                for refvalue in mitre_refs_to_refs[ref]:
                    if mitre_refs_to_names[ref] not in popularTechniques:
                        popularTechniques[mitre_refs_to_names[ref]] = 1
                        # debug.append({"item": "mapping", "technique": mitre_refs_to_names[ref], "group": mitre_refs_to_names[refvalue], "count": 1})
                    else:
                        popularTechniques[mitre_refs_to_names[ref]] += 1
                        # debug.append({"item": "mapping", "technique": mitre_refs_to_names[ref], "group": mitre_refs_to_names[refvalue], "count": popularTechniques[mitre_refs_to_names[ref]]})
                    if ref in mitre_refs_to_names and refvalue in mitre_refs_to_names:
                        if "intrusion-set" in refvalue and mitre_refs_to_names[ref] not in mitre_techniques_to_groups:
                            mitre_techniques_to_groups[mitre_refs_to_names[ref]] = []
                            # mitre_techniques_to_group_objs[mitre_refs_to_names[ref]] = []
                        if "intrusion-set" in refvalue and mitre_refs_to_names[refvalue] not in mitre_techniques_to_groups[mitre_refs_to_names[ref]]:
                            mitre_techniques_to_groups[mitre_refs_to_names[ref]].append(mitre_refs_to_names[refvalue])
                            # reference = {
                            #     "technique_name": "",#mitre_names['attack'][mitre_refs_to_names[ref]],
                            #     "technique_id": mitre_refs_to_names[ref],
                            #     "group_name": mitre_refs_to_names[refvalue],
                            #     "group_id": mitre_refs_to_ids[refvalue]
                            # }
                            # if mitre_refs_to_names[refvalue] in mitre_group_name_to_description:
                            #     reference["group_description"] = mitre_group_name_to_description[mitre_refs_to_names[refvalue]]
                            # localID = refvalue + ref
                            # if localID in group_ref_technique_ref_to_details:
                            #     reference["external_references"] = group_ref_technique_ref_to_details[localID]['external_references']
                            #     reference["description"] = group_ref_technique_ref_to_details[localID]['description']
                            #     # reference["dvdebug"] = JSON.dumps(mitre_group_name_to_description)
                            # mitre_techniques_to_group_objs[mitre_refs_to_names[ref]].append(reference)
                        if ("tool" in refvalue or "malware" in refvalue) and mitre_refs_to_names[ref] not in mitre_techniques_to_software:
                            mitre_techniques_to_software[mitre_refs_to_names[ref]] = []
                        if ("tool" in refvalue or "malware" in refvalue) and mitre_refs_to_names[refvalue] not in mitre_techniques_to_software[mitre_refs_to_names[ref]]:
                            mitre_techniques_to_software[mitre_refs_to_names[ref]].append(mitre_refs_to_names[refvalue])
                        
                            
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while handling MITRE Processing", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True


        debug.append("Stage 13 Time Check:" + str(time.time() - start_time) )
        try:
            # Now we clear out any invalid characters in IDs and names
            keys = list(globalSourceList['summaries'].keys())
            debug.append("Debug Starting")
            for summaryName in keys:
                m = re.search("[^a-zA-Z0-9_]", summaryName)
                if m:
                    newSummaryName = re.sub(r"[^a-zA-Z0-9_\-]", "", summaryName)
                    globalSourceList['summaries'][newSummaryName] = globalSourceList['summaries'].pop(summaryName)
                    index = globalSourceList['roles']['default']['summaries'].index(summaryName)
                    globalSourceList['roles']['default']['summaries'][index] = newSummaryName
            
            for summaryName in globalSourceList['summaries']:    
                regex = r"\&[a-zA-Z0-9#]{2,10};"
                m = re.search(regex, globalSourceList['summaries'][summaryName]['name'])
                if m:
                    newName = re.sub(regex, "", globalSourceList['summaries'][summaryName]['name'])
                    globalSourceList['summaries'][summaryName]['name'] = newName
                # elif "Allowed" in globalSourceList['summaries'][summaryName]['name']:
                    # debug.append("NO NAME match " + globalSourceList['summaries'][summaryName]['name'])
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error Clearing!", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 14 Time Check:" + str(time.time() - start_time) )
        try:
            # Now we do enrichment and processing
            for summaryName in globalSourceList['summaries']:
                # Define all the defaults for enrichment
                globalSourceList['summaries'][summaryName]["id"] = summaryName
                globalSourceList['summaries'][summaryName]['enabled'] = "No"
                globalSourceList['summaries'][summaryName]["data_available"] = "Unknown"
                globalSourceList['summaries'][summaryName]["data_available_numeric"] = ""
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error setting the defaults for all enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 14.5 Time Check:" + str(time.time() - start_time) )
        try:
            # Now we do enrichment and processing
            for summaryName in globalSourceList['summaries']:
                # Define all the defaults for enrichment
                if globalSourceList['summaries'][summaryName]["displayapp"] == "Enterprise Security Content Update":
                    if "searchKeywords" in globalSourceList['summaries'][summaryName]:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] += " ESCU"
                    else:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] = "ESCU"
                elif globalSourceList['summaries'][summaryName]["displayapp"] == "Splunk Security Essentials":
                    if "searchKeywords" in globalSourceList['summaries'][summaryName]:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] += " SSE"
                    else:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] = "SSE"
                elif globalSourceList['summaries'][summaryName]["displayapp"] == "Splunk Enterprise Security":
                    if "searchKeywords" in globalSourceList['summaries'][summaryName]:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] += " ES"
                    else:
                        globalSourceList['summaries'][summaryName]["searchKeywords"] = "ES"
                elif globalSourceList['summaries'][summaryName]["displayapp"] == "Splunk User Behavior Analytics":
                    if "AT" in summaryName:
                        if "advancedtags" in globalSourceList['summaries'][summaryName]:
                            globalSourceList['summaries'][summaryName]["advancedtags"] += "|UBA Anomaly"
                        else: 
                            globalSourceList['summaries'][summaryName]["advancedtags"] = "UBA Anomaly"
                        if "searchKeywords" in globalSourceList['summaries'][summaryName]:
                            globalSourceList['summaries'][summaryName]["searchKeywords"] += " Anomaly"
                        else:
                            globalSourceList['summaries'][summaryName]["searchKeywords"] = "Anomaly"
                    elif "TT" in summaryName:
                        if "advancedtags" in globalSourceList['summaries'][summaryName]:
                            globalSourceList['summaries'][summaryName]["advancedtags"] += "|UBA Threat"
                        else: 
                            globalSourceList['summaries'][summaryName]["advancedtags"] = "UBA Threat"
                        if "searchKeywords" in globalSourceList['summaries'][summaryName]:
                            globalSourceList['summaries'][summaryName]["searchKeywords"] += " Threat"
                        else:
                            globalSourceList['summaries'][summaryName]["searchKeywords"] = "Threat"
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error adding in the UBA Threat and Anomaly", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True


        debug.append("Stage 15 Time Check:" + str(time.time() - start_time) )
        try:
            # Now we do enrichment and processing
            for summaryName in globalSourceList['summaries']:

                # Handle bookmark status
                if summaryName in bookmarks:
                    globalSourceList['summaries'][summaryName]['bookmark_status'] = bookmarks[summaryName]['status']
                    if "user" in bookmarks[summaryName]:
                        globalSourceList['summaries'][summaryName]['bookmark_user'] = bookmarks[summaryName]['user']
                    else: 
                        globalSourceList['summaries'][summaryName]['bookmark_user'] = "none"
                    if "notes" in bookmarks[summaryName] and bookmarks[summaryName]['notes'] != "":
                        globalSourceList['summaries'][summaryName]['bookmark_notes'] = bookmarks[summaryName]['notes']
                    else: 
                        globalSourceList['summaries'][summaryName]['bookmark_notes'] = "None"
                    if globalSourceList['summaries'][summaryName]['bookmark_status'] in bookmark_display_names:
                        globalSourceList['summaries'][summaryName]['bookmark_status_display'] = bookmark_display_names[globalSourceList['summaries'][summaryName]['bookmark_status']]
                    else:
                        globalSourceList['summaries'][summaryName]['bookmark_status_display'] = globalSourceList['summaries'][summaryName]['bookmark_status']
                
                    if globalSourceList['summaries'][summaryName]['bookmark_status'] == "successfullyImplemented":
                        globalSourceList['summaries'][summaryName]['enabled'] = "Yes"
                else:
                    globalSourceList['summaries'][summaryName]['bookmark_status'] = "none"
                    globalSourceList['summaries'][summaryName]['bookmark_status_display'] = "Not Bookmarked"
                    globalSourceList['summaries'][summaryName]['bookmark_notes'] = "None"
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error during bookmark enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 16 Time Check:" + str(time.time() - start_time) )
        try:
            for summaryName in globalSourceList['summaries']:
                # Enrich examples with the example data
                if "examples" in globalSourceList['summaries'][summaryName] and len(globalSourceList['summaries'][summaryName]['examples']) > 0:
                    for i in range(0, len(globalSourceList['summaries'][summaryName]['examples'])):
                        if globalSourceList['summaries'][summaryName]['examples'][i]['name'] in globalSearchList:
                            globalSourceList['summaries'][summaryName]['examples'][i]['showcase'] = globalSearchList[globalSourceList['summaries'][summaryName]['examples'][i]['name']]

        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error during actual search enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 17 Time Check:" + str(time.time() - start_time) )

        try:
            for summaryName in globalSourceList['summaries']:
                globalSourceList['summaries'][summaryName]['search_title'] = []
                # Enrich examples with the example data
                if summaryName in search_mappings:
                    for i in range(0, len(search_mappings[summaryName])):
                        globalSourceList['summaries'][summaryName]['search_title'].append(search_mappings[summaryName][i])
                globalSourceList['summaries'][summaryName]["search_title"] = "|".join( set(globalSourceList['summaries'][summaryName]["search_title"]) )
                if len(globalSourceList['summaries'][summaryName]["search_title"])>0:
                    globalSourceList['summaries'][summaryName]["hasContentMapping"] = "Yes"
            
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error during search mapping enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 18 Time Check:" + str(time.time() - start_time) )
        try:
            for summaryName in globalSourceList['summaries']:           
                globalSourceList['summaries'][summaryName]['productId'] = ""     
                # eventtypes_data_status
                if "data_source_categories" in globalSourceList['summaries'][summaryName]:
                    eventtypes = globalSourceList['summaries'][summaryName]['data_source_categories'].split("|")
                    eventtype_display = []
                    datasources = []
                    productIds = []
                    productNames = []
                    eventtype_data = []
                    da_score = 0
                    da_score_count = 0
                    for eventtype in eventtypes:
                        if eventtype in dsc_to_da_scores:
                            # debug.append({"msg": "Adding..", "summary": summaryName,  "dsc": eventtype, "scores": dsc_to_da_scores[eventtype]})
                            for score in dsc_to_da_scores[eventtype]:
                                da_score += score
                                da_score_count += 1
                        if eventtype in dsc_to_productIds:
                            products = dsc_to_productIds[eventtype].split("|")
                            for product in products:
                                productIds.append(product)
                                if product in product_details:
                                    if product_details[ product ]['productName'] != "":
                                        productNames.append( product_details[ product ]['vendorName'] + " - " + product_details[ product ]['productName'] )
                                    else:
                                        productNames.append( product_details[ product ]['vendorName'])
                        if eventtype in eventtype_names:
                            eventtype_display.append( eventtype_names[eventtype] )
                            if eventtype in eventtype_to_legacy_names:
                                datasources += eventtype_to_legacy_names[eventtype].split("|")
                            else:
                                datasources += dsc_to_ds_name[eventtype].split("|")
                        # if eventtype in eventtypes_coverage_level and eventtypes_coverage_level[eventtype] != "unknown":
                        #     eventtype_data.append(eventtypes_coverage_level[eventtype])
                        # elif eventtype in eventtypes_data_status and eventtypes_data_status[eventtype] != "unknown":
                        #     if isinstance(eventtypes_data_status[eventtype], str) or isinstance(eventtypes_data_status[eventtype], basestring):
                        #         if eventtypes_data_status[eventtype] == "success":
                        #             eventtype_data.append(100)
                        #         else:
                        #             eventtype_data.append(0)
                        #     elif isinstance(eventtypes_data_status[eventtype], int):
                        #         eventtype_data.append(eventtypes_data_status[eventtype])
                    # if len(eventtype_data) > 0:
                        # total = 0
                        # for num in eventtype_data:
                        #     total += num
                    if da_score_count > 0:
                        # debug.append({"msg": "analyzing da_Score", "summary": summaryName, "eventtypes": eventtypes, "total": da_score, "count": da_score_count, "avg": round(da_score / da_score_count)})
                        globalSourceList['summaries'][summaryName]["data_available_numeric"] = round(da_score / da_score_count)
                        if globalSourceList['summaries'][summaryName]["data_available_numeric"] >= 20:
                            globalSourceList['summaries'][summaryName]["data_available"] = "Available"
                        else:
                            globalSourceList['summaries'][summaryName]["data_available"] = "Unavailable"
                            globalSourceList['summaries'][summaryName]["data_available_numeric"] = 0
                    else:
                        # debug.append({"msg": "analyzing ZERO da_score_count", "summary": summaryName, "eventtypes": eventtypes, "total": da_score, "count": da_score_count})
                        globalSourceList['summaries'][summaryName]["data_available"] = "Unavailable"
                        globalSourceList['summaries'][summaryName]["data_available_numeric"] = 0
                    # else:
                    #     globalSourceList['summaries'][summaryName]["data_available"] = "Bad"
                    #     globalSourceList['summaries'][summaryName]["data_available_numeric"] = 0
                    
                    globalSourceList['summaries'][summaryName]['data_source_categories_display'] = "|".join( eventtype_display )
                    globalSourceList['summaries'][summaryName]['datasource'] = "|".join( set( datasources ) )
                    if globalSourceList['summaries'][summaryName]['datasource'] == "":
                        globalSourceList['summaries'][summaryName]['datasource'] = "None"
                    globalSourceList['summaries'][summaryName]['productId'] = "|".join( productIds )
                    globalSourceList['summaries'][summaryName]['product'] = "|".join( productNames )

                # globalSourceList['summaries'][summaryName]['data_source_categories'] = globalSourceList['summaries'][summaryName]['data_source_categories']
                # globalSourceList['summaries'][summaryName]['data_source_categories_display'] = globalSourceList['summaries'][summaryName]['data_source_categories_display']
                # Probably this should be disabled...
                # if summaryName in kvstore_data_status:
                #   globalSourceList['summaries'][summaryName]['data_available'] = kvstore_data_status[summaryName]
                
                # Check if data is inSplunk=no
                if "inSplunk" in globalSourceList['summaries'][summaryName]:
                    inSplunk = globalSourceList['summaries'][summaryName]['inSplunk']
                    if inSplunk.lower() == "no":
                        globalSourceList['summaries'][summaryName]["data_available"] = "Available"
                        globalSourceList['summaries'][summaryName]["data_available_numeric"] = 100


        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error during Data Availability Enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 19 Time Check:" + str(time.time() - start_time) )
        try:
            
            for summaryName in globalSourceList['summaries']:                

                #Do Mitre Display Name Mapping
                globalSourceList['summaries'][summaryName]["mitre_tactic_display"] = []
                globalSourceList['summaries'][summaryName]["mitre_technique_display"] = []
                globalSourceList['summaries'][summaryName]["mitre_sub_technique_display"] = []
                globalSourceList['summaries'][summaryName]["mitre_matrix"] = []
                globalSourceList['summaries'][summaryName]["mitre_technique_description"] = []
                globalSourceList['summaries'][summaryName]["mitre_technique_combined"] = []
                globalSourceList['summaries'][summaryName]["mitre_id"] = []
                globalSourceList['summaries'][summaryName]["mitre_keywords"] = []
                globalSourceList['summaries'][summaryName]["mitre_platforms"] = []
                globalSourceList['summaries'][summaryName]["mitre_software"] = []
                
                
                # if summaryName == "basic_brute_force":
                #     globalSourceList["summaries"][summaryName]["mitre_data"] = json.dumps(mitre_names["attack"])
                # globalSourceList['summaries'][summaryName]["mitre_technique_group_json"] = {}
                technique_popularity = []
                # debug.append({"debug": "popularity", "list": popularTechniques})
                if "mitre_tactic" in globalSourceList['summaries'][summaryName]:
                    tactics = globalSourceList['summaries'][summaryName]["mitre_tactic"].split("|")
                    for tactic in tactics:
                        if tactic != "":
                            if tactic in mitre_names['attack']:
                                globalSourceList['summaries'][summaryName]["mitre_tactic_display"].append(mitre_names['attack'][tactic])
                                globalSourceList['summaries'][summaryName]["mitre_matrix"].append("Enterprise ATT&CK")
                            # elif tactic in mitre_names['preattack']:
                            #     globalSourceList['summaries'][summaryName]["mitre_tactic_display"].append(mitre_names['preattack'][tactic])
                            #     globalSourceList['summaries'][summaryName]["mitre_matrix"].append("PRE-ATT&CK")
                            else:
                                globalSourceList['summaries'][summaryName]["mitre_tactic_display"].append(tactic)
                if "mitre_technique" in globalSourceList['summaries'][summaryName]:
                    #Dedup list
                    globalSourceList['summaries'][summaryName]["mitre_technique"] = "|".join(list(set(globalSourceList['summaries'][summaryName]["mitre_technique"].split("|"))))
                    techniques = globalSourceList['summaries'][summaryName]["mitre_technique"].split("|")
                    for technique in techniques:
                        if technique != "" and "." not in technique:
                            if technique in popularTechniques:
                                technique_popularity.append(popularTechniques[technique])
                            else:
                                technique_popularity.append(0)
                            if technique in mitre_technique_descriptions:
                                globalSourceList['summaries'][summaryName]["mitre_technique_description"].append( mitre_technique_descriptions[technique] )
                            if technique in mitre_keywords:
                                globalSourceList['summaries'][summaryName]["mitre_keywords"] +=  mitre_keywords[technique]
                            if technique in mitre_platforms:
                                globalSourceList['summaries'][summaryName]["mitre_platforms"] +=  mitre_platforms[technique]
                            if technique in mitre_techniques_to_software:
                                globalSourceList['summaries'][summaryName]["mitre_software"] = [*globalSourceList['summaries'][summaryName]["mitre_software"], *mitre_techniques_to_software[technique]]
                            # if technique in mitre_techniques_to_group_objs:
                            #     for group in mitre_techniques_to_group_objs[technique]:
                            #         # if group['group_name'] not in globalSourceList['summaries'][summaryName]["mitre_technique_group_json"]:
                            #             # globalSourceList['summaries'][summaryName]["mitre_technique_group_json"][group['group_name']] = []
                            #         if group['technique_id'] in mitre_names["attack"]:
                            #             group["technique_name"] = mitre_names["attack"][ group['technique_id'] ]
                            #         # globalSourceList['summaries'][summaryName]["mitre_technique_group_json"][group['group_name']].append(group)
                            if technique in mitre_names["attack"]:
                                globalSourceList['summaries'][summaryName]["mitre_technique_display"].append(mitre_names['attack'][technique])
                                globalSourceList['summaries'][summaryName]["mitre_id"].append(technique)
                                globalSourceList['summaries'][summaryName]["mitre_technique_combined"].append(technique + " - " + mitre_names['attack'][technique])
                                globalSourceList['summaries'][summaryName]["mitre_matrix"].append("Enterprise ATT&CK")
                            else:
                                globalSourceList['summaries'][summaryName]["mitre_technique_display"].append(technique)
                        elif technique != "" and "." in technique:
                            #There's a Sub-technique in the technique field. Add it there instead
                            if "mitre_sub_technique" not in globalSourceList['summaries'][summaryName]:
                                globalSourceList['summaries'][summaryName]["mitre_sub_technique"] = ""
                            globalSourceList['summaries'][summaryName]["mitre_sub_technique"] += "|" + technique
                            #Remove Sub-technique from the technique field.
                            techniques_temp=list(set(globalSourceList['summaries'][summaryName]["mitre_technique"].split("|")))
                            techniques_temp.remove(technique)
                            globalSourceList['summaries'][summaryName]["mitre_technique"] = "|".join(techniques_temp)
                            del techniques_temp

                if "mitre_sub_technique" in globalSourceList['summaries'][summaryName]:
                    #Dedup list
                    globalSourceList['summaries'][summaryName]["mitre_sub_technique"] = "|".join(list(set(globalSourceList['summaries'][summaryName]["mitre_sub_technique"].split("|"))))
                    sub_techniques = globalSourceList['summaries'][summaryName]["mitre_sub_technique"].split("|")
                    #If we have a sub-technique, use the link to other objects in the matrix from the sub-technique and discard any link from the technique itself. Hence resets below. 
                    globalSourceList['summaries'][summaryName]["mitre_platforms"] = []
                    globalSourceList['summaries'][summaryName]["mitre_software"] = []
                    for sub_technique in sub_techniques:
                        if sub_technique != "":
                            if (sub_technique[0:5] in globalSourceList['summaries'][summaryName]["mitre_id"]):
                                #Remove the technique from mitre_id if we have sub_techniques
                                globalSourceList['summaries'][summaryName]["mitre_id"].remove(sub_technique[0:5])
                                #globalSourceList['summaries'][summaryName]["mitre_technique_combined"].remove(sub_technique[0:5])
                            if sub_technique in popularTechniques:
                                technique_popularity.append(popularTechniques[sub_technique])
                            else:
                                technique_popularity.append(0)
                            if sub_technique in mitre_technique_descriptions:
                                globalSourceList['summaries'][summaryName]["mitre_technique_description"].append( mitre_technique_descriptions[sub_technique] )
                            if sub_technique in mitre_keywords:
                                globalSourceList['summaries'][summaryName]["mitre_keywords"] +=  mitre_keywords[sub_technique]
                            if sub_technique in mitre_platforms:
                                globalSourceList['summaries'][summaryName]["mitre_platforms"] =  [*globalSourceList['summaries'][summaryName]["mitre_platforms"],*mitre_platforms[sub_technique]]
                            if sub_technique in mitre_techniques_to_software:
                                globalSourceList['summaries'][summaryName]["mitre_software"] = [*globalSourceList['summaries'][summaryName]["mitre_software"], *mitre_techniques_to_software[sub_technique]]
                            if sub_technique in mitre_names["attack"]:
                                globalSourceList['summaries'][summaryName]["mitre_sub_technique_display"].append(mitre_names['attack'][sub_technique])
                                globalSourceList['summaries'][summaryName]["mitre_id"].append(sub_technique)   
                            else:
                                globalSourceList['summaries'][summaryName]["mitre_sub_technique_display"].append(sub_technique)
                total = 0
                count = 0
                for item in technique_popularity:
                    count += 1
                    total += item
                if count > 0:
                    globalSourceList['summaries'][summaryName]["mitre_techniques_avg_group_popularity"] = str(round(total / count, 2))
                globalSourceList['summaries'][summaryName]["mitre_software"] = list(set(  globalSourceList['summaries'][summaryName]["mitre_software"] )) 
                globalSourceList['summaries'][summaryName]["mitre_software"].sort()
                # globalSourceList['summaries'][summaryName]["mitre_technique_group_json"] = json.dumps(globalSourceList['summaries'][summaryName]["mitre_technique_group_json"])
                globalSourceList['summaries'][summaryName]["mitre_tactic_display"] = "|".join(globalSourceList['summaries'][summaryName]["mitre_tactic_display"])
                globalSourceList['summaries'][summaryName]["mitre_technique_display"] = "|".join(globalSourceList['summaries'][summaryName]["mitre_technique_display"])
                globalSourceList['summaries'][summaryName]["mitre_id"] = "|".join(globalSourceList['summaries'][summaryName]["mitre_id"])
                globalSourceList['summaries'][summaryName]["mitre_sub_technique_display"] = "|".join(globalSourceList['summaries'][summaryName]["mitre_sub_technique_display"])
                globalSourceList['summaries'][summaryName]["mitre_software"] = "|".join( globalSourceList['summaries'][summaryName]["mitre_software"] )
                globalSourceList['summaries'][summaryName]["mitre_technique_description"] = "|".join( globalSourceList['summaries'][summaryName]["mitre_technique_description"] )
                globalSourceList['summaries'][summaryName]["mitre_technique_combined"] = "|".join( set(globalSourceList['summaries'][summaryName]["mitre_technique_combined"]) )
                globalSourceList['summaries'][summaryName]["mitre_keywords"] = " | ".join( set(globalSourceList['summaries'][summaryName]["mitre_keywords"]) )
                globalSourceList['summaries'][summaryName]["mitre_matrix"] = "|".join( set(globalSourceList['summaries'][summaryName]["mitre_matrix"]) )
                
                if "Enterprise ATT&CK" in globalSourceList['summaries'][summaryName]["mitre_matrix"]:
                    globalSourceList['summaries'][summaryName]["mitre_platforms"].append("Enterprise")
                cloud_platforms = ["AWS", "GCP", "Azure", "Azure AD", "Office 365", "SaaS"]
                cloud_matrix=False
                for platform in cloud_platforms:
                    if platform in globalSourceList['summaries'][summaryName]["mitre_platforms"]:
                        cloud_matrix=True
                if cloud_matrix:
                    globalSourceList['summaries'][summaryName]["mitre_platforms"].append("Cloud")
                globalSourceList['summaries'][summaryName]["mitre_platforms"] = "|".join( set(globalSourceList['summaries'][summaryName]["mitre_platforms"]) )
                if globalSourceList['summaries'][summaryName]["mitre_platforms"] == "":
                    globalSourceList['summaries'][summaryName]["mitre_platforms"] = "None"
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error during MITRE Enrichment", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
            

        debug.append("Stage 20 Time Check:" + str(time.time() - start_time) )
        try:
            # Now we default anything that needs to be defaulted
            provide_No_Fields = ["hasSearch","hasContentMapping"]
            provide_NA_Fields = ["data_source_categories", "data_source_categories_display"]
            provide_none_Fields = []
            provide_Other_Fields = ["category"]
            provide_Empty_String_Fields = ["mitre_techniques_avg_group_popularity"]
            provide_zero_String_Fields = []
            ensure_no_null_fields = ["custom_time", "custom_user"]
            provide_Uppercasenone_Fields = ["killchain", "mitre_id", "mitre", "mitre_tactic", "mitre_technique", "mitre_sub_technique", "mitre_id", "mitre_tactic_display", "mitre_technique_display", "mitre_sub_technique_display","mitre_technique_combined","mitre_threat_groups","mitre_software","mitre_matrix","mitre_platform", "category", "SPLEase","domain","datamodel","analytic_story"]

            for summaryName in globalSourceList['summaries']:
                if "channel" not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName]['channel'] == "":
                    if "app" in globalSourceList['summaries'][summaryName]:
                        globalSourceList['summaries'][summaryName]['channel'] = globalSourceList['summaries'][summaryName]['app']
                    else:
                        globalSourceList['summaries'][summaryName]['channel'] = "Unknown"

                for field in provide_NA_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_NA_Fields:
                        globalSourceList['summaries'][summaryName][field] = "N/A"

                for field in provide_No_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_No_Fields:
                        globalSourceList['summaries'][summaryName][field] = "No"

                for field in provide_Empty_String_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_Empty_String_Fields:
                        globalSourceList['summaries'][summaryName][field] = ""

                for field in provide_zero_String_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == ""):
                        globalSourceList['summaries'][summaryName][field] = 0

                for field in provide_none_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_none_Fields:
                        globalSourceList['summaries'][summaryName][field] = "none"

                for field in provide_Other_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_Other_Fields:
                        globalSourceList['summaries'][summaryName][field] = "Other"

                for field in provide_Uppercasenone_Fields:
                    if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] is None or globalSourceList['summaries'][summaryName][field] == "") and field in provide_Uppercasenone_Fields:
                        globalSourceList['summaries'][summaryName][field] = "None"

                # for field in ensure_no_null_fields:
                #     if (field not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName][field] == "") and field in ensure_no_null_fields:
                #         globalSourceList['summaries'][summaryName][field] = ""


        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error while defaulting", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 21 Time Check:" + str(time.time() - start_time) )
        try:
            # Clear out excluded content
            keys = list(globalSourceList['summaries'].keys())
            for summaryName in keys:
                if "includeSSE" not in globalSourceList['summaries'][summaryName] or globalSourceList['summaries'][summaryName]["includeSSE"].lower() != "yes":
                    globalSourceList['summaries'].pop(summaryName)
                elif ignore_channel_exclusion == False and "channel" in globalSourceList['summaries'][summaryName] and globalSourceList['summaries'][summaryName]['channel'] in channel_exclusion and channel_exclusion[ globalSourceList['summaries'][summaryName]['channel'] ]:
                    globalSourceList['summaries'].pop(summaryName)
                    # if summaryName in globalSourceList['roles']['default']['summaries']:
                    #     globalSourceList['roles']['default']['summaries'].remove(summaryName)
            globalSourceList['roles']['default']['summaries'] = list(globalSourceList['summaries'].keys())
            # Now ignoring the roles default summaries in the actual json -- everything is driven by includeSSE
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error pulling excluded content", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True
        globalSourceList['debug'] = debug
        globalSourceList['throwError'] = throwErrorMessage

        debug.append("Stage 22 Time Check:" + str(time.time() - start_time) )


        try:
            fields = ["search_title", "mitre_id", "mitre_technique_combined", "mitre_sub_technique_combined", "mitre_tactic_combined", "killchain", "name", "category", "analytic_story"]
            kvstore_output = getKVStore("sse_content_exported")
            collection = service.kvstore['sse_content_exported']
            for summaryName in globalSourceList['summaries']:
                if "search_title" in globalSourceList['summaries'][summaryName] and globalSourceList['summaries'][summaryName]["search_title"] != "":
                    record = {
                        "_key": summaryName,
                        "summaryId": summaryName
                    }
                    for field in fields:
                        if field == "mitre_technique_combined":
                            mitres = globalSourceList['summaries'][summaryName]["mitre_technique"].split("|")
                            record["mitre_technique"] = []
                            record["mitre_technique_combined"] = []
                            record["mitre_technique_description"] = []
                            for mitre in mitres:
                                if mitre != "":
                                    record["mitre_technique"].append(mitre)
                                if mitre in mitre_names['attack']:
                                    record["mitre_technique_combined"].append(mitre + " - " + mitre_names['attack'][mitre])    
                                # elif mitre in mitre_names['preattack']:
                                #     record["mitre_technique_combined"].append(mitre + " - " + mitre_names['preattack'][mitre])    
                                if mitre in mitre_technique_descriptions:
                                    record["mitre_technique_description"].append( mitre_technique_descriptions[mitre] )
                        elif field == "mitre_sub_technique_combined":
                            mitres = globalSourceList['summaries'][summaryName]["mitre_sub_technique"].split("|")
                            record["mitre_sub_technique"] = []
                            record["mitre_sub_technique_combined"] = []
                            record["mitre_sub_technique_description"] = []
                            for mitre in mitres:
                                if mitre != "":
                                    record["mitre_sub_technique"].append(mitre)
                                if mitre in mitre_names['attack']:
                                    record["mitre_sub_technique_combined"].append(mitre + " - " + mitre_names['attack'][mitre])
                        elif field == "mitre_tactic_combined":
                            mitres = globalSourceList['summaries'][summaryName]["mitre_tactic"].split("|")
                            record["mitre_tactic"] = []
                            record["mitre_tactic_combined"] = []
                            record["mitre_tactic_display"] = []
                            for mitre in mitres:
                                if mitre != "":
                                    record["mitre_tactic"].append(mitre)
                                if mitre in mitre_names['attack']:
                                    record["mitre_tactic_combined"].append(mitre + " - " + mitre_names['attack'][mitre])
                                    record["mitre_tactic_display"].append(mitre_names['attack'][mitre])    
                                # elif mitre in mitre_names['preattack']:
                                #     record["mitre_tactic_combined"].append(mitre + " - " + mitre_names['preattack'][mitre])   
                        elif field == "mitre_id":
                            mitres = globalSourceList['summaries'][summaryName]["mitre_id"].split("|")
                            record["mitre_id"] = []
                            record["mitre_display"] = []
                            record["mitre_description"] = []
                            for mitre in mitres:
                                if mitre != "":
                                    record["mitre_id"].append(mitre)
                                if mitre in mitre_names['attack']:
                                    record["mitre_display"].append(mitre_names['attack'][mitre])    
                                if mitre in mitre_technique_descriptions:
                                    record["mitre_description"].append( mitre_technique_descriptions[mitre] ) 
                        elif field == "name":
                            record["summaryName"] = globalSourceList['summaries'][summaryName][field]
                        elif field == "search_title":
                            search_titles = globalSourceList['summaries'][summaryName]["search_title"].split("|")
                            record["search_title"] = []
                            for search_title in search_titles:
                                if search_title != "":
                                    record["search_title"].append(search_title)
                        elif field == "category":
                            categories = globalSourceList['summaries'][summaryName]["category"].split("|")
                            record["category"] = []
                            for category in categories:
                                if category != "":
                                    record["category"].append(category)
                        elif field == "killchain":
                            killchains = globalSourceList['summaries'][summaryName]["killchain"].split("|")
                            record["killchain"] = []
                            for killchain in killchains:
                                if killchain != "":
                                    record["killchain"].append(killchain)
                        elif field == "analytic_story":
                            analytic_stories = globalSourceList['summaries'][summaryName]["analytic_story"].split("|")
                            record["analytic_story"] = []
                            for analytic_story in analytic_stories:
                                if (analytic_story != "" and analytic_story != "None"):
                                    record["analytic_story"].append(analytic_story)
                        elif field in globalSourceList['summaries'][summaryName]:
                            record[field] = globalSourceList['summaries'][summaryName][field]
                    should = "insert"
                    for row in kvstore_output:
                        if row['_key'] == record['_key']:
                            should = "update"
                            if '_user' in row:
                                del row['_user']
                            if json.dumps(row, sort_keys=True) == json.dumps(record, sort_keys=True):
                                should = "pass"
                            # debug.append({"msg": "Checking exported", "showcase": summaryName, "timecheck": str(time.time() - start_time), "should": should, "row": json.dumps(row, sort_keys=True), "record": json.dumps(record, sort_keys=True)})
                    
                    try:
                        if should == "update":
                            collection.data.update(summaryName, json.dumps(record))
                        elif should == "insert":
                            collection.data.insert(json.dumps(record))
                    except Exception as e:
                        debug.append(json.dumps({"status": "ERROR", "description": "Couldn't add content into the kvstore built for ES Integration.", "insert_message": str(e), "update_message": str(update_e)}))
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Couldn't handle the kvstore built for ES Integration.", "message": str(e), "traceback": traceback.format_exc()}))
            throwErrorMessage = True

        debug.append("Stage 23 Time Check:" + str(time.time() - start_time) )

        # debug.append({"msg": "Here's the dsc_to_scores", "values": dsc_to_da_scores})


        # try:
        #     cacheShowcase = {}
        #    summaryName][field] = globalSourceList['summaries'][summaryName][field]
        #     collection = service.kvstore['sse_showcaseinfo_cache']
        #     kvstore_output = service.kvstore['sse_showcaseinfo_cache'].data.query()
        #     updateObjects = []
        #     for row in kvstore_output:
        #         if row['id'] not in cacheShowcase:
        #             collection.data.delete(json.dumps({"_key":row['id']}))
        #             updateObjects.append(row['id'])
        #         else:
        #             collection.data.update(row['id'], cacheShowcase[row['id']])
        #             updateObjects.append(row['id'])
        #     for summaryName in cacheShowcase:
        #         if summaryName not in updateObjects:
        #             collection.data.insert(cacheShowcase[summaryName])
        # except Exception as e:
        #     debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while updating sse_showcaseinfo_cache", "message": str(e), "traceback": traceback.format_exc()}))
        #     throwErrorMessage = True





        # ## Disabling Caching because it's not enough of a performance benefit
        # ## (Discovered that time to download was the real problem, not time to gen the showcase)
        # try: 
        #     collection = service.kvstore['sse_json_doc_storage']
        # except Exception as e: 
        #     debug.append(json.dumps({"status": "ERROR", "description": "Couldn't establish the kvstore collection... expect more errors.", "message": str(e), "traceback": traceback.format_exc()}))

        # try:
        #     record = {
        #         "_key": "sseshowcase" + desired_locale,
        #         "description": "Cached version of SSE Showcase",
        #         "version": "Not Applicable",
        #         "json": json.dumps(globalSourceList)
        #     }
            
        #     collection.data.update("sseshowcase" + desired_locale, json.dumps(record))
        #     if caching == "updateonly":
        #         return {'payload': {"update": "successful"},  
        #                 'status': 200          # HTTP status code
        #         }
        # except Exception as initial:
        #     try:
        #         collection.data.insert(json.dumps(record))
        #         if caching == "updateonly":
        #             return {'payload': {"update": "successful"},  
        #                     'status': 200          # HTTP status code
        #             }
        #     except Exception as e:
        #         debug.append(json.dumps({"status": "ERROR", "description": "Error occurred while updating sseshowcase", "message": str(e), "traceback": traceback.format_exc()}))
        #         throwErrorMessage = True
        #         try:
        #             total_url = base_url + '/servicesNS/nobody/' + app + "/storage/collections/data/sse_json_doc_storage/" + "sseshowcase" + desired_locale
        #             debug.append({"status": "Failed to update the kvstore via the python sdk, deleting the cache because we can't be trusted.", "url": total_url})
        #             headers = {
        #             'Authorization': ('Splunk %s' % sessionKey)
        #             }
        #             opener = urllib2.build_opener(urllib2.HTTPHandler)
        #             req = urllib2.Request(total_url, None, headers)
        #             req.get_method = lambda: 'DELETE'  # creates the delete method
        #             url = urllib2.urlopen(req)  # deletes database item
        #         except Exception as e: 
        #             if str(e) != "HTTP Error 404: Not Found":
        #                 debug.append(json.dumps({"status": "ERROR", "description": "Error, we couldn't even delete the kvstore entry! What a sad day.", "message": str(e), "traceback": traceback.format_exc()}))
        #                 throwErrorMessage = True
        #             else:
        #                 debug.append(json.dumps({"status": "WARN", "description": "We weren't the first ones here. No cache existed.", "message": ""}))
        
        debug.append("Stage 24 Time Check:" + str(time.time() - start_time) )
        try:
            if field_list_version == "mini":
                del globalSourceList['escu_stories']
                for summaryName in globalSourceList['summaries']:
                    for key in list(globalSourceList['summaries'][summaryName].keys()):
                        if key not in mini_fields:
                            del globalSourceList['summaries'][summaryName][key]
                try:
                    showcase_info_file = open(pathToShowcaseInfoMini+"ShowcaseInfoMini.json", "w")
                    if showcase_info_file.writable():
                        showcase_info_file.write(json.dumps(globalSourceList))
                        showcase_info_file.close()
                except Exception as e:
                        logger.error("Error: ", str(e))  
        except Exception as e:
            debug.append(json.dumps({"status": "ERROR", "description": "Error while minifying", "message": str(e), "traceback": traceback.format_exc()}))

        
        debug.append("Stage 25 Time Check:" + str(time.time() - start_time) )
        
        return {'payload': globalSourceList,  
                'status': 200          # HTTP status code
        }