Untitled
unknown
plain_text
a month ago
4.8 kB
2
Indexable
import streamlit as st import pandas as pd import re st.title("🔧 Network Config Compliance Checker") # --- Upload Config Files --- uploaded_files = st.file_uploader("📂 Upload Config Files", type=["txt"], accept_multiple_files=True) # --- Policy Management (unchanged UI) --- # [Keep the exact same UI code for policy creation as before...] # --- Core Fix: Block-Based Evaluation Logic --- def parse_blocks(config_text): """Parse config into templates and interfaces with their content.""" templates = {match[0].strip(): match[1] for match in re.findall(r"(template \S+)(.*?)(?=template \S+|$)", config_text, re.DOTALL)} interfaces = {match[0].strip(): match[1] for match in re.findall(r"(interface \S+)(.*?)(?=interface \S+|$)", config_text, re.DOTALL)} return templates, interfaces def evaluate_policy(policy, templates, interfaces, general_config): """Evaluate a policy with strict dependency scoping.""" results = [] conditions = policy["conditions"] dependency_chain = {} # Track {keyword: (exists, block_content)} # Resolve dependencies in order for cond in conditions: keyword = cond["keyword"] dependent_on = cond["dependent_on"] condition_type = cond["condition"] # Determine search scope search_text = general_config # Default to full config if dependent_on: # Check if dependency is a resolved template/interface if dependent_on in dependency_chain: parent_exists, parent_block = dependency_chain[dependent_on] if not parent_exists: # Parent failed - mark condition as failed dependency_chain[keyword] = (False, None) continue search_text = parent_block # Restrict to parent's block else: # Check if dependency is a template/interface if dependent_on.startswith("template "): search_text = templates.get(dependent_on, "") elif dependent_on.startswith("interface "): search_text = interfaces.get(dependent_on, "") # Evaluate current condition exists = bool(re.search(keyword, search_text, re.DOTALL)) meets_condition = ( (condition_type == "Exists" and exists) or (condition_type == "Does Not Exist" and not exists) ) # Store results for dependencies dependency_chain[keyword] = (meets_condition, search_text if exists else None) if not meets_condition: return False # Entire policy fails if any condition fails return True # All conditions met # --- Compliance Check Logic (Revised) --- if st.button("🚀 Run Compliance Check"): if not uploaded_files: st.warning("⚠️ Please upload config files first.") else: results = [] for uploaded_file in uploaded_files: config_text = uploaded_file.read().decode("utf-8") switch_name = uploaded_file.name.split(".")[0] # Parse blocks once per file templates, interfaces = parse_blocks(config_text) # Evaluate all policies for policy in st.session_state.advanced_policies: policy_name = policy["name"] scope = policy["scope"] # General config check if scope in ["General Configuration", "Both"]: is_compliant = evaluate_policy(policy, templates, interfaces, config_text) results.append({ "Switch": switch_name, "Interface": "N/A (General)", "Policy": policy_name, "Status": policy["action"] if is_compliant else "Non-Compliant" }) # Interface config check if scope in ["Interface Configuration", "Both"]: for int_name, int_config in interfaces.items(): is_compliant = evaluate_policy(policy, templates, interfaces, int_config) results.append({ "Switch": switch_name, "Interface": int_name.split()[1], # Extract interface name "Policy": policy_name, "Status": policy["action"] if is_compliant else "Non-Compliant" }) # Display results df = pd.DataFrame(results) st.write(df) st.download_button("📥 Download Report", df.to_csv(index=False), "compliance_report.csv", "text/csv")
Editor is loading...
Leave a Comment