using Microsoft.Data.SqlClient; namespace SQLInsight.IntegrationTests; /// /// Runs db/permissions/grant-least-privilege.sql and proves that the agent login can read everything it needs, /// and nothing else. /// [Collection(SqlServerTestGroup.Name)] [Trait("Category", "Integration")] public class LeastPrivilegeTests(SqlServerFixture sql) { private const string Database = SqlServerFixture.TestDatabase; [Fact] public async Task Agent_login_is_not_sysadmin() { Assert.Equal(0, await ScalarAsync("SELECT IS_SRVROLEMEMBER('sysadmin')")); } [Theory] [InlineData("SELECT COUNT(*) FROM sys.dm_os_wait_stats")] [InlineData("SELECT COUNT(*) FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t")] [InlineData("SELECT COUNT(*) FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) p")] [InlineData("SELECT COUNT(*) FROM sys.dm_io_virtual_file_stats(NULL, NULL)")] [InlineData("SELECT COUNT(*) FROM sys.dm_os_ring_buffers")] [InlineData("SELECT COUNT(*) FROM sys.dm_xe_sessions WHERE name = 'system_health'")] [InlineData("SELECT COUNT(*) FROM sys.configurations")] [InlineData("SELECT COUNT(*) FROM msdb.dbo.backupset")] [InlineData("SELECT COUNT(*) FROM msdb.dbo.sysjobs")] [InlineData("SELECT COUNT(*) FROM msdb.dbo.sysjobhistory")] [InlineData("SELECT COUNT(*) FROM msdb.dbo.suspect_pages")] [InlineData($"SELECT COUNT(*) FROM [{Database}].sys.database_query_store_options")] [InlineData($"SELECT COUNT(*) FROM [{Database}].sys.query_store_runtime_stats")] [InlineData($"SELECT COUNT(*) FROM [{Database}].sys.indexes WHERE object_id = OBJECT_ID(N'[{Database}].dbo.CustomerData')")] [InlineData($"SELECT COUNT(*) FROM [{Database}].sys.dm_db_index_usage_stats")] [InlineData($"SELECT COUNT(*) WHERE DATABASEPROPERTYEX(N'{Database}', 'LastGoodCheckDbTime') IS NOT NULL")] public async Task Agent_can_read_monitoring_sources(string query) { Assert.True(await ScalarAsync(query) >= 0); } [Fact] public async Task Agent_cannot_read_customer_data() { var ex = await Assert.ThrowsAsync( () => ScalarAsync($"SELECT COUNT(*) FROM [{Database}].dbo.CustomerData")); Assert.Equal(229, ex.Number); // The SELECT permission was denied. } [Fact] public async Task Agent_cannot_change_anything() { var ex = await Assert.ThrowsAsync( () => ScalarAsync($"USE [{Database}]; CREATE TABLE dbo.ShouldNotExist (Id int); SELECT 1")); Assert.Equal(262, ex.Number); // CREATE TABLE permission denied. } [Fact] public async Task Script_is_idempotent() { await sql.ExecuteAsSaAsync(await SqlServerFixture.GrantScriptAsync()); } private async Task ScalarAsync(string query) { await using var connection = new SqlConnection(sql.AgentConnectionString); await connection.OpenAsync(); await using var command = connection.CreateCommand(); command.CommandText = query; return (T)Convert.ChangeType((await command.ExecuteScalarAsync())!, typeof(T), System.Globalization.CultureInfo.InvariantCulture); } }