A five-minute collector reads important error log entries from the best
source the agent's rights allow: the error log itself (xp_readerrorlog,
only with securityadmin), the default trace's ErrorLog and Audit Login
Failed events (optional ALTER TRACE), or the exception and connectivity
ring buffers (VIEW SERVER STATE: numbers and severity, failed logins).
Repetitions are summed per error; the watermark is the newest entry
read, because the default trace is buffered. Stored in
insight.ErrorLogEvents (migration 0013, EventDays), resumed after restart.
Rules SQLI-LOG-001..006: corruption 823/824/825, I/O over 15 s (833),
severe errors (17+), login failure bursts (configurable), stack dumps and
AG errors; rules needing the log text are "not measurable" with the
right to grant. Page /instanser/{navn}/fejllog (menu Overvågning) and
GET /api/v1/instances/{name}/error-log with messages redacted.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
119 lines
5.3 KiB
Transact-SQL
119 lines
5.3 KiB
Transact-SQL
/*
|
|
SQLInsight Pro: least-privilege rettigheder til agentens login
|
|
================================================================
|
|
|
|
Giver agenten præcis de rettigheder, den skal bruge for at overvåge instansen. Aldrig sysadmin.
|
|
Scriptet kan køres igen uden skade, fx efter en opgradering eller når der er oprettet nye databaser.
|
|
|
|
Understøtter SQL Server 2005 og nyere. SQL Server 2000 har ikke VIEW SERVER STATE: se docs/legacy-versions.md.
|
|
|
|
Forudsætning: login'et findes allerede, fx
|
|
CREATE LOGIN [DOMÆNE\svc-sqlinsight$] FROM WINDOWS; -- gMSA (anbefalet)
|
|
CREATE LOGIN [sqlinsight-agent] FROM EXTERNAL PROVIDER; -- Azure SQL Managed Instance (Entra ID)
|
|
|
|
Hvad der gives, og hvorfor:
|
|
Server
|
|
2005-2019: VIEW SERVER STATE DMV'er: waits, sessions, plan cache, I/O
|
|
2022+: VIEW SERVER PERFORMANCE STATE samme, mere granulært
|
|
VIEW SERVER SECURITY STATE sikkerheds-DMV'er (fx audit, certifikater)
|
|
Alle: VIEW ANY DEFINITION metadata (indexes, statistikker). Giver IKKE adgang til data.
|
|
2014+: CONNECT ANY DATABASE kan åbne alle databaser (nuværende og fremtidige). Giver IKKE adgang til data.
|
|
Databaser (kun før 2014): en bruger uden rettigheder i hver online database, så DMV'er og Query Store kan læses.
|
|
msdb: SELECT på backup-, restore-, job- og suspect_pages-tabeller. Intet andet.
|
|
|
|
Hvad der IKKE gives: adgang til tabeldata, skriverettigheder, xp_cmdshell eller sysadmin.
|
|
*/
|
|
SET NOCOUNT ON;
|
|
|
|
DECLARE @LoginName sysname;
|
|
SET @LoginName = N'DOMÆNE\svc-sqlinsight$'; -- <== ret til agentens login
|
|
|
|
DECLARE @Major int;
|
|
DECLARE @Sql nvarchar(max);
|
|
DECLARE @Quoted nvarchar(300);
|
|
SET @Major = CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)), 4) AS int);
|
|
/* Azure SQL Managed Instance reports 12.x but runs the newest engine. Use the broad, universally supported permissions. */
|
|
IF CAST(SERVERPROPERTY('EngineEdition') AS int) = 8 SET @Major = 15;
|
|
SET @Quoted = QUOTENAME(@LoginName);
|
|
|
|
IF @Major < 9
|
|
BEGIN
|
|
RAISERROR(N'SQL Server 2000 understøttes ikke af dette script. Se docs/legacy-versions.md.', 16, 1);
|
|
RETURN;
|
|
END;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = @LoginName)
|
|
BEGIN
|
|
RAISERROR(N'Login %s findes ikke. Opret det først.', 16, 1, @LoginName);
|
|
RETURN;
|
|
END;
|
|
|
|
IF IS_SRVROLEMEMBER(N'sysadmin', @LoginName) = 1
|
|
PRINT N'ADVARSEL: ' + @LoginName + N' er sysadmin. Agenten har ikke brug for det; fjern rollen.';
|
|
|
|
/* Server-rettigheder */
|
|
IF @Major >= 16
|
|
SET @Sql = N'GRANT VIEW SERVER PERFORMANCE STATE TO ' + @Quoted + N'; GRANT VIEW SERVER SECURITY STATE TO ' + @Quoted + N';';
|
|
ELSE
|
|
SET @Sql = N'GRANT VIEW SERVER STATE TO ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
|
|
SET @Sql = N'GRANT VIEW ANY DEFINITION TO ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
|
|
IF @Major >= 12
|
|
BEGIN
|
|
SET @Sql = N'GRANT CONNECT ANY DATABASE TO ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
/* Før 2014: en bruger uden rettigheder i hver online database. Kør scriptet igen, når der oprettes nye. */
|
|
DECLARE @Db sysname;
|
|
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
|
|
SELECT name FROM sys.databases
|
|
WHERE state = 0 AND name NOT IN (N'master', N'tempdb', N'model', N'msdb') AND is_read_only = 0;
|
|
OPEN db_cursor;
|
|
FETCH NEXT FROM db_cursor INTO @Db;
|
|
WHILE @@FETCH_STATUS = 0
|
|
BEGIN
|
|
SET @Sql = N'USE ' + QUOTENAME(@Db) + N';
|
|
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE sid = SUSER_SID(' + QUOTENAME(@LoginName, '''') + N'))
|
|
CREATE USER ' + @Quoted + N' FOR LOGIN ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
FETCH NEXT FROM db_cursor INTO @Db;
|
|
END;
|
|
CLOSE db_cursor;
|
|
DEALLOCATE db_cursor;
|
|
END;
|
|
|
|
/* msdb: backup-historik, jobs og suspect pages */
|
|
SET @Sql = N'USE msdb;
|
|
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE sid = SUSER_SID(' + QUOTENAME(@LoginName, '''') + N'))
|
|
CREATE USER ' + @Quoted + N' FOR LOGIN ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.backupset TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.backupmediafamily TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.backupmediaset TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.restorehistory TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.suspect_pages TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysjobs TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysjobsteps TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysjobhistory TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysjobactivity TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysjobschedules TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.sysschedules TO ' + @Quoted + N';
|
|
GRANT SELECT ON dbo.syscategories TO ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
|
|
/*
|
|
Valgfrit: hvem og hvornår ved ændringer af serverroller.
|
|
Rettighedsrevisionen (sysadmin m.m.) og fejlloggen virker uden. Med ALTER TRACE kan agenten desuden læse default trace og vise
|
|
fejltekster og mislykkede logins fra fejlloggen (docs/fejllog.md), og
|
|
HVEM der gav en ny rettighed og HVORNÅR. ALTER TRACE giver også adgang til at oprette traces, så det er et bevidst
|
|
valg; fjern kommentaren for at give den:
|
|
|
|
SET @Sql = N'GRANT ALTER TRACE TO ' + @Quoted + N';';
|
|
EXEC (@Sql);
|
|
*/
|
|
|
|
PRINT N'Rettigheder givet til ' + @LoginName + N'.';
|