Untitled
unknown
plain_text
8 months ago
8.3 kB
4
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)
# --- Advanced Policy Section ---
st.subheader("🛠️ Define Compliance Policies")
if "advanced_policies" not in st.session_state:
st.session_state.advanced_policies = []
with st.expander("➕ Create New Policy"):
policy_name = st.text_input("Policy Name (e.g., Template Check)")
policy_scope = st.selectbox("🔍 Policy Scope", ["Interface Configuration", "General Configuration", "Both"])
if "advanced_conditions" not in st.session_state:
st.session_state.advanced_conditions = []
if st.button("➕ Add Condition"):
st.session_state.advanced_conditions.append({"condition": "Exists", "keyword": "", "dependent_on": None})
for idx, condition in enumerate(st.session_state.advanced_conditions):
cols = st.columns([0.3, 0.3, 0.2, 0.2])
condition["condition"] = cols[0].selectbox(f"Condition {idx+1}", ["Exists", "Does Not Exist"], key=f"cond_{idx}")
condition["keyword"] = cols[1].text_input("Keyword / Command", key=f"kw_{idx}")
# Dependency selection
condition["dependent_on"] = cols[2].selectbox(
"Depends On",
["None"] + [c["keyword"] for c in st.session_state.advanced_conditions if c["keyword"]],
key=f"dep_{idx}",
)
if cols[3].button("❌ Remove", key=f"del_{idx}"):
st.session_state.advanced_conditions.pop(idx)
compliance_action_adv = st.selectbox("🔍 Compliance Action", ["Compliant", "Non-Compliant", "Warning"])
if st.button("✅ Add Policy"):
if policy_name and st.session_state.advanced_conditions:
conditions = [{"condition": cond["condition"], "keyword": cond["keyword"], "dependent_on": cond["dependent_on"]}
for cond in st.session_state.advanced_conditions]
st.session_state.advanced_policies.append({
"name": policy_name,
"scope": policy_scope,
"conditions": conditions,
"action": compliance_action_adv
})
st.session_state.advanced_conditions = []
st.success("Policy Added!")
# --- Display & Delete Policies ---
st.subheader("📋 Active Policies")
if st.session_state.advanced_policies:
for idx, policy in enumerate(st.session_state.advanced_policies):
with st.container():
st.write(f"**🔹 {policy['name']} → {policy['action']} ({policy['scope']})**")
for cond in policy["conditions"]:
dep_info = f" (Depends on: {cond['dependent_on']})" if cond["dependent_on"] else ""
st.write(f" - {cond['condition']} '{cond['keyword']}'{dep_info}")
if st.button(f"🗑️ Delete '{policy['name']}'", key=f"del_policy_{idx}"):
st.session_state.advanced_policies.pop(idx)
st.rerun()
else:
st.info("No policies defined yet. Add a new one above.")
# --- Helper Function to Evaluate Conditions ---
def evaluate_conditions(config_text, conditions, template_blocks=None):
conditions_met = True
missing_conditions = []
dependency_status = {}
current_scope = config_text # Default to full config if no template
for cond in conditions:
# Check if dependency is a template
if cond["dependent_on"] and template_blocks:
for template_name, template_config in template_blocks:
if template_name.strip() == f"template {cond['dependent_on']}":
current_scope = template_config # Search within the dependent template block
break
else:
current_scope = config_text # Reset to full config if dependency not found
exists = bool(re.search(cond["keyword"], current_scope, re.DOTALL))
# Check dependencies
if cond["dependent_on"] and cond["dependent_on"] in dependency_status:
if not dependency_status[cond["dependent_on"]]:
conditions_met = False
missing_conditions.append(f"Dependency failed: {cond['dependent_on']}")
continue # Skip actual checking
if cond["condition"] == "Exists" and not exists:
conditions_met = False
missing_conditions.append(cond["keyword"])
elif cond["condition"] == "Does Not Exist" and exists:
conditions_met = False
missing_conditions.append(f"NOT {cond['keyword']}")
dependency_status[cond["keyword"]] = exists # Store result for dependencies
return conditions_met, missing_conditions
# --- Compliance Check ---
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 template blocks
template_blocks = re.findall(r"(template \S+)(.*?)(?=template \S+|$)", config_text, re.DOTALL)
# --- General Config Compliance Check ---
for policy in st.session_state.advanced_policies:
if policy["scope"] in ["General Configuration", "Both"]:
conditions_met, missing_conditions = evaluate_conditions(
config_text,
policy["conditions"],
template_blocks=template_blocks # Pass template blocks
)
if conditions_met:
status = policy["action"] # Compliant
elif missing_conditions:
status = "Non-Compliant"
else:
status = "Non-Compliant" # If no conditions met
results.append({
"Switch": switch_name,
"Interface": "N/A (General Config)",
"Policy": policy["name"],
"Status": status
})
# --- Interface Config Compliance Check ---
interface_blocks = re.findall(r"(interface \S+)(.*?)(?=interface \S+|$)", config_text, re.DOTALL)
processed_interfaces = set() # Track processed interfaces
for interface, config in interface_blocks:
interface_name = interface.split()[1]
# Skip processing if the interface has already been processed
if interface_name in processed_interfaces:
continue
# Add the interface to the processed set
processed_interfaces.add(interface_name)
for policy in st.session_state.advanced_policies:
if policy["scope"] in ["Interface Configuration", "Both"]:
conditions_met, missing_conditions = evaluate_conditions(
config,
policy["conditions"],
template_blocks=template_blocks # Pass template blocks
)
# Final Status Evaluation for Interface
if conditions_met:
status = policy["action"] # Compliant
elif re.search(r"shutdown", config, re.DOTALL):
status = "Shutdown" # Interface is shut down
else:
status = "Infrastructure Interface" # None of the conditions exist
results.append({
"Switch": switch_name,
"Interface": interface_name,
"Policy": policy["name"],
"Status": status
})
# Convert to DataFrame and Display
df = pd.DataFrame(results)
st.write(df)
# Download Report Button
st.download_button("📥 Download Report", df.to_csv(index=False), "compliance_report.csv", "text/csv")Editor is loading...
Leave a Comment