# M365 Security Scorecard - Code Snippets Reference
## Key Code Sections from app.py
### 1. Security Categories Definition
```python
SECURITY_CHECKS = {
"identity_access": {
"en": "Identity & Access",
"fr": "Identite et Acces",
"checks": [
{"en": "MFA enabled for all users", "fr": "MFA activee pour tous les utilisateurs"},
{"en": "Conditional Access policies configured", "fr": "Politiques d'acces conditionnel configurees"},
# ... 6 more checks
]
},
# ... 5 more categories
}
```
### 2. KQL Hunting Queries
```python
KQL_HUNTING_QUERIES = [
{
"title": "Detect MFA Bypass Attempts",
"query": "SigninLogs | where ConditionalAccessStatus == 'failure' and AuthenticationRequirement == 'multiFactorAuthentication' | summarize Count=count() by UserPrincipalName, IPAddress, ClientAppUsed"
},
# ... 4 more queries
]
```
### 3. Real-Time Score Calculation
```python
def calculate_scores(checks_state):
"""Calculate scores per category"""
scores = {}
recommendations = []
for category_id, category_data in SECURITY_CHECKS.items():
if category_id in checks_state:
checked_items = sum(checks_state[category_id])
total_items = len(category_data["checks"])
score = (checked_items / total_items) * 100 if total_items > 0 else 0
scores[category_id] = score
# Generate recommendations...
overall_score = sum(scores.values()) / len(scores) if scores else 0
return scores, overall_score, recommendations
```
### 4. Radar Chart Creation
```python
def create_radar_chart(scores, language):
"""Create radar chart for category scores"""
categories_display = [SECURITY_CHECKS[cat_id][language] for cat_id in scores.keys()]
values = list(scores.values())
fig = go.Figure(data=go.Scatterpolar(
r=values,
theta=categories_display,
fill='toself',
name='Security Score',
line=dict(color='#4f46e5'),
fillcolor='rgba(79, 70, 229, 0.2)'
))
fig.update_layout(
polar=dict(radialaxis=dict(visible=True, range=[0, 100])),
showlegend=False,
height=400
)
return fig
```
### 5. Gauge Chart Creation
```python
def create_gauge_chart(overall_score, language):
"""Create gauge chart for overall maturity"""
fig = go.Figure(go.Indicator(
mode="gauge+number+delta",
value=overall_score,
title={'text': "Overall Security Maturity Score"},
gauge={
'axis': {'range': [0, 100]},
'bar': {'color': "darkblue"},
'steps': [
{'range': [0, 25], 'color': "rgba(255, 0, 0, 0.2)"},
{'range': [25, 50], 'color': "rgba(255, 165, 0, 0.2)"},
{'range': [50, 75], 'color': "rgba(255, 255, 0, 0.2)"},
{'range': [75, 100], 'color': "rgba(0, 255, 0, 0.2)"}
]
}
))
fig.update_layout(height=400)
return fig
```
### 6. Smart Recommendations Engine
```python
def create_recommendations_html(recommendations, language, limit=5):
"""Create recommendations panel"""
if not recommendations:
return "
All checks passed! Your M365 security posture is strong.
"
html = "Top 5 Priority Fixes
"
for i, rec in enumerate(recommendations[:limit], 1):
check_text = rec["check"][language]
category_text = rec["category"][language]
html += f"- {category_text}: {check_text}
"
html += "
"
return html
```
### 7. Markdown Report Export
```python
def generate_markdown_report(checks_state, scores, overall_score, language):
"""Generate markdown report for export"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
lang_code = "FR" if language == "fr" else "EN"
report = f"# M365 Security Scorecard Report\n\n"
report += f"**Report Generated:** {timestamp}\n"
report += f"**Language:** {lang_code}\n"
report += f"**Overall Security Score:** {overall_score:.1f}%\n\n"
# Add detailed assessment...
return report
```
### 8. Gradio Interface Setup
```python
with gr.Blocks(title="M365 Security Scorecard",
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo")) as demo:
gr.Markdown("# M365 Security Scorecard - Microsoft 365 Security Assessment")
with gr.Row():
language_radio = gr.Radio(
choices=["EN - English", "FR - Francais"],
value="EN - English",
label="Language / Langue",
interactive=True
)
# Create tabs for each category
with gr.Tabs():
check_components = {}
for category_id, category_data in SECURITY_CHECKS.items():
with gr.Tab(label=category_data["en"]):
# Create checkboxes for each check
for i, check in enumerate(category_data["checks"]):
check_key = f"{category_id}_{i}"
check_components[check_key] = gr.Checkbox(
label=f"{check['en']} / {check['fr']}",
value=False
)
```
### 9. Real-Time Update Handler
```python
def update_display(language, *check_args):
"""Update all displays based on checks"""
# Convert check_args to dictionary structure
checks_state = {}
arg_index = 0
for category_id in SECURITY_CHECKS.keys():
num_checks = len(SECURITY_CHECKS[category_id]["checks"])
checks_state[category_id] = list(check_args[arg_index:arg_index + num_checks])
arg_index += num_checks
# Calculate scores
scores, overall_score, recommendations = calculate_scores(checks_state)
# Create visualizations
radar = create_radar_chart(scores, language)
gauge = create_gauge_chart(overall_score, language)
# Create recommendations
recommendations_html = create_recommendations_html(recommendations, language)
# Create KQL section
kql_html = create_kql_queries_html(language)
# Create markdown report
markdown_report = generate_markdown_report(checks_state, scores, overall_score, language)
return radar, gauge, recommendations_html, kql_html, markdown_report
```
### 10. Event Binding
```python
# Change event to update results in real-time
language_radio.change(
fn=lambda *args: update_display("EN" if args[0] == "EN - English" else "FR", *args[1:]),
inputs=[language_radio] + list(check_components.values()),
outputs=[radar_chart, gauge_chart, recommendations_html, kql_html, markdown_output]
)
for component in check_components.values():
component.change(
fn=lambda *args: update_display("EN" if args[0] == "EN - English" else "FR", *args[1:]),
inputs=[language_radio] + list(check_components.values()),
outputs=[radar_chart, gauge_chart, recommendations_html, kql_html, markdown_output]
)
```
## HTML Generation Functions
### KQL Queries Display
```python
def create_kql_queries_html(language):
"""Create KQL hunting queries section"""
html = "M365 Threat Hunting - KQL Queries
"
for i, query_data in enumerate(KQL_HUNTING_QUERIES, 1):
html += f"{i}. {query_data['title']}
"
html += f"{query_data['query']}"
return html
```
### Resources Display
```python
def create_resources_html(language):
"""Create resources section with backlinks"""
resources = [
{"title": "Top 10 Tools for M365 Security Analysis", "url": "..."},
# ... 10 more resources
]
html = "Resources & Learning Materials
"
return html
```
## Gradio 4.44.0 Compatibility Notes
### Correct Patterns Used
1. **Tab Usage**: Using `gr.Tab` instead of deprecated `gr.TabItem`
2. **No Scale Parameter**: Avoiding `scale=` parameter on components
3. **No gr.update()**: Direct function returns instead of gr.update()
4. **f-strings**: No backslashes in f-strings
5. **Event Binding**: Using .change() and .click() properly
### Avoided Patterns
- No `scale=` on components
- No `gr.update()` calls
- No `gr.TabItem()` usage
- No backslashes in f-strings
- No deprecated component API
## Configuration Examples
### YAML Frontmatter (README.md)
```yaml
---
title: M365 Security Scorecard
emoji: 🛡️
colorFrom: blue
colorTo: indigo
sdk: gradio
sdk_version: 4.44.0
python_version: "3.10"
app_file: app.py
pinned: false
license: apache-2.0
tags:
- cybersecurity
- microsoft-365
- m365-security
---
```
### Theme Configuration
```python
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo")
```
## Dependencies
```python
import gradio as gr
import plotly.graph_objects as go
from datetime import datetime
import json
```
All dependencies are standard and production-ready.
---
For complete code, see `/home/deeptechadmin/hf/spaces/m365-scorecard/app.py`