Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
- .NET 10 solution with Core, Connectivity, Rules, Contracts, Agent, Web and Hub - Capability model gating collectors and rules by SQL Server version (2000 and later); rules that cannot run are reported as not measurable, never as passed - Connectivity via Microsoft.Data.SqlClient with ODBC fallback for legacy instances, hardened monitoring session settings valid back to SQL Server 2000 - Support lifecycle rule (SQLI-VER-001) with lifecycle data shipped as a rule pack - Version-aware least-privilege permissions script, verified by integration tests against SQL Server in Docker (reads monitoring sources, cannot read customer data) - Forgejo Actions CI, contributing guide, code of conduct, issue templates, legacy version notes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
105 lines
4.5 KiB
Transact-SQL
105 lines
4.5 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)
|
|
|
|
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);
|
|
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);
|
|
|
|
PRINT N'Rettigheder givet til ' + @LoginName + N'.';
|