Ejemplo n.º 1
0
def node_list(args):

    element_position = 1
    argument_node = args.hostname
    template_list = []
    template_list_copy = template_list
    auditcreeper_flag = True

    ### NODE_OBJECT IS A LIST OF ALL THE NODES IN THE DATABASE WITH ALL ATTRIBUTES
    node_object = process_nodes()

    ### MATCH_NODE IS A LIST OF NODES THAT MATCHES THE ARGUEMENTS PASSED IN BY USER
    match_node = search_node(argument_node, node_object)

    ### NODE_TEMPLATE IS A LIST OF ALL THE TEMPLATES BASED ON PLATFORMS AND DEVICE TYPE
    node_template = process_templates()

    ### MATCH_TEMPLATE IS A LIST OF 'MATCH' AND/OR 'NO MATCH' IT WILL USE THE MATCH_NODE
    ### RESULT, RUN IT AGAINST THE NODE_OBJECT AND COMPARES IT WITH NODE_TEMPLATE DATABASE
    ### TO SEE IF THERE IS A TEMPLATE FOR THE SPECIFIC PLATFORM AND TYPE.
    match_template = search_template(template_list, match_node, node_template,
                                     node_object, auditcreeper_flag)
    ### THIS WILL PARSE OUT THE GENERATED CONFIGS FROM THE *.JINJA2 FILE TO A LIST

    if (len(match_node) == 0):
        print("[+] [NO MATCHING NODES AGAINST DATABASE]")
        print("")

    else:
        print("[")
        template_list = template_list_copy[0]

        for index in initialize.element:

            print("    {")
            print("\t\"hostname\": \"{}\"\n" \
               "\t\"os\": \"{}\"\n" \
               "\t\"platform\": \"{}\"\n" \
               "\t\"type\": \"{}\"".format(node_object[index]['hostname'],node_object[index]['os'],node_object[index]['platform'],node_object[index]['type'])) + "\n" \
               "\t\"data\": {\n" \
               "\t    \"managed_configs\": {" \

            for template in template_list:
                print("\t\t   \"{}\"".format(template))
            print("\t     }")
            print("\t }")

            template_list = get_template(template_list_copy)

            #			if(len(template_list_copy) != 1):
            #				template_list_copy.pop(0)
            #				template_list = template_list_copy[0]

            if (element_position == len(initialize.element)):
                print("    }")
            else:
                print("    },")

            element_position = element_position + 1
        print("]")
