diff --git a/SQL Scripts/SQLI-SYN-001.sql b/SQL Scripts/SQLI-SYN-001.sql new file mode 100644 index 0000000..32a41c3 --- /dev/null +++ b/SQL Scripts/SQLI-SYN-001.sql @@ -0,0 +1,65 @@ +/* + SQLI-SYN-001 – Et syntetisk tjek fejler + ======================================== + + Hvad og hvorfor + Agenten gør det, en bruger eller applikation ville gøre – forbinder til en port, henter en side, logger på SQL Server + og kører en forespørgsel, slår et navn op, logger på Dynamics AX – og det fejler. Er tjekket knyttet til en tjeneste + på en Windows-server, og kører tjenesten, siges det direkte: "… svarer ikke, selv om tjenesten kører" – den fejl, + en tjenesteovervågning alene ikke ser. + + Tærskler (agentens appsettings.json og tjekkets indstillinger) + SQLInsight:SyntheticChecks:FailuresBeforeFinding standard 2 (fejl i træk før et fund: ét tabt svar er ingen alarm) + Pr. tjek: interval (standard 300 s, 60–86400) og timeout (standard 15 s, AX 60 s, højst 120). + + Alvor + Høj. + + Rettigheder + TCP, HTTP(S), DNS: ingen ud over netværksadgang fra agentens server. HTTP med Windows-godkendelse: agentens konto. + SQL: login'et i tjekket (agentens Windows-konto eller et SQL-login, hvis adgangskode krypteres til agenten som i 1.3) + skal kunne logge ind og køre forespørgslen; least-privilege-login'et fra grant-least-privilege.sql er nok til standardforespørgslen. + AX-logon: agentens Windows-konto skal være AX-bruger (i firmaet), og .NET Business Connector skal være installeret på + agentens server; ellers testes kun AOS-porten (og resultatet siger det). + Tjenestens tilstand: WMI Remote Enable på root\cimv2 + læseret på Service Control Manager på tjenestens server. + + Understøttede versioner + SQL: SQL Server 2005 og nyere (SqlClient, ODBC-fallback for 2005). AX-logon: AX 2009 (kræver Windows PowerShell + 2.0-motoren) og AX 2012. Windows-tjenester: Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/Synthetic/SyntheticCheckRunner.cs – SyntheticCheckRunner.RunAsync (TcpAsync, HttpAsync, SqlAsync, + DnsAsync, AxAsync), AX-logon: src/SQLInsight.Servers/Synthetic/AxBusinessConnector.cs og ax-logon.ps1. Køres efter + tjekkets interval af src/SQLInsight.Agent/Servers/SyntheticCheckService.cs – RunCheckAsync, som også slår den tilknyttede + tjenestes tilstand op (CimQueries.SingleServiceQuery). + Regel + src/SQLInsight.Rules/Servers/SyntheticCheckRules.cs – SyntheticCheckFailingRule + + Evaluering + Har de seneste FailuresBeforeFinding kørsler alle fejlet, er det et fund. Titlen siger, om den tilknyttede tjeneste + kører, er stoppet, eller om tjekket blot fejler, med fejlteksten som måling (følsom). + + SQL: Ved et SQL-tjek kører agenten præcis dette på den instans, tjekket peger på (ændrer intet: forespørgslen + valideres som én skrivebeskyttet SELECT, både når den gemmes og før den køres, og køres i en transaktion, der altid + rulles tilbage). Hver GO er en separat kommando på samme forbindelse. +*/ + +-- Variant: SQL-tjek med standardforespørgslen (alle versioner fra SQL Server 2005) +SET LOCK_TIMEOUT 5000; SET DEADLOCK_PRIORITY LOW; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +GO +-- Kun hvis tjekket har en database (tjekkets "Database", ] fordoblet): USE []; +BEGIN TRANSACTION; +GO +SELECT 1 +GO +IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; +GO + +/* + Ikke-SQL-tjek, efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + TCP: Test-NetConnection -ComputerName aos01 -Port 2712 + HTTP: Invoke-WebRequest -Uri https://ep.firma.local/ -UseDefaultCredentials -UseBasicParsing | Select-Object StatusCode + DNS: Resolve-DnsName aos01.firma.local + AX: Test-NetConnection -ComputerName aos01 -Port 2712 (logon: se src/SQLInsight.Servers/Synthetic/ax-logon.ps1) + Tjeneste: Get-CimInstance -ComputerName aos01 -Query "SELECT Name, DisplayName, State, StartMode, ExitCode FROM Win32_Service WHERE Name = 'AOS60`$01'" +*/ diff --git a/SQL Scripts/SQLI-SYN-002.sql b/SQL Scripts/SQLI-SYN-002.sql new file mode 100644 index 0000000..43b4cc3 --- /dev/null +++ b/SQL Scripts/SQLI-SYN-002.sql @@ -0,0 +1,48 @@ +/* + SQLI-SYN-002 – Et syntetisk tjek svarer langsomt + ================================================= + + Hvad og hvorfor + Tjekket lykkes, men svaret har de seneste gange taget længere end tjekkets grænse. Brugerne oplever det som en langsom + applikation, længe før den holder op med at svare. + + Tærskler (agentens appsettings.json og tjekkets indstillinger) + Pr. tjek: "Langsomt svar over (ms)" (insight.SyntheticChecks.SettingsJson: warnMilliseconds). Uden grænse: "ikke relevant". + SQLInsight:SyntheticChecks:SlowRunsBeforeFinding standard 3 (langsomme svar i træk før et fund) + + Alvor + Middel. + + Rettigheder + Som SQLI-SYN-001. + + Understøttede versioner + Som SQLI-SYN-001. + + Collector + src/SQLInsight.Servers/Synthetic/SyntheticCheckRunner.cs – SyntheticCheckRunner.RunAsync (DurationMs: hele tjekket, for + SQL login + forespørgsel), fra src/SQLInsight.Agent/Servers/SyntheticCheckService.cs – RunCheckAsync. + Regel + src/SQLInsight.Rules/Servers/SyntheticCheckRules.cs – SyntheticCheckSlowRule + + Evaluering + Er de seneste SlowRunsBeforeFinding kørsler alle lykkedes og alle langsommere end grænsen, er det et fund. + + SQL: Et SQL-tjek kører præcis det samme som i SQLI-SYN-001 (svartiden er login plus forespørgsel): +*/ + +-- Variant: SQL-tjek med standardforespørgslen (alle versioner fra SQL Server 2005) +SET LOCK_TIMEOUT 5000; SET DEADLOCK_PRIORITY LOW; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +GO +BEGIN TRANSACTION; +GO +SELECT 1 +GO +IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; +GO + +/* + Ikke-SQL-tjek, efterprøv svartiden med PowerShell (skrivebeskyttet): + Measure-Command { Invoke-WebRequest -Uri https://ep.firma.local/ -UseDefaultCredentials -UseBasicParsing } | Select-Object TotalMilliseconds + Measure-Command { Test-NetConnection -ComputerName aos01 -Port 2712 } | Select-Object TotalMilliseconds +*/ diff --git a/SQL Scripts/SQLI-SYN-003.sql b/SQL Scripts/SQLI-SYN-003.sql new file mode 100644 index 0000000..825ea78 --- /dev/null +++ b/SQL Scripts/SQLI-SYN-003.sql @@ -0,0 +1,39 @@ +/* + SQLI-SYN-003 – TLS-certifikatet udløber snart + ============================================== + + Hvad og hvorfor + Når certifikatet på en HTTPS-adresse udløber, afviser browsere og integrationer forbindelsen (eller viser en + sikkerhedsadvarsel), og siden er i praksis nede. Udløbsdatoen læses ved hvert HTTPS-tjek – også når certifikatet + afvises (fx selvsigneret). + + Tærskler (agentens appsettings.json) + SQLInsight:SyntheticChecks:CertificateWarningDays standard 21 (fund når certifikatet udløber inden for så mange dage) + SQLInsight:SyntheticChecks:CertificateCriticalDays standard 7 (Høj inden for så mange dage) + + Alvor + Middel; Høj inden for CertificateCriticalDays; Kritisk når det er udløbet. + + Rettigheder + Ingen ud over netværksadgang fra agentens server til adressen. + + Understøttede versioner + Alle HTTPS-servere (TLS 1.2 og nyere fra agentens server). + + Collector + src/SQLInsight.Servers/Synthetic/SyntheticCheckRunner.cs – HttpAsync (RemoteCertificateValidationCallback gemmer + certifikatets NotAfter og Subject), fra src/SQLInsight.Agent/Servers/SyntheticCheckService.cs – RunCheckAsync. + Regel + src/SQLInsight.Rules/Servers/SyntheticCheckRules.cs – CertificateExpiryRule + + Evaluering + Kun HTTP-tjek med https://. Den nyeste kørsel, der har set et certifikat, bruges: dage til udløb = NotAfter − nu. + Uden set certifikat endnu: "ikke målbar". Andre tjek: "ikke relevant". + + Reglen bruger ikke SQL. Tjekket er en HTTPS GET; filen indeholder kun kommentarer og ændrer intet. + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server): + $c = New-Object System.Net.Sockets.TcpClient('ep.firma.local', 443) + $s = New-Object System.Net.Security.SslStream($c.GetStream(), $false, { $true }) + $s.AuthenticateAsClient('ep.firma.local'); $s.RemoteCertificate.GetExpirationDateString(); $c.Close() +*/ diff --git a/SQL Scripts/SQLI-WIN-001.sql b/SQL Scripts/SQLI-WIN-001.sql new file mode 100644 index 0000000..83abb09 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-001.sql @@ -0,0 +1,48 @@ +/* + SQLI-WIN-001 – CPU-forbruget er højt i længere tid + =================================================== + + Hvad og hvorfor + Serverens processorer har i gennemsnit været næsten fuldt belastet i en længere periode. Alt på serveren bliver + langsommere (forespørgsler, AOS-kald, fildeling, logon). Korte toppe er normale og giver intet fund. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Cpu:HighPercent standard 90 (gennemsnitlig CPU i procent) + SQLInsight:Servers:Cpu:SustainedMinutes standard 15 (perioden gennemsnittet tages over) + Målingerne skal dække mindst 80 % af perioden (en kort top efter et hul tæller ikke). + + Alvor + Høj; Kritisk når gennemsnittet er 98 % eller derover. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + Performance Monitor Users (ydelsestællere) + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere (WS-Man fra Windows Server 2012 / WinRM 3.0; DCOM på alle). + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetPerformanceAsync (CimQueries.ProcessorQuery), + hvert minut (SQLInsight:Servers:Intervals:performance) fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync. + Beregning: src/SQLInsight.Core/Servers/ServerPerformance.cs – ServerPerformanceMath.Cpu. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerCpuRule + + Evaluering + Hvert minut læses tælleren Processor(_Total)\% Processor Time som rå værdi. CPU for minuttet er + 100 × (1 − Δ tomgangstid / Δ tid) mellem to læsninger (PERF_100NSEC_TIMER_INV), altså gennemsnittet over hele + minuttet, ikke et øjebliksbillede. Er gennemsnittet af minutterne i de seneste SustainedMinutes minutter mindst + HighPercent, er det et fund. Uden to læsninger endnu: "ikke målbar". + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT PercentProcessorTime, Timestamp_Sys100NS FROM Win32_PerfRawData_PerfOS_Processor WHERE Name = '_Total' + SELECT NumberOfLogicalProcessors FROM Win32_ComputerSystem + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER # DCOM: -SessionOption (New-CimSessionOption -Protocol Dcom) + $q = "SELECT PercentProcessorTime, Timestamp_Sys100NS FROM Win32_PerfRawData_PerfOS_Processor WHERE Name = '_Total'" + $a = Get-CimInstance -CimSession $s -Query $q; Start-Sleep -Seconds 60; $b = Get-CimInstance -CimSession $s -Query $q + 100 * (1 - ($b.PercentProcessorTime - $a.PercentProcessorTime) / ($b.Timestamp_Sys100NS - $a.Timestamp_Sys100NS)) +*/ diff --git a/SQL Scripts/SQLI-WIN-002.sql b/SQL Scripts/SQLI-WIN-002.sql new file mode 100644 index 0000000..7392616 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-002.sql @@ -0,0 +1,47 @@ +/* + SQLI-WIN-002 – Serveren har næsten ingen ledig hukommelse + ========================================================== + + Hvad og hvorfor + Når Windows løber tør for ledig hukommelse, flyttes data til sidefilen, alt bliver langsomt, og processer kan fejle + med "out of memory". SQL Server kan blive tvunget til at give hukommelse tilbage. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Memory:AvailablePercent standard 5 (andel ledig af den samlede hukommelse) + SQLInsight:Servers:Memory:AvailableMegabytes standard 1024 (ledig hukommelse i MB) + Begge skal være under grænsen (gennemsnit over 5 minutter), så store SQL Server-hosts, der bevidst har lidt + tilbage, men stadig flere GB, ikke giver fund. + + Alvor + Middel; Høj under 2 % og under 256 MB. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + Performance Monitor Users + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetPerformanceAsync (CimQueries.MemoryQuery) og + Session.GetOperatingSystemAsync (CimQueries.OperatingSystemQuery), hvert minut fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerMemoryRule + + Evaluering + Ledig hukommelse er Memory\Available MBytes; andelen er den i forhold til Win32_OperatingSystem.TotalVisibleMemorySize. + Gennemsnittet over de seneste 5 minutter (mindst 80 % dækket) sammenlignes med begge grænser. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT AvailableMBytes, PagesPersec, CommittedBytes, CommitLimit, Timestamp_PerfTime, Frequency_PerfTime FROM Win32_PerfRawData_PerfOS_Memory + SELECT Caption, Version, BuildNumber, LastBootUpTime, TotalVisibleMemorySize, CSName FROM Win32_OperatingSystem + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + $m = Get-CimInstance -CimSession $s -Query "SELECT AvailableMBytes FROM Win32_PerfRawData_PerfOS_Memory" + $o = Get-CimInstance -CimSession $s -Query "SELECT TotalVisibleMemorySize FROM Win32_OperatingSystem" + "{0} MB ledig ({1:N1} %)" -f $m.AvailableMBytes, (100 * $m.AvailableMBytes * 1024 / $o.TotalVisibleMemorySize) +*/ diff --git a/SQL Scripts/SQLI-WIN-003.sql b/SQL Scripts/SQLI-WIN-003.sql new file mode 100644 index 0000000..8faad69 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-003.sql @@ -0,0 +1,45 @@ +/* + SQLI-WIN-003 – Serveren pager hukommelse til disk + ================================================== + + Hvad og hvorfor + Windows læser og skriver hukommelsessider til sidefilen, fordi der ikke er plads i RAM. Det er mange gange + langsommere end hukommelse og belaster disken, som andre også bruger. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Memory:PagesPerSecond standard 1000 (Memory\Pages/sec, gennemsnit over 15 minutter) + Kun sammen med lidt ledig hukommelse (under 10 % i samme periode): Pages/sec alene er også fil-I/O gennem + memory-mapped filer og er ikke i sig selv et problem. + + Alvor + Middel. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + Performance Monitor Users + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetPerformanceAsync (CimQueries.MemoryQuery), hvert minut + fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync. + Beregning: src/SQLInsight.Core/Servers/ServerPerformance.cs – ServerPerformanceMath.PagesPerSecond. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerPagingRule + + Evaluering + Pages/sec er en PERF_COUNTER_COUNTER: (Δ PagesPersec) / (Δ Timestamp_PerfTime / Frequency_PerfTime) mellem to + læsninger. Er gennemsnittet over 15 minutter mindst grænsen, og den ledige andel samtidig under 10 %, er det et fund. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT AvailableMBytes, PagesPersec, CommittedBytes, CommitLimit, Timestamp_PerfTime, Frequency_PerfTime FROM Win32_PerfRawData_PerfOS_Memory + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + $q = "SELECT PagesPersec, Timestamp_PerfTime, Frequency_PerfTime FROM Win32_PerfRawData_PerfOS_Memory" + $a = Get-CimInstance -CimSession $s -Query $q; Start-Sleep -Seconds 60; $b = Get-CimInstance -CimSession $s -Query $q + ($b.PagesPersec - $a.PagesPersec) / (($b.Timestamp_PerfTime - $a.Timestamp_PerfTime) / $b.Frequency_PerfTime) +*/ diff --git a/SQL Scripts/SQLI-WIN-004.sql b/SQL Scripts/SQLI-WIN-004.sql new file mode 100644 index 0000000..7d383be --- /dev/null +++ b/SQL Scripts/SQLI-WIN-004.sql @@ -0,0 +1,40 @@ +/* + SQLI-WIN-004 – Den reserverede hukommelse (commit) er tæt på grænsen + ===================================================================== + + Hvad og hvorfor + Commit charge er den hukommelse, programmerne har reserveret (RAM plus sidefil). Når grænsen nås, kan Windows ikke + give mere hukommelse ud, og programmer og tjenester fejler, selv om der måske er ledig RAM. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Memory:CommitPercent standard 90 (CommittedBytes / CommitLimit, gennemsnit over 5 minutter) + + Alvor + Middel; Høj ved 97 % eller derover. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + Performance Monitor Users + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetPerformanceAsync (CimQueries.MemoryQuery), hvert minut + fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerCommitRule + + Evaluering + 100 × CommittedBytes / CommitLimit pr. minut; gennemsnittet over 5 minutter (mindst 80 % dækket) mod grænsen. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT AvailableMBytes, PagesPersec, CommittedBytes, CommitLimit, Timestamp_PerfTime, Frequency_PerfTime FROM Win32_PerfRawData_PerfOS_Memory + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + $m = Get-CimInstance -CimSession $s -Query "SELECT CommittedBytes, CommitLimit FROM Win32_PerfRawData_PerfOS_Memory" + 100 * $m.CommittedBytes / $m.CommitLimit +*/ diff --git a/SQL Scripts/SQLI-WIN-005.sql b/SQL Scripts/SQLI-WIN-005.sql new file mode 100644 index 0000000..7747373 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-005.sql @@ -0,0 +1,48 @@ +/* + SQLI-WIN-005 – Lidt ledig plads på et drev + =========================================== + + Hvad og hvorfor + Når et drev løber fuldt, stopper alt, der skriver til det: SQL Server kan ikke vokse data- og logfiler, backup + fejler, AOS og Windows kan ikke skrive logfiler og midlertidige filer, og brugere kan ikke gemme. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Disks:FreePercent standard 10 (ledig andel, under: Middel) + SQLInsight:Servers:Disks:CriticalFreePercent standard 5 (under: Høj) + SQLInsight:Servers:Disks:EnoughFreeGigabytes standard 50 (er der mindst så mange GB ledige, er der intet fund, + uanset andelen: store drev med lille andel ledig kan være fine) + + Alvor + Middel under FreePercent, Høj under CriticalFreePercent, Kritisk under 1 GB eller 1 %. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetDisksAsync (CimQueries.VolumeQuery, ellers + CimQueries.LogicalDiskQuery), hvert 15. minut (SQLInsight:Servers:Intervals:disks) fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectDisksAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – DiskFreeSpaceRule + + Evaluering + Lokale diske (DriveType 3) med drevbogstav eller monteringssti; partitioner uden (system/recovery, navn \\?\Volume{…}) + springes over. Ledig andel = FreeSpace / Capacity. Et fund pr. drev, der er under FreePercent og samtidig har + mindre end EnoughFreeGigabytes ledig. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT Name, Label, FileSystem, Capacity, FreeSpace FROM Win32_Volume WHERE DriveType = 3 + SELECT DeviceID, VolumeName, FileSystem, Size, FreeSpace FROM Win32_LogicalDisk WHERE DriveType = 3 (fallback) + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + Get-CimInstance -CimSession $s -Query "SELECT Name, Label, FileSystem, Capacity, FreeSpace FROM Win32_Volume WHERE DriveType = 3" | + Where-Object { $_.Name -notlike '\\?\*' } | + Select-Object Name, Label, @{n='LedigGB';e={[math]::Round($_.FreeSpace / 1GB, 1)}}, @{n='Ledig%';e={[math]::Round(100 * $_.FreeSpace / $_.Capacity, 1)}} +*/ diff --git a/SQL Scripts/SQLI-WIN-006.sql b/SQL Scripts/SQLI-WIN-006.sql new file mode 100644 index 0000000..90d16e8 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-006.sql @@ -0,0 +1,55 @@ +/* + SQLI-WIN-006 – Et drev bliver fuldt om få dage + =============================================== + + Hvad og hvorfor + Varsler, at disken løber fuld om et antal dage, før det sker: pladsen på drevet er de seneste uger brugt i et jævnt + tempo, og fortsætter det, er drevet fuldt inden for prognosegrænsen. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Disks:ForecastDays standard 30 (fund når drevet forventes fuldt inden for så mange dage) + SQLInsight:Servers:Disks:ForecastHistoryDays standard 14 (dage med SQLInsights egne målinger, linjen beregnes over) + SQLInsight:Servers:DiskHistoryDays standard 35 (hvor længe målingerne gemmes i insight.ServerDiskSamples) + Faste fornuftsgrænser (src/SQLInsight.Core/Servers/DiskForecast.cs – DiskForecastSettings): mindst 2 dages historik og + 12 målinger, R² mindst 0,5, vækst mindst 0,01 GB pr. dag, højst 365 dage frem. + + Alvor + Middel; Høj inden for 7 dage; Kritisk inden for 2 dage. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetDisksAsync (CimQueries.VolumeQuery), hvert 15. minut fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectDisksAsync, som gemmer målingen og beregner prognosen. + Prognose: src/SQLInsight.Core/Servers/DiskForecast.cs – DiskForecaster.Forecast. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – DiskForecastRule + + Evaluering + Ledig plads pr. drev hver 15. minut gemmes i repositoriet. Prognosen tager timegennemsnit af de seneste + ForecastHistoryDays dage – kun siden drevet sidst skiftede størrelse (et udvidet drev starter en ny tendens) – og + lægger en ret linje (mindste kvadraters metode) gennem den ledige plads. Hælder linjen nedad, passer den rimeligt + (R²), og er der nok historik, er "fuld om ca. N dage" = ledig plads nu / forbrug pr. dag. Svinger pladsen op og ned + (backup skrevet og slettet), er der ingen prognose frem for et skræmmende gæt. + + Reglen bruger ikke SQL mod den overvågede server. Forespørgslen mod Windows står herunder, og den forespørgsel, agenten + bruger mod sit eget repository (ikke den overvågede server), står til sidst. Filen indeholder kun kommentarer. + + CIM/WQL (namespace root\cimv2): + SELECT Name, Label, FileSystem, Capacity, FreeSpace FROM Win32_Volume WHERE DriveType = 3 + + Historikken i SQLInsight-repositoriet (src/SQLInsight.Repository/InsightRepository.WindowsServers.cs – GetServerDiskHistoryAsync): + SELECT Volume, DATEADD(hour, DATEDIFF(hour, 0, SampledAt), 0) AS [Hour], MAX(SizeGb), AVG(FreeGb) + FROM insight.ServerDiskSamples WHERE ServerId = @id AND SampledAt >= @from + GROUP BY Volume, DATEADD(hour, DATEDIFF(hour, 0, SampledAt), 0) + ORDER BY Volume, [Hour]; + + Efterprøv med PowerShell (skrivebeskyttet; ledig plads nu): + Get-CimInstance -ComputerName SERVER -Query "SELECT Name, Capacity, FreeSpace FROM Win32_Volume WHERE DriveType = 3" | + Select-Object Name, @{n='LedigGB';e={[math]::Round($_.FreeSpace / 1GB, 1)}} +*/ diff --git a/SQL Scripts/SQLI-WIN-007.sql b/SQL Scripts/SQLI-WIN-007.sql new file mode 100644 index 0000000..a0a73c5 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-007.sql @@ -0,0 +1,50 @@ +/* + SQLI-WIN-007 – En tjeneste, der skal starte automatisk, kører ikke + =================================================================== + + Hvad og hvorfor + En tjeneste med starttypen Automatisk står ikke som kørende. Det, tjenesten gør, sker ikke, og en automatisk + tjeneste, der er stoppet, er oftest gået ned. SQLInsight starter aldrig selv tjenester. + + Tærskler (agentens appsettings.json og serverens indstillinger i SQLInsight Web) + SQLInsight:Servers:Services:Ignore ekstra tjenester, der må være stoppet (navn eller præfiks*) + SQLInsight:Servers:Services:StartupGraceMinutes standard 15 (ingen fund de første minutter efter en genstart) + Indbygget liste over automatiske tjenester, der stopper af sig selv (StoppedAutomaticServiceRule.StopByDesign), + fx sppsvc, gupdate, edgeupdate, MapsBroker, RemoteRegistry, clr_optimization_*, CDPUserSvc_*. + Pr. server: "Tjenester der ignoreres" (insight.WindowsServers.IgnoredServices). Overvågede tjenester (SQLI-WIN-008) + rapporteres dér og ikke her. + + Alvor + Middel. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 + læseret (CC LC RP RC) på Service Control Manager + (over netværket må ellers kun administratorer liste tjenester). + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere (DelayedAutoStart læses fra Windows Server 2012; før det uden). + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetServicesAsync (CimQueries.ServiceQuery, ellers + CimQueries.ServiceQueryWithoutDelayed), hvert 5. minut (SQLInsight:Servers:Intervals:services) fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectServicesAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – StoppedAutomaticServiceRule + + Evaluering + Et fund pr. tjeneste med StartMode = 'Auto' og State <> 'Running', som hverken står på den indbyggede liste, i + Ignore, i serverens ignoreringsliste eller i serverens liste over overvågede tjenester. Ingen fund inden for + StartupGraceMinutes efter LastBootUpTime. Viser serveren slet ingen tjenester, er området "ikke målbar" + (manglende læseret på Service Control Manager). + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT Name, DisplayName, State, StartMode, DelayedAutoStart, ExitCode FROM Win32_Service + SELECT Name, DisplayName, State, StartMode, ExitCode FROM Win32_Service (før Windows Server 2012) + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + Get-CimInstance -ComputerName SERVER -Query "SELECT Name, DisplayName, State, StartMode, DelayedAutoStart, ExitCode FROM Win32_Service" | + Where-Object { $_.StartMode -eq 'Auto' -and $_.State -ne 'Running' } | Select-Object Name, DisplayName, State, ExitCode +*/ diff --git a/SQL Scripts/SQLI-WIN-008.sql b/SQL Scripts/SQLI-WIN-008.sql new file mode 100644 index 0000000..3b1ea3b --- /dev/null +++ b/SQL Scripts/SQLI-WIN-008.sql @@ -0,0 +1,41 @@ +/* + SQLI-WIN-008 – En overvåget tjeneste kører ikke + ================================================ + + Hvad og hvorfor + Tjenester, der er valgt for serveren i SQLInsight Web (fx AOS60$01 for Dynamics AX, W3SVC for IIS, MSSQLSERVER), + skal køre uanset starttype. Når de ikke gør, er det, de leverer, ikke tilgængeligt. SQLInsight starter aldrig selv tjenester. + + Tærskler + Listen pr. server: "Overvågede tjenester" (insight.WindowsServers.WatchedServices), sat i SQLInsight Web eller API v1. + SQLInsight:Servers:Services:StartupGraceMinutes standard 15 (ingen fund de første minutter efter en genstart) + + Alvor + Høj når tjenesten ikke kører; Middel når den ikke findes (eller ikke kan ses). + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 + læseret (CC LC RP RC) på Service Control Manager + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetServicesAsync (CimQueries.ServiceQuery), hvert 5. minut fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectServicesAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – WatchedServiceRule + + Evaluering + For hvert navn på listen findes tjenesten på navn eller visningsnavn. Findes den ikke: fund (Middel). Er State ikke + 'Running': fund (Høj). Uden liste: "ikke relevant". + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT Name, DisplayName, State, StartMode, DelayedAutoStart, ExitCode FROM Win32_Service + SELECT Name, DisplayName, State, StartMode, ExitCode FROM Win32_Service WHERE Name = '' (syntetiske tjek) + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + Get-CimInstance -ComputerName SERVER -Query "SELECT Name, DisplayName, State, StartMode, ExitCode FROM Win32_Service WHERE Name = 'AOS60`$01'" +*/ diff --git a/SQL Scripts/SQLI-WIN-009.sql b/SQL Scripts/SQLI-WIN-009.sql new file mode 100644 index 0000000..35d003f --- /dev/null +++ b/SQL Scripts/SQLI-WIN-009.sql @@ -0,0 +1,54 @@ +/* + SQLI-WIN-009 – Fejl i Windows' hændelseslog + ============================================ + + Hvad og hvorfor + Fejl og kritiske hændelser i System- og Application-loggen: disk- og filsystemfejl, opbrugte ressourcer, tjenester + der stopper eller ikke starter, programmer der går ned, fejl fra Dynamics AX' AOS – og almindelige fejl, der gentager sig. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:EventLog:RepeatThreshold standard 5 (en almindelig fejl skal ses så mange gange på 24 timer) + SQLInsight:Servers:EventLog:Ignore ekstra støj: "Kilde:id", "Kilde" eller "Kilde*" + SQLInsight:Servers:EventLog:MaxFindings standard 15 (højst så mange fund pr. server, vigtigste først) + SQLInsight:Servers:EventLog:MaxEventsPerCollection standard 2000 (hændelser pr. log pr. indsamling) + Indbygget støjliste (ServerEventAnalysis.DefaultIgnore): DCOM 10016/10010, Schannel 36874/36887/36888, TPM-WMI 1796/1801, + WMI 10, Security-SPP 8198, og SQL Server's egne kilder (MSSQLSERVER, MSSQL$*, SQLSERVERAGENT, SQLAgent$*, + SQLISPackage*), som SQL Server-fejlloggen allerede dækker. Et fund holdes åbent 24 timer efter hændelsen sidst blev set. + + Alvor + Høj: disk/filsystem, ressourcer, niveau Kritisk, tjeneste stoppet 3+ gange. Middel: tjeneste stoppet, program gik ned, + Dynamics AX. Lav: almindelige fejl der gentager sig. (Uventet nedlukning: se SQLI-WIN-010.) + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + Event Log Readers (System- og Application-loggen; aldrig Security-loggen). + Over RPC (MS-EVEN6): firewallreglerne "Remote Event Log Management". Fallback over CIM: WMI Remote Enable på root\cimv2. + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetEventsAsync: EventLogReader med CimQueries.EventXPath, + ellers CimQueries.EventQuery; hvert 5. minut (SQLInsight:Servers:Intervals:events) fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectEventsAsync. Gruppering og støjfilter: + src/SQLInsight.Core/Servers/ServerEvents.cs – ServerEventAnalysis.Group/Recent/Categorize. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – WindowsEventLogRule + + Evaluering + Hændelser med niveau 1 (kritisk) og 2 (fejl) siden sidste indsamling læses fra System og Application. Støj tælles, + men grupperes ikke. Resten grupperes pr. log, kilde og hændelses-id med antal, første og seneste tidspunkt og den + nyeste tekst som eksempel (følsom: vises kun lokalt, [udeladt] i API'et). Grupperne fra de seneste 24 timer lægges + sammen. Vigtige kategorier giver fund med det samme, almindelige fejl først ved RepeatThreshold gentagelser. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + Event Log (MS-EVEN6), XPath pr. log ('System' og 'Application'): + *[System[(Level=1 or Level=2) and TimeCreated[@SystemTime>'2026-10-02T12:00:00.000Z']]] + CIM/WQL fallback (namespace root\cimv2; EventType 1 = fejl, kritiske hændelser rapporteres som fejl): + SELECT Logfile, SourceName, EventCode, EventType, TimeGenerated, RecordNumber, Message FROM Win32_NTLogEvent + WHERE Logfile = 'System' AND EventType = 1 AND TimeGenerated > '20261002120000.000000+000' + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + Get-WinEvent -ComputerName SERVER -LogName System -FilterXPath "*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) <= 86400000]]]" | + Group-Object ProviderName, Id | Sort-Object Count -Descending | Select-Object Count, Name +*/ diff --git a/SQL Scripts/SQLI-WIN-010.sql b/SQL Scripts/SQLI-WIN-010.sql new file mode 100644 index 0000000..61b8c1d --- /dev/null +++ b/SQL Scripts/SQLI-WIN-010.sql @@ -0,0 +1,42 @@ +/* + SQLI-WIN-010 – Serveren er genstartet + ====================================== + + Hvad og hvorfor + Serveren er genstartet det seneste døgn. Uventet (strøm, blå skærm, hård nulstilling) afbryder alt midt i det, og + databaser og AX skal gendanne sig selv; en planlagt genstart (fx Windows-opdateringer) er kun til orientering. + + Tærskler + Fast: 24 timer efter LastBootUpTime (ServerEventAnalysis.RecentWindow), derefter forsvinder fundet af sig selv. + + Alvor + Høj ved uventet genstart; Info ved genstart uden tegn på at den var uventet. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 (starttidspunkt); Event Log Readers (hvorfor). + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetOperatingSystemAsync (CimQueries.OperatingSystemQuery) og + Session.GetEventsAsync, fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync og CollectEventsAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerRestartRule + + Evaluering + Er LastBootUpTime inden for 24 timer, er serveren genstartet. Er der i hændelsesloggen (seneste 24 timer) en hændelse i + kategorien "uventet nedlukning" – Microsoft-Windows-Kernel-Power 41, EventLog 6008, BugCheck/WER-SystemErrorReporting 1001 – + senest set tidligst en time før starttidspunktet, er genstarten uventet (Høj), ellers Info. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT Caption, Version, BuildNumber, LastBootUpTime, TotalVisibleMemorySize, CSName FROM Win32_OperatingSystem + Event Log (MS-EVEN6), XPath for System: + *[System[(Level=1 or Level=2) and TimeCreated[@SystemTime>'2026-10-02T12:00:00.000Z']]] + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + (Get-CimInstance -ComputerName SERVER -Query "SELECT LastBootUpTime FROM Win32_OperatingSystem").LastBootUpTime + Get-WinEvent -ComputerName SERVER -FilterHashtable @{ LogName = 'System'; Id = 41, 6008, 1001, 1074; StartTime = (Get-Date).AddDays(-1) } +*/ diff --git a/SQL Scripts/SQLI-WIN-011.sql b/SQL Scripts/SQLI-WIN-011.sql new file mode 100644 index 0000000..ff52f32 --- /dev/null +++ b/SQL Scripts/SQLI-WIN-011.sql @@ -0,0 +1,39 @@ +/* + SQLI-WIN-011 – Serveren er ikke genstartet i lang tid + ====================================================== + + Hvad og hvorfor + De fleste Windows-opdateringer kræver en genstart. En server, der ikke er genstartet i flere måneder, mangler derfor + næsten sikkert sikkerhedsopdateringer. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:UptimeDays standard 0 = slået fra (fx 120 for et fund efter 120 dage uden genstart) + + Alvor + Lav. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\cimv2 + WS-Man: Remote Management Users · DCOM: Distributed COM Users + + Understøttede versioner + Windows Server 2008 R2 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetOperatingSystemAsync (CimQueries.OperatingSystemQuery), + fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectPerformanceAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – ServerUptimeRule + + Evaluering + Oppetid = nu − LastBootUpTime. Er UptimeDays større end 0, og oppetiden mindst så mange dage, er det et fund. + Med UptimeDays = 0 er reglen "ikke relevant". + + Reglen bruger ikke SQL. Forespørgslen mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\cimv2): + SELECT Caption, Version, BuildNumber, LastBootUpTime, TotalVisibleMemorySize, CSName FROM Win32_OperatingSystem + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + (Get-Date) - (Get-CimInstance -ComputerName SERVER -Query "SELECT LastBootUpTime FROM Win32_OperatingSystem").LastBootUpTime +*/ diff --git a/SQL Scripts/SQLI-WIN-012.sql b/SQL Scripts/SQLI-WIN-012.sql new file mode 100644 index 0000000..56cd68f --- /dev/null +++ b/SQL Scripts/SQLI-WIN-012.sql @@ -0,0 +1,50 @@ +/* + SQLI-WIN-012 – En planlagt opgave fejlede sidste gang, den kørte + ================================================================= + + Hvad og hvorfor + En opgave i Opgavestyring (Task Scheduler) sluttede med en fejlkode. Planlagte opgaver er ofte oprydning, eksport, + integrationer eller filbackup: når de fejler, opdager ingen det, før noget mangler. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Tasks:IncludeMicrosoftTasks standard false (Microsofts egne opgaver under \Microsoft\ overvåges ikke) + SQLInsight:Servers:Tasks:Ignore opgaver der aldrig overvåges (sti\navn eller præfiks*) + SQLInsight:Servers:Tasks:MaxWatched standard 50 (højst så mange opgaver pr. server) + Resultater, der ikke er fejl: 0x0, 0x41300 (klar), 0x41301 (kører), 0x41302 (deaktiveret), 0x41303 (har ikke kørt), + 0x41304 (ingen flere kørsler), 0x41325 (i kø), 0x8004131F (kørte allerede) – src/SQLInsight.Core/Servers/ServerTasks.cs. + + Alvor + Middel. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\Microsoft\Windows\TaskScheduler. Agenten ser kun opgaver, hvis egne + sikkerhedsindstillinger tillader kontoen at læse dem. Seneste resultat læses med Task Schedulers GetInfo (et + skrivebeskyttet CIM-metodekald, som Get-ScheduledTaskInfo); over WinRM kræver metodekald, at kontoen også har + Execute-ret i WinRM – ellers bruges DCOM. + + Understøttede versioner + Windows Server 2012 og nyere (navnerummet TaskScheduler findes ikke på 2008 R2: "ikke målbar"). + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetTasksAsync (CimQueries.TaskQuery og + PS_ScheduledTask.GetInfoByName), hvert 15. minut (SQLInsight:Servers:Intervals:tasks) fra + src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectTasksAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – FailedScheduledTaskRule + + Evaluering + Et fund pr. aktiveret, overvåget opgave, hvis LastTaskResult er en fejl. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\Microsoft\Windows\TaskScheduler): + SELECT TaskName, TaskPath, State FROM MSFT_ScheduledTask + CIM-metode (skrivebeskyttet) pr. overvåget opgave: + PS_ScheduledTask.GetInfoByName(TaskName, TaskPath) -> cmdletOutput: MSFT_TaskDynamicInfo + (LastRunTime, LastTaskResult, NextRunTime, NumberOfMissedRuns) + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + Get-ScheduledTask -CimSession $s | Where-Object TaskPath -notlike '\Microsoft\*' | Get-ScheduledTaskInfo -CimSession $s | + Select-Object TaskPath, TaskName, LastRunTime, @{n='Resultat';e={'0x{0:X}' -f $_.LastTaskResult}}, NextRunTime, NumberOfMissedRuns +*/ diff --git a/SQL Scripts/SQLI-WIN-013.sql b/SQL Scripts/SQLI-WIN-013.sql new file mode 100644 index 0000000..a213b4a --- /dev/null +++ b/SQL Scripts/SQLI-WIN-013.sql @@ -0,0 +1,44 @@ +/* + SQLI-WIN-013 – En planlagt opgave kørte ikke, da den skulle + ============================================================ + + Hvad og hvorfor + Opgaven skulle have kørt, men gjorde det ikke: Opgavestyring kørte ikke, betingelserne var ikke opfyldt (fx "kun når + brugeren er logget på"), eller serveren var slukket. Det, opgaven gør, er ikke sket. + + Tærskler (agentens appsettings.json) + SQLInsight:Servers:Tasks:LateMinutes standard 60 (næste kørsel mere end så mange minutter i fortiden) + SQLInsight:Servers:Tasks:IncludeMicrosoftTasks standard false + SQLInsight:Servers:Tasks:Ignore opgaver der aldrig overvåges + + Alvor + Middel. + + Rettigheder på den overvågede server (db/permissions/grant-windows-server.ps1, aldrig lokal administrator) + WMI Enable Account/Remote Enable på root\Microsoft\Windows\TaskScheduler (se SQLI-WIN-012 om GetInfo over WinRM). + + Understøttede versioner + Windows Server 2012 og nyere. + + Collector + src/SQLInsight.Servers/CimWindowsServerSource.cs – Session.GetTasksAsync (CimQueries.TaskQuery og + PS_ScheduledTask.GetInfoByName), hvert 15. minut fra src/SQLInsight.Agent/Servers/ServerMonitor.cs – CollectTasksAsync. + Regel + src/SQLInsight.Rules/Servers/WindowsServerRules.cs – MissedScheduledTaskRule + + Evaluering + Et fund pr. aktiveret, overvåget opgave, der ikke kører nu, og hvor enten NumberOfMissedRuns > 0, eller NextRunTime + ligger mere end LateMinutes i fortiden, uden at LastRunTime er efter det tidspunkt. + + Reglen bruger ikke SQL. Forespørgslerne mod Windows står herunder; filen indeholder kun kommentarer og ændrer intet. + + CIM/WQL (namespace root\Microsoft\Windows\TaskScheduler): + SELECT TaskName, TaskPath, State FROM MSFT_ScheduledTask + CIM-metode (skrivebeskyttet) pr. overvåget opgave: + PS_ScheduledTask.GetInfoByName(TaskName, TaskPath) -> cmdletOutput: MSFT_TaskDynamicInfo + + Efterprøv med PowerShell (skrivebeskyttet; kør på agentens server som agentens konto): + $s = New-CimSession -ComputerName SERVER + Get-ScheduledTask -CimSession $s | Where-Object { $_.TaskPath -notlike '\Microsoft\*' -and $_.State -ne 'Disabled' } | + Get-ScheduledTaskInfo -CimSession $s | Where-Object { $_.NumberOfMissedRuns -gt 0 -or ($_.NextRunTime -and $_.NextRunTime -lt (Get-Date).AddMinutes(-60)) } +*/ diff --git a/tests/SQLInsight.Rules.Tests/ServerRuleScriptTests.cs b/tests/SQLInsight.Rules.Tests/ServerRuleScriptTests.cs new file mode 100644 index 0000000..776fa40 --- /dev/null +++ b/tests/SQLInsight.Rules.Tests/ServerRuleScriptTests.cs @@ -0,0 +1,37 @@ +using SQLInsight.Rules.Servers; + +namespace SQLInsight.Rules.Tests; + +/// Every Windows server and synthetic check rule has its reviewable script in SQL Scripts/ (named by its id). +public class ServerRuleScriptTests +{ + private static DirectoryInfo Scripts() + { + for (var directory = new DirectoryInfo(AppContext.BaseDirectory); directory is not null; directory = directory.Parent) + { + var candidate = new DirectoryInfo(Path.Combine(directory.FullName, "SQL Scripts")); + if (candidate.Exists) + { + return candidate; + } + } + + throw new DirectoryNotFoundException("SQL Scripts/ blev ikke fundet over testens mappe."); + } + + [Fact] + public void Every_server_and_check_rule_has_a_script_with_its_id_and_title() + { + var folder = Scripts(); + + Assert.All(ServerRuleCatalog.All, rule => + { + var file = Path.Combine(folder.FullName, rule.Id + ".sql"); + Assert.True(File.Exists(file), $"{rule.Id}.sql mangler i SQL Scripts/."); + var text = File.ReadAllText(file); + Assert.Contains($"{rule.Id} – {rule.Title}", text, StringComparison.Ordinal); + Assert.Contains("Evaluering", text, StringComparison.Ordinal); + Assert.DoesNotContain("sysadmin", text, StringComparison.OrdinalIgnoreCase); + }); + } +}