Untitled

 avatar
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