Ladda CSV-exporterna som används i Secure Score-reviewen.
Log Analytics CSV
Dataimport
Ladda review-underlag
CSV 1 och CSV 2 krävs. CSV 3 är valfri.
Arbetssätt
Exempel på vad du kan få fram
Praktiska scenarier för en månatlig Secure Score-review, från ny regression till patchkontroll på en specifik server.
Så använder du exemplen
Välj ett scenario, följ stegen i rätt flik och använd resultatet som underlag för prioritering, felsökning eller ett kundärende.
Subscriptions01
Varför fick en subscription regression?
En kund vill förstå varför Secure Score har gått ned sedan förra månaden.
Gör så här
Öppna Subscriptions.
Låt Score-status vara Regression.
Välj subscription i tabellen.
Behåll Recommendation-filter på nya eller regresserade ändringar.
Du får fram
Vilka recommendations som blev Unhealthy eller regresserade sedan förra månaden, inklusive severity och berörd resurs.
Subscriptions02
Vilka risker finns kvar?
Du vill fokusera på kvarstående risker och inte distraheras av patchrekommendationer.
Gör så här
Öppna Subscriptions och välj en subscription.
Välj Visa endast risker som är Unhealthy nu.
Låt Exkludera rekommendationer som börjar med Update vara ikryssad.
Du får fram
Alla aktiva, kvarstående recommendations för subscriptionen utan att update-risker tar fokus från övriga säkerhetsåtgärder.
Rekommendationer03
Hur stort är ett gemensamt problem?
Du vill förstå vilka recommendations som påverkar flest resurser och subscriptions.
Gör så här
Öppna Rekommendationer.
Välj Visa endast risker som är Unhealthy nu.
Välj en recommendation i listan.
Du får fram
Antal berörda subscriptions och resurser. I detaljvyn syns även när rekommendationen senast observerades i CSV 3-data.
Updates04
Är det en gammal eller ny patch?
Du vill avgöra om en update har varit Unhealthy länge eller om den precis har blivit aktuell.
Gör så här
Öppna Updates.
Sortera på Flest Unhealthy dagar först.
Välj en update i tabellen.
Kontrollera Först Unhealthy och Senast observerad.
Du får fram
Om det handlar om en äldre update som inte följt med i patchrutinen eller en ny patch som nyligen upptäckts.
Updates · felsökning05
Kunden säger att en server inte har patchats
Kunden upplever att en eller flera servrar inte får månatliga uppdateringar.
Gör så här
Öppna Updates.
Välj Windows eller Linux under Update-typ.
Sök på servernamn i Sök update, subscription eller enhet.
Välj en patch i tabellen för att se berörda enheter.
Du får fram
En lista med patches som berör servern, när de först blev Unhealthy och när de senast observerades. Det ger underlag för att jämföra mot kundens patchfönster och avgöra om patchningen har uteblivit.
För åldersbedömning: värden som Först Unhealthy, Senast observerad och Unhealthy dagar kommer från CSV 3. Kontrollera att KQL 3 hämtar den historikperiod ni vill använda, exempelvis 90 dagar.
Manual
Hämta CSV-filer från Azure Portal
Följ stegen nedan för att exportera de tre CSV-filerna som dashboarden använder.
1
Öppna rätt Log Analytics workspace
Öppna Azure Portal och gå till Log Analytics workspaces. Välj workspace logs-security och öppna sedan Logs.
2
Kör KQL-frågorna
Kopiera en KQL-fråga nedan, uppdatera SubscriptionMap med subscriptions som ska ingå och klicka på Run.
3
Ändra Show results till 5,000
Innan export: klicka på Show results ovanför resultatet och välj 5,000. Det minskar risken att exporten saknar rader.
4
Exportera CSV
Klicka på Share och välj Export to CSV (all columns). Spara filerna med tydliga namn, till exempel KQL1.csv, KQL2.csv och KQL3.csv.
5
Ladda filerna i Dataimport
Gå tillbaka till fliken Dataimport och ladda CSV 1, CSV 2 och valfritt CSV 3. CSV 3 används för Unhealthy duration.
Viktigt: Använd alltid Show results: 5,000 innan CSV-export. Om en fråga har fler än 5,000 rader behöver den begränsas eller filtreras i KQL för att inte missa data.
KQL 1 – Secure Score per subscription
Exportera som KQL1.csv.
let SubscriptionMap =
datatable(
SubscriptionId:string,
SubscriptionName:string,
Environment:string
)
[
"YOUR-SUBSCRIPTION-ID", "YOUR-SUBSCRIPTION-NAME", "Prod"
]
| extend SubscriptionId = tolower(SubscriptionId);
let CurrentMonthStart = startofmonth(now());
let PreviousMonthStart = startofmonth(now(), -1);
let ScoreHistory = materialize(
SecureScores
| where TimeGenerated >= PreviousMonthStart
| where DisplayName == "ASC score"
| project
TimeGenerated,
SubscriptionId = tolower(tostring(SecureScoresSubscriptionId)),
PercentageScore = todouble(PercentageScore)
| where SubscriptionId in (SubscriptionMap | project SubscriptionId)
);
let Current =
ScoreHistory
| where TimeGenerated >= CurrentMonthStart
| summarize arg_max(TimeGenerated, PercentageScore) by SubscriptionId
| project
SubscriptionId,
CurrentScorePercent = round(PercentageScore * 100.0, 2),
CurrentTime = TimeGenerated;
let Previous =
ScoreHistory
| where TimeGenerated >= PreviousMonthStart
| where TimeGenerated < CurrentMonthStart
| summarize arg_max(TimeGenerated, PercentageScore) by SubscriptionId
| project
SubscriptionId,
PreviousScorePercent = round(PercentageScore * 100.0, 2),
PreviousTime = TimeGenerated;
SubscriptionMap
| join kind=leftouter Current on SubscriptionId
| join kind=leftouter Previous on SubscriptionId
| extend ScoreChangePercentagePoints =
round(CurrentScorePercent - PreviousScorePercent, 2)
| extend Finding = case(
isnull(CurrentScorePercent), "No current data",
isnull(PreviousScorePercent), "No previous-month baseline",
ScoreChangePercentagePoints <= -1, "Regression",
ScoreChangePercentagePoints >= 1, "Improvement",
"No material change"
)
| project
SubscriptionName,
Environment,
SubscriptionId,
CurrentScorePercent,
PreviousScorePercent,
ScoreChangePercentagePoints,
Finding,
CurrentTime,
PreviousTime
| order by ScoreChangePercentagePoints asc
KQL 2 – Recommendation changes
Exportera som KQL2.csv. Den inkluderar både statusändringar och kvarstående Unhealthy-rekommendationer.
Valfri. Exportera som KQL3.csv för Unhealthy dagar och första observerade datum.
let SubscriptionMap =
datatable(
SubscriptionId:string,
SubscriptionName:string,
Environment:string
)
[
"YOUR-SUBSCRIPTION-ID", "YOUR-SUBSCRIPTION-NAME", "Prod"
]
| extend SubscriptionId = tolower(SubscriptionId);
let CurrentStateLookback = 31d;
let CurrentUnhealthy =
materialize(
SecurityRecommendation
| where TimeGenerated >= ago(CurrentStateLookback)
| extend SubscriptionId = tolower(tostring(split(AssessedResourceId, "/")[2]))
| where SubscriptionId in (SubscriptionMap | project SubscriptionId)
| project
TimeGenerated,
SubscriptionId,
RecommendationId,
AssessedResourceId,
RecommendationState
| summarize arg_max(TimeGenerated, RecommendationState)
by SubscriptionId, RecommendationId, AssessedResourceId
| where RecommendationState =~ "Unhealthy"
| project
SubscriptionId,
RecommendationId,
AssessedResourceId,
CurrentTime = TimeGenerated
);
let RelevantHistory =
materialize(
CurrentUnhealthy
| join kind=inner (
SecurityRecommendation
| extend SubscriptionId = tolower(tostring(split(AssessedResourceId, "/")[2]))
| where SubscriptionId in (SubscriptionMap | project SubscriptionId)
| project
TimeGenerated,
SubscriptionId,
RecommendationId,
RecommendationName,
RecommendationState,
AssessedResourceId
) on SubscriptionId, RecommendationId, AssessedResourceId
| project
SubscriptionId,
RecommendationId,
RecommendationName,
RecommendationState,
AssessedResourceId,
CurrentTime,
TimeGenerated
);
let LastNonUnhealthyBeforeCurrent =
RelevantHistory
| where TimeGenerated < CurrentTime
| where RecommendationState !~ "Unhealthy"
| summarize LastNonUnhealthyTime = max(TimeGenerated)
by SubscriptionId, RecommendationId, AssessedResourceId;
RelevantHistory
| join kind=leftouter LastNonUnhealthyBeforeCurrent
on SubscriptionId, RecommendationId, AssessedResourceId
| where isempty(LastNonUnhealthyTime) or TimeGenerated > LastNonUnhealthyTime
| where RecommendationState =~ "Unhealthy"
| summarize
FirstUnhealthyInCurrentPeriod = min(TimeGenerated),
LastUnhealthy = max(TimeGenerated),
Samples = count(),
RecommendationName = any(RecommendationName)
by SubscriptionId, RecommendationId, AssessedResourceId
| extend UnhealthyDays =
datetime_diff("day", LastUnhealthy, FirstUnhealthyInCurrentPeriod)
| join kind=inner (
SubscriptionMap
| project SubscriptionId, SubscriptionName, Environment
) on SubscriptionId
| project
SubscriptionName,
Environment,
SubscriptionId,
RecommendationName,
RecommendationId,
FirstUnhealthyInCurrentPeriod,
LastUnhealthy,
UnhealthyDays,
Samples,
AssessedResourceId
| order by UnhealthyDays desc, SubscriptionName asc
Subscriptions i scope
–
Efter filter
Regressioner
–
Finding = Regression
Genomsnittlig score
–
CurrentScorePercent
Visade risker
–
Efter riskfilter
Subscription-filter: påverkar endast denna flik och score-sammanfattningen. Score-status visar enbart
Alla, Regression och Improvement.
Subscription overview
Subscription
Environment
Current
Previous
Change
Finding
Recommendation-filter
Påverkar endast detaljer för vald subscription.
Gemensamma filter: Miljö och subscription-val påverkar endast denna flik.
Recommendation-filter
Påverkar endast Gemensamma rekommendationer.
Gemensamma rekommendationer
Recommendation
Severity
Subscriptions
Ändringar
Miljöer
Update-vyn är helt fristående från de övriga filtren. Den använder bara sina egna filter ovan och visar rekommendationer vars namn börjar med Update.
Äldsta Unhealthy dagar är högsta värdet bland berörda enheter för samma update.