using SQLInsight.Agent; using SQLInsight.Agent.CustomRules; using SQLInsight.Connectivity; using SQLInsight.Core.CustomRules; using SQLInsight.Rules.Lifecycle; namespace SQLInsight.IntegrationTests; /// Community and local rules run with the agent's least-privilege login against a real SQL Server. [Collection(SqlServerTestGroup.Name)] [Trait("Category", "Integration")] public class CustomRuleIntegrationTests(SqlServerFixture sql) : IAsyncLifetime { private readonly string _database = "SQLInsightFk_" + Guid.NewGuid().ToString("N")[..8]; public Task InitializeAsync() => sql.ExecuteAsSaAsync($""" CREATE DATABASE [{_database}]; EXEC('USE [{_database}]; CREATE TABLE dbo.Kunder (Id int PRIMARY KEY); CREATE TABLE dbo.Ordrer (Id int PRIMARY KEY, KundeId int CONSTRAINT FK_Ordrer_Kunder REFERENCES dbo.Kunder (Id)); ALTER TABLE dbo.Ordrer NOCHECK CONSTRAINT FK_Ordrer_Kunder; ALTER TABLE dbo.Ordrer CHECK CONSTRAINT FK_Ordrer_Kunder;'); """); public Task DisposeAsync() => sql.ExecuteAsSaAsync($"ALTER DATABASE [{_database}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{_database}];"); [Fact] public async Task Community_and_local_rules_run_with_least_privilege() { var local = CustomRuleLoader.Parse(""" [ { "id": "LOCAL-SEC-001", "title": "Databasemail", "severity": "Low", "query": "SELECT name FROM msdb.dbo.sysmail_account", "findingTitle": "{name}", "explanation": "x", "recommendation": "y" }, { "id": "LOCAL-SEC-002", "title": "Stavefejl", "severity": "Low", "query": "SELECT nosuchcolumn FROM sys.databases", "findingTitle": "x", "explanation": "x", "recommendation": "y" } ] """, "local.json", "lokal"); Assert.Empty(local.Errors); var rules = RulePack.Embedded().CommunityRules.Concat(local.Rules).ToList(); var instance = new MonitoredInstance { Name = "itest", Server = sql.Server, Authentication = AuthenticationMode.SqlLogin, UserName = SqlServerFixture.AgentLogin, Password = SqlServerFixture.AgentPassword, Provider = ConnectionProvider.SqlClient, TrustServerCertificate = true, }; using var output = new StringWriter(); var exit = await RuleCommands.TestAsync(rules, instance, new SqlConnectionFactory(), output, CancellationToken.None); var text = output.ToString(); Assert.Contains("COM-SEC-001: Findings", text, StringComparison.Ordinal); Assert.Contains("Det indbyggede login 'sa' er aktivt", text, StringComparison.Ordinal); Assert.Contains($"{_database}: fremmednøglen FK_Ordrer_Kunder på dbo.Ordrer er ikke betroet", text, StringComparison.Ordinal); Assert.Contains("COM-CFG-001: Passed", text, StringComparison.Ordinal); Assert.Contains("LOCAL-SEC-001: NotMeasurable – Agentens login mangler rettigheder", text, StringComparison.Ordinal); Assert.Contains("LOCAL-SEC-002: Error", text, StringComparison.Ordinal); Assert.Equal(2, exit); } }