Ejemplo n.º 2
0
def render(template_list, node_object, auditcreeper):

    ### TEMPLATE_LIST_COPY TAKE A COPY OF THE CURRENT TEMPLATE_LIST
    template_list_copy = template_list

    if (auditcreeper):
        template_list = template_list_copy[0]

    print("[!] [THE FOLLOWING TEMPLATE(S) IS/ARE RENDERED:]")
    print("")
    for index in initialize.element:

        print("{}".format(node_object[index]['hostname']))
        for template in template_list:
            ### THIS CALLS THE DIRECTORY MODULE WHICH WILL RETURN THE CORRECT DIRECTORY PATH BASED ON DEVICE PLATFORM, OS AND TYPE
            directory = get_directory(node_object[index]['platform'],
                                      node_object[index]['os'],
                                      node_object[index]['type'])
            env = Environment(loader=FileSystemLoader("{}".format(directory)))
            baseline = env.get_template(template)
            f = open(
                "/rendered-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "w")
            config_list = []
            config = baseline.render(nodes=node_object[index])
            f.write(config)
            f.close
            print("{}{}".format(directory, template))
            print("{}".format(config))
        if (auditcreeper):
            template_list = get_template(template_list_copy)

    return None
Ejemplo n.º 3
0
def render(template_list,node_object,auditcreeper,output,with_remediations):

### TEMPLATE_LIST_COPY TAKE A COPY OF THE CURRENT TEMPLATE_LIST
	template_list_copy = template_list

	if(auditcreeper):
	    template_list = template_list_copy[0]

#	print("[!] [THE FOLLOWING TEMPLATE(S) IS/ARE RENDERED:]")
	for index in initialize.element:

		print ("{}".format(node_object[index]['hostname']))
		for template in template_list:
		### THIS CALLS THE DIRECTORY MODULE WHICH WILL RETURN THE CORRECT DIRECTORY PATH BASED ON DEVICE PLATFORM, OS AND TYPE
			directory = get_directory(node_object[index]['platform'],node_object[index]['os'],node_object[index]['type'])
			env = Environment(loader=FileSystemLoader("{}".format(directory)))
			baseline = env.get_template(template)
			f = open("/rendered-configs/{}".format(node_object[index]['hostname']) + ".conf", "w") 
			config_list = []
			config = baseline.render(nodes = node_object[index],with_remediations=with_remediations)
			f.write(config) 
			f.close 
			print("{}{}".format(directory,template))
			if(output):
				print("{}".format(config))

			f = open("/rendered-configs/{}".format(node_object[index]['hostname']) + ".conf", "r")
			init_config = f.readlines()
			### THE BELOW PARSE_COMMANDS FUNCTION WILL ONLY GET EXECUTED IF NEEDS TO STORE COMMANDS IN THE GLOBAL VARILABLE INITIALIZE.CONFIGURATION FOR PUSH
			### PUSH_CFGS(OUTPUT = TRUE) VS RENDER_CONFIG(OUTPUT = FALSE) FUNCTIONS.
			if(output!=True):
				parse_commands(init_config)

		if(auditcreeper):
			template_list = get_template(template_list_copy)
		print

	return None
Ejemplo n.º 4
0
def auditdiff_engine(template_list, node_object, auditcreeper, output,
                     remediation):

    controller = 'get_config'
    command = ''

    ### PUSH_CONFIGS IS A LIST OF THE FINAL CONFIGS TO BE PUSHED
    #	push_configs = []

    ### INDEX_POSITION IS THE INDEX OF ALL THE MATCHED FILTER_CONFIG AGAINST THE BACKUP_CONFIGS. THE INDEX IS COMING FROM THE BACKUP_CONFIG
    index_position = 0

    ### NODE_INDEX KEEPS TRACK OF THE INDEX IN INITIALIZE.NTW_DEVICE. IF REMEDIATION IS NOT REQUIRED (CONFIGS MATCHES TEMPLATE), THEN THE NODE IS POPPED OFF
    ### INITIALIZE.NTW_DEVICE AND NOTHING IS CHANGED ON THAT DEVICE
    node_index = 0

    ### AUDIT_FILTER_RE IS THE REGULAR EXPRESSION TO FILTER OUT THE AUDIT FILTER IN EVERY TEMPLATE
    AUDIT_FILTER_RE = r"\[.*\]"

    ### TEMPLATE_LIST_COPY TAKE A COPY OF THE CURRENT TEMPLATE_LIST
    template_list_copy = template_list

    if (auditcreeper):
        template_list = template_list_copy[0]

    print("[+] [COMPUTING DIFF. STANDBY...]")
    multithread_engine(initialize.ntw_device, controller, command)

    ### THIS FOR LOOP WILL LOOP THROUGH ALL THE MATCHED ELEMENTS FROM THE USER SEARCH AND AUDIT ON SPECIFIC TEMPLATE OR IF NO ARGUMENT IS GIVEN, ALL TEMPLATES

    for index in initialize.element:

        ### NODE_CONFIG IS THE FINALIZED CONFIG TO PUSH TO THE NODE FOR REMEDIATION
        node_configs = []
        ntw_device_pop = True
        ### TEMPLATE_NAME IS SET TO TRUE IN ORDER TO PRINT OUT THE TEMPLATE HEADING WHEN RECURSING
        template_name = True

        if (not remediation):
            print("Only in the device: -")
            print("Only in the generated config: +")

            print("{}".format(node_object[index]['hostname']))

        ### THIS WILL LOOP THROUGH ALL THE TEMPLATES SPECIFIED FOR THE PARTICULAR HOST IN NODES.YAML
        for template in template_list:

            ### INDEX_LIST IS A LIST OF ALL THE POSITIONS COLLECTED FROM INDEX_POSITION VARIABLE
            index_list = []

            ### FILTER_CONFIG IS A LIST OF COLLECTION OF ALL THE AUDIT FILTERS THAT MATCHED THE LINES IN BACKUP_CONFIG. THESE ENTRIES DO NOT CONTAIN DEPTHS/DEEP CONFIGS
            filtered_config = []

            ### FILTERED_BACKUP_CONFIG IS THE FINAL LIST OF ALL THE AUDIT FILTERS THAT MATCHES THE LINES IN BACKUP_CONFIG. THESE ENTRIES INCLUDE DEPTHS/DEEP CONFIGS
            filtered_backup_config = []

            ### THIS SECTION OF CODE WILL PROCESS THE TEMPLATE AND OUTPUT TO A *.CONF FILE
            directory = get_directory(node_object[index]['platform'],
                                      node_object[index]['os'],
                                      node_object[index]['type'])
            env = Environment(loader=FileSystemLoader("{}".format(directory)))
            baseline = env.get_template(template)
            f = open(
                "/rendered-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "w")

            ### GENERATING TEMPLATE BASED ON NODE OBJECT
            config = baseline.render(nodes=node_object[index])

            f.write(config)
            f.close

            ### THIS SECTION OF CODE WILL OPEN THE RENDERED-CONFIG *.CONF FILE AND STORE IN RENDERED_CONFIG AS A LIST
            f = open(
                "/rendered-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "r")
            init_config = f.readlines()
            ### RENDERED_CONFIG IS A LIST OF ALL THE CONFIGS THAT WAS RENDERED FROM THE TEMPLATES (SOURCE OF TRUTH)
            rendered_config = []

            for config_line in init_config:
                strip_config = config_line.strip('\n')
                ### THIS WILL REMOVE ANY LINES THAT ARE EMPTY OR HAS A '!' MARK
                if (strip_config == '' or strip_config == "!"):
                    continue
                else:
                    rendered_config.append(strip_config)

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print ("RENDERED CONFIG: {}".format(rendered_config))

### THIS SECTION OF CODE WILL OPEN BACKUP-CONFIG *.CONF FILE AND STORE IN BACKUP_CONFIG AS A LIST
            f = open(
                "/backup-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "r")
            init_config = f.readlines()
            backup_config = []

            for config_line in init_config:
                strip_config = config_line.strip('\n')
                backup_config.append(strip_config)

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print ("BACKUP CONFIG: {}".format(backup_config))

### THIS WILL OPEN THE JINJA2 TEMPLATE AND PARSE OUT THE AUDIT_FILTER SECTION VIA REGULAR EXPRESSION
            directory = get_directory(node_object[index]['platform'],
                                      node_object[index]['os'],
                                      node_object[index]['type'])
            f = open("{}".format(directory) + template, "r")
            parse_audit = f.readline()
            audit_filter = eval(re.findall(AUDIT_FILTER_RE, parse_audit)[0])

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
            #			print ("AUDIT_FILTER: {}".format(audit_filter))

            ### FILTER OUT THE BACKUP_CONFIGS WITH THE AUDIT_FILTER
            ### THIS WILL TAKE EACH ELEMENT FROM THE AUDIT_FILTER LIST AND SEARCH FOR THE MATCHED LINES IN BACKUP_CONFIG
            ### MATCHED ENTRIES ARE THEN APPENDED TO FILTER_CONFIG VARIABLE AS A LIST
            parse_backup_configs = CiscoConfParse(
                "/backup-configs/{}".format(node_object[index]['hostname']) +
                ".conf")
            for audit in audit_filter:

                current_template = parse_backup_configs.find_objects(
                    r"^{}".format(audit))
                for audit_string in current_template:
                    filtered_backup_config.append(audit_string.text)
                    if (audit_string.is_parent):
                        for child in audit_string.all_children:
                            filtered_backup_config.append(child.text)

            ### UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print("FILTERED BACKUP CONFIG: {}".format(filtered_backup_config))

### SYNC_DIFF WILL DIFF OUT THE FILTERED_BACKUP_COFNIG FROM THE RENDERED CONFIG AND STORE WHATEVER COMMANDS THAT
### NEEDS TO BE ADDED/REMOVE IN PUSH_CONFIGS VARIABLE
            parse = CiscoConfParse(filtered_backup_config)
            push_configs = parse.sync_diff(rendered_config,
                                           "",
                                           ignore_order=True,
                                           remove_lines=True,
                                           debug=False)
            if (len(push_configs) == 0):
                if (output):
                    print("{}{} (none)".format(directory, template))
                    print
            else:

                ### THIS WILL JUST PRINT THE HEADING OF THE TEMPLATE NAME SO YOU KNOW WHAT IS BEING CHANGED UNDER WHICH TEMPLATE
                if (output):
                    print("{}{}".format(directory, template))

                for line in push_configs:
                    search = parse_backup_configs.find_objects(
                        r"^{}".format(line))
                    if ('no' in line):
                        line = re.sub("no", "", line)
                        if (not remediation):
                            print("-{}".format(line))
                    elif (len(search) == 0):
                        if (not remediation):
                            print("+ {}".format(line))
                    elif (len(search) > 1):
                        if (not remediation):
                            print("+ {}".format(line))
                    else:
                        if (not remediation):
                            print("  {}".format(line))

                ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#				print("PUSH_CONFIGS: {}".format(push_configs))
                if (remediation):

                    ### THIS STEP WILL APPEND REMEDIATION CONFIGS FROM TEMPLATE (EXPECTED RESULTS)
                    for config in push_configs:
                        node_configs.append(config)
                        ntw_device_pop = False

                    ### INITIALIZE.COFIGURATION APPENDS ALL THE REMEDIATED CONFIGS AND PREPARES IT FOR PUSH
                    if (auditcreeper == False):
                        initialize.configuration.append(node_configs)
                    node_index = node_index + 1

        if (auditcreeper):
            initialize.configuration.append(node_configs)
            if (ntw_device_pop == True):
                initialize.ntw_device.pop(node_index)
                initialize.configuration.pop(node_index)
            template_list = get_template(template_list_copy)

#	if(remediation):
#		print("[+]: PUSH ENABLED")
#		print("[!]: PUSH DISABLED")

    return None
Ejemplo n.º 5
0
def auditdiff_engine(template_list, node_object, auditcreeper):

    controller = 'get_config'

    command = ''

    ### PUSH_CONFIGS IS A LIST OF THE FINAL CONFIGS TO BE PUSHED
    push_configs = []

    ### INDEX_POSITION IS THE INDEX OF ALL THE MATCHED FILTER_CONFIG AGAINST THE BACKUP_CONFIGS. THE INDEX IS COMING FROM THE BACKUP_CONFIG
    index_position = 0

    ### NODE_INDEX KEEPS TRACK OF THE INDEX IN INITIALIZE.NTW_DEVICE. IF REMEDIATION IS NOT REQUIRED (CONFIGS MATCHES TEMPLATE), THEN THE NODE IS POPPED OFF
    ### INITIALIZE.NTW_DEVICE AND NOTHING IS CHANGED ON THAT DEVICE
    node_index = 0

    ### AUDIT_FILTER_RE IS THE REGULAR EXPRESSION TO FILTER OUT THE AUDIT FILTER IN EVERY TEMPLATE
    AUDIT_FILTER_RE = r"\[.*\]"

    ### TEMPLATE_LIST_COPY TAKE A COPY OF THE CURRENT TEMPLATE_LIST
    template_list_copy = template_list

    if (auditcreeper):
        template_list = template_list_copy[0]

    print("[+] [GATHERING RUNNING-CONFIG. STANDBY...]")
    multithread_engine(initialize.ntw_device, controller, command)

    ### THIS FOR LOOP WILL LOOP THROUGH ALL THE MATCHED ELEMENTS FROM THE USER SEARCH AND AUDIT ON SPECIFIC TEMPLATE OR IF NO ARGUMENT IS GIVEN, ALL TEMPLATES
    for index in initialize.element:

        ### NODE_CONFIG IS THE FINALIZED CONFIG TO PUSH TO THE NODE FOR REMEDIATION
        node_configs = []
        ntw_device_pop = True
        ### TEMPLATE_NAME IS SET TO TRUE IN ORDER TO PRINT OUT THE TEMPLATE HEADING WHEN RECURSING
        template_name = True
        first_parent = True
        previous_parent = ''

        print("Only in the device: -")
        print("Only in the generated config: +")
        print("{}".format(node_object[index]['hostname']))

        for template in template_list:

            ### INDEX_LIST IS A LIST OF ALL THE POSITIONS COLLECTED FROM INDEX_POSITION VARIABLE
            index_list = []

            ### FILTER_CONFIG IS A LIST OF COLLECTION OF ALL THE AUDIT FILTERS THAT MATCHED THE LINES IN BACKUP_CONFIG. THESE ENTRIES DO NOT CONTAIN DEPTHS/DEEP CONFIGS
            filtered_config = []

            ### FILTERED_BACKUP_CONFIG IS THE FINAL LIST OF ALL THE AUDIT FILTERS THAT MATCHES THE LINES IN BACKUP_CONFIG. THESE ENTRIES INCLUDE DEPTHS/DEEP CONFIGS
            filtered_backup_config = []

            ### THIS SECTION OF CODE WILL PROCESS THE TEMPLATE AND OUTPUT TO A *.CONF FILE
            directory = get_directory(node_object[index]['platform'],
                                      node_object[index]['os'],
                                      node_object[index]['type'])
            env = Environment(loader=FileSystemLoader("{}".format(directory)))
            baseline = env.get_template(template)
            f = open(
                "/rendered-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "w")

            ### GENERATING TEMPLATE BASED ON NODE OBJECT
            config = baseline.render(nodes=node_object[index])

            f.write(config)
            f.close

            ### THIS SECTION OF CODE WILL OPEN THE RENDERED-CONFIG *.CONF FILE AND STORE IN RENDERED_CONFIG AS A LIST
            f = open(
                "/rendered-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "r")
            init_config = f.readlines()
            ### RENDERED_CONFIG IS A LIST OF ALL THE CONFIGS THAT WAS RENDERED FROM THE TEMPLATES (SOURCE OF TRUTH)
            rendered_config = []

            for config_line in init_config:
                strip_config = config_line.strip('\n')
                ### THIS WILL REMOVE ANY LINES THAT ARE EMPTY OR HAS A '!' MARK
                if (strip_config == '' or strip_config == "!"):
                    continue
                else:
                    rendered_config.append(strip_config)

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print ("RENDERED CONFIG: {}".format(rendered_config))

### THIS SECTION OF CODE WILL OPEN BACKUP-CONFIG *.CONF FILE AND STORE IN BACKUP_CONFIG AS A LIST
            f = open(
                "/backup-configs/{}".format(node_object[index]['hostname']) +
                ".conf", "r")
            init_config = f.readlines()
            backup_config = []

            for config_line in init_config:
                strip_config = config_line.strip('\n')
                backup_config.append(strip_config)

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print ("BACKUP CONFIG: {}".format(backup_config))

### THIS WILL OPEN THE JINJA2 TEMPLATE AND PARSE OUT THE AUDIT_FILTER SECTION VIA REGULAR EXPRESSION
            directory = get_directory(node_object[index]['platform'],
                                      node_object[index]['os'],
                                      node_object[index]['type'])
            f = open("{}".format(directory) + template, "r")
            parse_audit = f.readline()
            audit_filter = eval(re.findall(AUDIT_FILTER_RE, parse_audit)[0])

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
            #			print ("{}".format(audit_filter))

            ### FILTER OUT THE BACKUP_CONFIGS WITH THE AUDIT_FILTER
            ### THIS WILL TAKE EACH ELEMENT FROM THE AUDIT_FILTER LIST AND SEARCH FOR THE MATCHED LINES IN BACKUP_CONFIG
            ### MATCHED ENTRIES ARE THEN APPENDED TO FILTER_CONFIG VARIABLE AS A LIST
            for audit in audit_filter:

                parse_backup_configs = CiscoConfParse(
                    "/backup-configs/{}".format(node_object[index]
                                                ['hostname']) + ".conf")
                current_template = parse_backup_configs.find_objects(
                    r"^{}".format(audit))
                for audit_string in current_template:
                    filtered_backup_config.append(audit_string.text)
                    if (audit_string.is_parent):
                        for child in audit_string.all_children:
                            filtered_backup_config.append(child.text)

            ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#			print("FILTERED BACKUP CONFIG: {}".format(filtered_backup_config))

### FILTERED_SET/RENDERED_SET RETURNS A DICTIONARY OF THE NUMBER OF TIMES A CONFIG IS REPEATED IN THE LIST
            filtered_backup_set = Counter(filtered_backup_config)
            rendered_set = Counter(rendered_config)
            minus_commands_counter = filtered_backup_set - rendered_set
            plus_commands_counter = rendered_set - filtered_backup_set

            ### MINUS_COMMANDS IS A LIST OF COMMANDS THAT EXIST ON THE NODE THAT SHOULDN'T BE WHEN COMPARED AGAINST THE TEMPLATE
            ### PLUS_COMMAND IS A LIST OF COMMAND THAT DOESN'T EXIST ON THE NODE THAT SHOULD BE WHEN COMPARED AGAINST THE TEMPLATE
            minus_commands = list(minus_commands_counter.elements())
            plus_commands = list(plus_commands_counter.elements())

            #			print("MINUS_COMMANDS: {}".format(minus_commands))
            #			print("PLUS_COMMANDS:: {}".format(plus_commands))
            ### THIS SECTION OF CODE CHECKS TO SEE IF THE LENGTH OF THE TWO LIST IS EQUAL TO ZERO, THEN NOTHING HAS TO BE REMEDIATED
            if (len(minus_commands) == 0 and len(plus_commands) == 0
                    and auditcreeper == False):
                print("{}{} (none)".format(directory, template))
                print
                initialize.ntw_device.pop(node_index)

            if (len(minus_commands) == 0 and len(plus_commands) == 0
                    and auditcreeper == True):
                print("{}{} (none)".format(directory, template))
                print

            elif (len(minus_commands) >= 1 or len(plus_commands) >= 1):

                ### THIS WILL JUST PRINT THE HEADING OF THE TEMPLATE NAME SO YOU KNOW WHAT IS BEING CHANGED UNDER WHICH TEMPLATE
                print("{}{}".format(directory, template))

                ### THIS SECTION OF CODE WILL PRINT THE DIFF OF WHAT CONFIG(S) WILL BE CHANGING
                for line in difflib.unified_diff(filtered_backup_config,
                                                 rendered_config,
                                                 n=5):
                    if (line.startswith("---") or line.startswith("+++")
                            or line.startswith("@")):
                        continue
                    else:
                        print line
                        if (line.startswith("-")):
                            config_line = line.strip()
                            ### THIS IF CONDITION IS TO SATISFY SOME CASES WHERE IT HAS A HYPEN IN BETWEEN A CONFIG. EX SNMP-SERVER
                            if (re.match("-\w.+\-", config_line)):
                                config_line = re.sub("^\-", "no ", config_line)
                                push_configs.append(config_line)
                            elif (re.match("-", config_line)):
                                config_line = re.sub("-", "no ", config_line)
                                push_configs.append(config_line)
                            elif (re.match("-\s\w", line)):
                                config_line = re.sub("-", "no", config_line)
                                push_configs.append(config_line)
                        elif (line.startswith("+")):
                            config_line = line.strip()
                            config_line = line.strip("+")
                            push_configs.append(config_line)
                        else:
                            config_line = line.strip("\n")
                            push_configs.append(config_line)
                print("")
                ### THIS SECTION OF CODE WILL CHECK FOR THE WHITE SPACES FROM THE BEGINNING OF THE LIST
                ### IF THE ELEMENT HAS 1 WHITE SPACE, IT THEN KNOWS IT'S A PARENT CONFIG
                ### ANYTHING GREATER THAN 1 WHITE SPACE IS A PARENT/CHILD
                config_index = 0
                whitespace = len(push_configs[config_index]) - len(
                    push_configs[config_index].lstrip())
                while (whitespace != 1):
                    push_configs.pop(config_index)
                    whitespace = len(push_configs[config_index]) - len(
                        push_configs[config_index].lstrip())

                ###UN-COMMENT THE BELOW PRINT STATEMENT FOR DEBUGING PURPOSES
#				print("PUSH_CONFIGS: {}".format(push_configs))

### THIS STEP WILL APPEND REMEDIATION CONFIGS FROM TEMPLATE
                for config in push_configs:
                    node_configs.append(config)
                    ntw_device_pop = False

                ### INITIALIZE.COFIGURATION APPENDS ALL THE REMEDIATED CONFIGS AND PREPARES IT FOR PUSH
                if (auditcreeper == False):
                    initialize.configuration.append(node_configs)
                node_index = node_index + 1

        if (auditcreeper):
            initialize.configuration.append(node_configs)
            if (ntw_device_pop == True):
                initialize.ntw_device.pop(node_index)
                initialize.configuration.pop(node_index)
            template_list = get_template(template_list_copy)

    return None