Spaces:
Running
Running
import streamlit as st | |
import pandas as pd | |
import plotly.express as px | |
import plotly.graph_objects as go | |
import numpy as np | |
from datetime import datetime, timedelta | |
def render_monitoring(): | |
st.title("Monitoring Configuration") | |
# Dashboard layout for monitoring configuration | |
col1, col2 = st.columns([2, 3]) | |
with col1: | |
st.subheader("Monitoring Settings") | |
with st.form("monitoring_settings"): | |
st.markdown("### General Settings") | |
scan_frequency = st.select_slider( | |
"Scan Frequency", | |
options=["1 hour", "2 hours", "4 hours", "6 hours", "12 hours", "24 hours"], | |
value="4 hours" | |
) | |
intelligence_sources = st.multiselect( | |
"Intelligence Sources", | |
["Dark Web Forums", "Paste Sites", "Marketplaces", "Telegram Channels", "IRC Channels", "Ransomware Blogs", "Breach Databases", "Hacker Forums", "Social Media"], | |
default=["Dark Web Forums", "Paste Sites", "Marketplaces", "Ransomware Blogs"] | |
) | |
st.markdown("### Alert Thresholds") | |
col1a, col1b = st.columns(2) | |
with col1a: | |
critical_threshold = st.number_input("Critical Alert Threshold", min_value=1, max_value=100, value=80) | |
with col1b: | |
high_threshold = st.number_input("High Alert Threshold", min_value=1, max_value=100, value=60) | |
col1c, col1d = st.columns(2) | |
with col1c: | |
medium_threshold = st.number_input("Medium Alert Threshold", min_value=1, max_value=100, value=40) | |
with col1d: | |
low_threshold = st.number_input("Low Alert Threshold", min_value=1, max_value=100, value=20) | |
st.markdown("### Notification Channels") | |
email_notify = st.checkbox("Email Notifications", value=True) | |
if email_notify: | |
email_recipients = st.text_input("Email Recipients", value="[email protected], [email protected]") | |
slack_notify = st.checkbox("Slack Notifications", value=True) | |
if slack_notify: | |
slack_channel = st.text_input("Slack Channel", value="#security-alerts") | |
api_notify = st.checkbox("API Webhook", value=False) | |
if api_notify: | |
webhook_url = st.text_input("Webhook URL", placeholder="https://api.example.com/webhook") | |
sms_notify = st.checkbox("SMS Notifications", value=False) | |
if sms_notify: | |
phone_numbers = st.text_input("Phone Numbers", placeholder="+1234567890, +0987654321") | |
submit = st.form_submit_button("Save Configuration", type="primary") | |
if submit: | |
st.success("Monitoring configuration saved successfully!") | |
with col2: | |
st.subheader("Monitored Keywords & Entities") | |
# Tabs for different monitoring categories | |
tab1, tab2, tab3, tab4 = st.tabs(["Company Assets", "Credentials", "PII", "Custom Keywords"]) | |
with tab1: | |
st.markdown("### Company Assets Monitoring") | |
# Sample company assets to monitor | |
company_assets = pd.DataFrame({ | |
"Asset Type": ["Domain", "Domain", "IP Range", "Brand", "Brand", "Product", "Technology"], | |
"Value": ["company.com", "company-services.net", "198.51.100.0/24", "CompanyName", "ProductX", "ServiceY", "TechnologyZ"], | |
"Priority": ["High", "Medium", "High", "Critical", "High", "Medium", "Low"], | |
"Status": ["Active", "Active", "Active", "Active", "Active", "Active", "Active"] | |
}) | |
# Editable dataframe | |
edited_assets = st.data_editor( | |
company_assets, | |
num_rows="dynamic", | |
column_config={ | |
"Asset Type": st.column_config.SelectboxColumn( | |
"Asset Type", | |
options=["Domain", "IP Range", "Brand", "Product", "Technology", "Other"], | |
), | |
"Priority": st.column_config.SelectboxColumn( | |
"Priority", | |
options=["Critical", "High", "Medium", "Low"], | |
), | |
"Status": st.column_config.SelectboxColumn( | |
"Status", | |
options=["Active", "Paused"], | |
), | |
}, | |
use_container_width=True | |
) | |
with tab2: | |
st.markdown("### Credentials Monitoring") | |
# Sample credential monitoring settings | |
credential_monitoring = pd.DataFrame({ | |
"Email Domain": ["@company.com", "@company-services.net", "@product-x.com"], | |
"Include Subdomains": [True, True, False], | |
"Monitor Password Breach": [True, True, True], | |
"Alert Level": ["Critical", "High", "High"], | |
"Status": ["Active", "Active", "Active"] | |
}) | |
edited_credentials = st.data_editor( | |
credential_monitoring, | |
num_rows="dynamic", | |
column_config={ | |
"Include Subdomains": st.column_config.CheckboxColumn( | |
"Include Subdomains", | |
help="Monitor all subdomains", | |
), | |
"Monitor Password Breach": st.column_config.CheckboxColumn( | |
"Monitor Password Breach", | |
), | |
"Alert Level": st.column_config.SelectboxColumn( | |
"Alert Level", | |
options=["Critical", "High", "Medium", "Low"], | |
), | |
"Status": st.column_config.SelectboxColumn( | |
"Status", | |
options=["Active", "Paused"], | |
), | |
}, | |
use_container_width=True | |
) | |
with tab3: | |
st.markdown("### PII Monitoring") | |
# Sample PII monitoring settings | |
pii_monitoring = pd.DataFrame({ | |
"PII Type": ["SSN", "Credit Card", "Bank Account", "Passport Number", "Driver License"], | |
"Monitor": [True, True, True, False, False], | |
"Alert Level": ["Critical", "Critical", "High", "High", "Medium"], | |
"Status": ["Active", "Active", "Active", "Paused", "Paused"] | |
}) | |
edited_pii = st.data_editor( | |
pii_monitoring, | |
num_rows="dynamic", | |
column_config={ | |
"PII Type": st.column_config.SelectboxColumn( | |
"PII Type", | |
options=["SSN", "Credit Card", "Bank Account", "Passport Number", "Driver License", "Health Information", "Other"], | |
), | |
"Monitor": st.column_config.CheckboxColumn( | |
"Monitor", | |
), | |
"Alert Level": st.column_config.SelectboxColumn( | |
"Alert Level", | |
options=["Critical", "High", "Medium", "Low"], | |
), | |
"Status": st.column_config.SelectboxColumn( | |
"Status", | |
options=["Active", "Paused"], | |
), | |
}, | |
use_container_width=True | |
) | |
with tab4: | |
st.markdown("### Custom Keywords") | |
# Sample custom keywords | |
custom_keywords = pd.DataFrame({ | |
"Keyword": ["confidential memo", "project phoenix", "merger", "acquisition", "layoff", "security breach"], | |
"Category": ["Internal Document", "Project", "Financial", "Financial", "HR", "Security"], | |
"Alert Level": ["Critical", "High", "Critical", "Critical", "High", "Critical"], | |
"Status": ["Active", "Active", "Active", "Active", "Active", "Active"] | |
}) | |
edited_keywords = st.data_editor( | |
custom_keywords, | |
num_rows="dynamic", | |
column_config={ | |
"Category": st.column_config.SelectboxColumn( | |
"Category", | |
options=["Internal Document", "Project", "Financial", "HR", "Security", "Product", "Other"], | |
), | |
"Alert Level": st.column_config.SelectboxColumn( | |
"Alert Level", | |
options=["Critical", "High", "Medium", "Low"], | |
), | |
"Status": st.column_config.SelectboxColumn( | |
"Status", | |
options=["Active", "Paused"], | |
), | |
}, | |
use_container_width=True | |
) | |
# Monitoring sources and coverage | |
st.markdown("---") | |
st.subheader("Monitoring Sources & Coverage") | |
# Create tabs for different monitoring source categories | |
source_tab1, source_tab2, source_tab3 = st.tabs(["Dark Web Coverage", "Source Categories", "Geographic Coverage"]) | |
with source_tab1: | |
# Dark web monitoring sources | |
st.markdown("### Dark Web Monitoring Sources") | |
# Sample data for dark web sources | |
dark_web_sources = pd.DataFrame({ | |
"Source Type": ["Market", "Forum", "Forum", "Market", "Paste Site", "Leak Site", "Chat", "Market"], | |
"Name": ["AlphaBay", "XSS Forum", "Exploit.in", "ASAP Market", "DeepPaste", "DarkLeak", "Telegram", "White House"], | |
"Focus": ["General", "Hacking", "Credentials", "Drugs/Fraud", "Text sharing", "Data leaks", "Communication", "General"], | |
"Coverage": [95, 90, 85, 80, 75, 70, 65, 60], | |
"Status": ["Active", "Active", "Active", "Active", "Active", "Active", "Active", "Active"] | |
}) | |
fig = px.bar( | |
dark_web_sources, | |
x="Name", | |
y="Coverage", | |
color="Coverage", | |
color_continuous_scale=["#2ECC71", "#F1C40F", "#E74C3C"], | |
text="Coverage", | |
height=400 | |
) | |
fig.update_layout( | |
paper_bgcolor='rgba(26, 26, 26, 0)', | |
plot_bgcolor='rgba(26, 26, 26, 0)', | |
xaxis=dict( | |
title=None, | |
tickfont=dict(color='#ECF0F1') | |
), | |
yaxis=dict( | |
title="Coverage Percentage", | |
showgrid=True, | |
gridcolor='rgba(44, 62, 80, 0.3)', | |
tickfont=dict(color='#ECF0F1') | |
), | |
coloraxis_showscale=False | |
) | |
fig.update_traces(texttemplate='%{text}%', textposition='outside') | |
st.plotly_chart(fig, use_container_width=True) | |
# Source details table | |
st.dataframe(dark_web_sources, use_container_width=True) | |
with source_tab2: | |
# Source category distribution | |
st.markdown("### Monitoring by Source Category") | |
# Sample data for source categories | |
source_categories = { | |
"Category": ["Dark Web Markets", "Hacking Forums", "Paste Sites", "Telegram Channels", "IRC Channels", "Leak Sites", "Ransomware Blogs", "Social Media"], | |
"Sources Count": [12, 15, 5, 18, 8, 7, 6, 10], | |
"Coverage Score": [90, 85, 75, 70, 60, 95, 80, 65] | |
} | |
source_df = pd.DataFrame(source_categories) | |
fig = px.scatter( | |
source_df, | |
x="Sources Count", | |
y="Coverage Score", | |
color="Coverage Score", | |
color_continuous_scale=["#E74C3C", "#F1C40F", "#2ECC71"], | |
size="Sources Count", | |
hover_name="Category", | |
height=400 | |
) | |
fig.update_layout( | |
paper_bgcolor='rgba(26, 26, 26, 0)', | |
plot_bgcolor='rgba(26, 26, 26, 0)', | |
xaxis=dict( | |
title="Number of Sources", | |
showgrid=True, | |
gridcolor='rgba(44, 62, 80, 0.3)', | |
tickfont=dict(color='#ECF0F1') | |
), | |
yaxis=dict( | |
title="Coverage Score (%)", | |
showgrid=True, | |
gridcolor='rgba(44, 62, 80, 0.3)', | |
tickfont=dict(color='#ECF0F1') | |
), | |
coloraxis_showscale=False | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
# Category details | |
st.dataframe(source_df, use_container_width=True) | |
with source_tab3: | |
# Geographic coverage | |
st.markdown("### Geographic Monitoring Coverage") | |
# World map showing coverage | |
st.image("https://images.unsplash.com/photo-1451187580459-43490279c0fa", | |
caption="Global monitoring coverage across dark web sources", | |
use_column_width=True) | |
# Regional coverage metrics | |
col_geo1, col_geo2, col_geo3, col_geo4 = st.columns(4) | |
with col_geo1: | |
st.metric( | |
label="North America", | |
value="92%", | |
delta="3%", | |
delta_color="normal" | |
) | |
with col_geo2: | |
st.metric( | |
label="Europe", | |
value="88%", | |
delta="5%", | |
delta_color="normal" | |
) | |
with col_geo3: | |
st.metric( | |
label="Asia Pacific", | |
value="76%", | |
delta="8%", | |
delta_color="normal" | |
) | |
with col_geo4: | |
st.metric( | |
label="Rest of World", | |
value="65%", | |
delta="12%", | |
delta_color="normal" | |
) | |
# Monitoring performance metrics | |
st.markdown("---") | |
st.subheader("Monitoring Performance") | |
# Performance metrics | |
perf_col1, perf_col2, perf_col3, perf_col4 = st.columns(4) | |
with perf_col1: | |
st.metric( | |
label="Scan Completion Rate", | |
value="98.7%", | |
delta="0.5%", | |
delta_color="normal" | |
) | |
with perf_col2: | |
st.metric( | |
label="Avg. Scan Duration", | |
value="43 min", | |
delta="-7 min", | |
delta_color="normal" | |
) | |
with perf_col3: | |
st.metric( | |
label="Monitored Keywords", | |
value="1,247", | |
delta="23", | |
delta_color="normal" | |
) | |
with perf_col4: | |
st.metric( | |
label="Coverage Index", | |
value="87/100", | |
delta="5", | |
delta_color="normal" | |
) | |
# Performance charts | |
st.markdown("### Performance Trends") | |
perf_tab1, perf_tab2 = st.tabs(["Scan Performance", "Detection Accuracy"]) | |
with perf_tab1: | |
# Generate dates for the past 30 days | |
dates = [(datetime.now() - timedelta(days=i)).strftime('%Y-%m-%d') for i in range(30, 0, -1)] | |
# Sample data for scan performance | |
scan_times = np.random.normal(45, 5, 30).astype(int) # Mean 45 minutes, std 5 minutes | |
success_rates = np.random.normal(98, 1, 30) # Mean 98%, std 1% | |
success_rates = [min(100, max(90, rate)) for rate in success_rates] # Clamp between 90-100% | |
scan_data = pd.DataFrame({ | |
'Date': dates, | |
'Scan Time (min)': scan_times, | |
'Success Rate (%)': success_rates | |
}) | |
# Create a figure with two y-axes | |
fig = go.Figure() | |
# Add scan time line | |
fig.add_trace(go.Scatter( | |
x=scan_data['Date'], | |
y=scan_data['Scan Time (min)'], | |
name='Scan Time (min)', | |
line=dict(color='#3498DB', width=2) | |
)) | |
# Add success rate line on secondary y-axis | |
fig.add_trace(go.Scatter( | |
x=scan_data['Date'], | |
y=scan_data['Success Rate (%)'], | |
name='Success Rate (%)', | |
line=dict(color='#2ECC71', width=2), | |
yaxis='y2' | |
)) | |
# Configure the layout with two y-axes | |
fig.update_layout( | |
paper_bgcolor='rgba(26, 26, 26, 0)', | |
plot_bgcolor='rgba(26, 26, 26, 0)', | |
xaxis=dict( | |
title="Date", | |
showgrid=False, | |
tickfont=dict(color='#ECF0F1') | |
), | |
yaxis=dict( | |
title="Scan Time (min)", | |
showgrid=True, | |
gridcolor='rgba(44, 62, 80, 0.3)', | |
tickfont=dict(color='#ECF0F1'), | |
range=[0, 60] | |
), | |
yaxis2=dict( | |
title="Success Rate (%)", | |
showgrid=False, | |
tickfont=dict(color='#ECF0F1'), | |
overlaying='y', | |
side='right', | |
range=[90, 100] | |
), | |
legend=dict( | |
orientation="h", | |
yanchor="bottom", | |
y=1.02, | |
xanchor="right", | |
x=1, | |
font=dict(color='#ECF0F1') | |
), | |
height=400 | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
with perf_tab2: | |
# Sample data for detection accuracy | |
accuracy_data = pd.DataFrame({ | |
'Date': dates, | |
'True Positives': np.random.randint(80, 100, 30), | |
'False Positives': np.random.randint(5, 15, 30), | |
'Precision': np.random.normal(92, 2, 30), | |
'Recall': np.random.normal(90, 3, 30) | |
}) | |
# Ensure precision and recall are within reasonable bounds | |
accuracy_data['Precision'] = accuracy_data['Precision'].apply(lambda x: min(100, max(80, x))) | |
accuracy_data['Recall'] = accuracy_data['Recall'].apply(lambda x: min(100, max(80, x))) | |
# Create a figure with stacked bars and lines | |
fig = go.Figure() | |
# Add stacked bars for true and false positives | |
fig.add_trace(go.Bar( | |
x=accuracy_data['Date'], | |
y=accuracy_data['True Positives'], | |
name='True Positives', | |
marker_color='#2ECC71' | |
)) | |
fig.add_trace(go.Bar( | |
x=accuracy_data['Date'], | |
y=accuracy_data['False Positives'], | |
name='False Positives', | |
marker_color='#E74C3C' | |
)) | |
# Add lines for precision and recall | |
fig.add_trace(go.Scatter( | |
x=accuracy_data['Date'], | |
y=accuracy_data['Precision'], | |
name='Precision (%)', | |
line=dict(color='#3498DB', width=2), | |
yaxis='y2' | |
)) | |
fig.add_trace(go.Scatter( | |
x=accuracy_data['Date'], | |
y=accuracy_data['Recall'], | |
name='Recall (%)', | |
line=dict(color='#F1C40F', width=2), | |
yaxis='y2' | |
)) | |
# Configure the layout | |
fig.update_layout( | |
paper_bgcolor='rgba(26, 26, 26, 0)', | |
plot_bgcolor='rgba(26, 26, 26, 0)', | |
barmode='stack', | |
xaxis=dict( | |
title="Date", | |
showgrid=False, | |
tickfont=dict(color='#ECF0F1') | |
), | |
yaxis=dict( | |
title="Alert Count", | |
showgrid=True, | |
gridcolor='rgba(44, 62, 80, 0.3)', | |
tickfont=dict(color='#ECF0F1') | |
), | |
yaxis2=dict( | |
title="Percentage (%)", | |
showgrid=False, | |
tickfont=dict(color='#ECF0F1'), | |
overlaying='y', | |
side='right', | |
range=[80, 100] | |
), | |
legend=dict( | |
orientation="h", | |
yanchor="bottom", | |
y=1.02, | |
xanchor="right", | |
x=1, | |
font=dict(color='#ECF0F1') | |
), | |
height=400 | |
) | |
st.plotly_chart(fig, use_container_width=True) | |