using System.Security.Cryptography; using SQLInsight.Core.Configuration; namespace SQLInsight.Core.Tests; public sealed class DatabaseSelectionTests { [Fact] public void All_monitors_every_database_and_sends_no_dynamics_ax_findings() { Assert.True(DatabaseSelection.All.IsEverything); Assert.True(DatabaseSelection.All.Includes("Sales")); Assert.False(DatabaseSelection.All.SendsDynamicsAxToHub("AX30")); Assert.False(DatabaseSelection.All.AnyDynamicsAxToHub); } [Fact] public void Ticked_databases_are_monitored_unticked_are_not_and_new_ones_follow_the_instance_setting() { var selection = new DatabaseSelection(monitorNew: false, ["AX30"], ["Archive"], []); Assert.True(selection.Includes("ax30")); Assert.False(selection.Includes("Archive")); Assert.False(selection.Includes("NewDb")); Assert.True(new DatabaseSelection(monitorNew: true, ["AX30"], ["Archive"], []).Includes("NewDb")); Assert.Equal(["AX30"], selection.Filter(["AX30", "Archive", "NewDb"])); } [Theory] [InlineData("master")] [InlineData("MSDB")] [InlineData("model")] [InlineData("tempdb")] public void System_databases_are_always_monitored(string database) { Assert.True(new DatabaseSelection(false, [], [database], []).Includes(database)); } [Fact] public void Dynamics_ax_findings_go_to_the_hub_only_for_opted_in_monitored_databases() { var selection = new DatabaseSelection(false, ["AX30", "AX40"], ["AXOLD"], ["AX30", "AXOLD"]); Assert.True(selection.SendsDynamicsAxToHub("AX30")); Assert.False(selection.SendsDynamicsAxToHub("AX40")); Assert.False(selection.SendsDynamicsAxToHub("AXOLD")); // opted in, but not monitored Assert.False(selection.SendsDynamicsAxToHub(null)); Assert.True(selection.AnyDynamicsAxToHub); } [Theory] [InlineData("COM-AX-001", true)] [InlineData("com-ax-012", true)] [InlineData("COM-FT-001", false)] [InlineData("SQLI-DB-001", false)] public void Dynamics_ax_rules_are_recognised_by_their_id(string ruleId, bool expected) => Assert.Equal(expected, DynamicsAxFindings.IsDynamicsAxRule(ruleId)); [Theory] [InlineData("database: AX30", "AX30")] [InlineData("database: ", null)] [InlineData("ag-database: g/r/AX30", null)] [InlineData(null, null)] public void Database_is_read_from_the_subject(string? subject, string? expected) => Assert.Equal(expected, DynamicsAxFindings.DatabaseOf(subject)); } public sealed class CredentialEnvelopeTests { private static (RSA Key, byte[] PublicKey) NewKey() { var rsa = RSA.Create(3072); return (rsa, rsa.ExportSubjectPublicKeyInfo()); } [Fact] public void Sealed_password_opens_only_with_the_agent_key_and_the_same_server_and_login() { var (key, publicKey) = NewKey(); using var _ = key; var context = CredentialEnvelope.Context("sql01\\PROD,1433", "sqlinsight"); var envelope = CredentialEnvelope.Seal("Hemmelig-1!", "agent-1", publicKey, context); Assert.Equal("agent-1", CredentialEnvelope.KeyIdOf(envelope)); Assert.DoesNotContain("Hemmelig", System.Text.Encoding.UTF8.GetString(envelope), StringComparison.Ordinal); Assert.Equal("Hemmelig-1!", CredentialEnvelope.Open(envelope, "agent-1", key, CredentialEnvelope.Context("SQL01\\prod,1433", "SQLINSIGHT"))); Assert.Throws(() => CredentialEnvelope.Open(envelope, "agent-1", key, CredentialEnvelope.Context("evil01", "sqlinsight"))); Assert.Throws(() => CredentialEnvelope.Open(envelope, "agent-1", key, CredentialEnvelope.Context("sql01\\PROD,1433", "sa"))); Assert.Throws(() => CredentialEnvelope.Open(envelope, "agent-2", key, context)); } [Fact] public void Another_agent_key_or_a_tampered_envelope_cannot_be_opened() { var (key, publicKey) = NewKey(); var (other, _) = NewKey(); using var a = key; using var b = other; var context = CredentialEnvelope.Context("sql01", "u"); var envelope = CredentialEnvelope.Seal("pw", "k", publicKey, context); Assert.Throws(() => CredentialEnvelope.Open(envelope, "k", other, context)); envelope[^1] ^= 0xFF; Assert.Throws(() => CredentialEnvelope.Open(envelope, "k", key, context)); Assert.Null(CredentialEnvelope.KeyIdOf([9, 9, 9])); } } public sealed class ServerAddressTests { [Theory] [InlineData("sql01", null, "sql01")] [InlineData(" sql01\\PROD ", null, "sql01\\PROD")] [InlineData("sql01.firma.local\\PROD", 1450, "sql01.firma.local\\PROD,1450")] public void Data_source_adds_the_port(string server, int? port, string expected) => Assert.Equal(expected, ServerAddress.DataSource(server, port)); [Theory] [InlineData("sql01", null, true)] [InlineData("sql01\\PROD", 1433, true)] [InlineData("tcp:sql01.firma.local", null, true)] [InlineData("", null, false)] [InlineData("sql01;Integrated Security=false", null, false)] [InlineData("sql01,1433", null, false)] [InlineData("sql01\\a\\b", null, false)] [InlineData("sql01", 0, false)] [InlineData("sql01", 70000, false)] public void Server_and_port_are_validated(string server, int? port, bool valid) => Assert.Equal(valid, ServerAddress.Validate(server, port) is null); [Theory] [InlineData(@"NT SERVICE\SQLInsight Agent", "sql01", "AGENT01", "FIRMA", @"FIRMA\AGENT01$")] [InlineData(@"NT SERVICE\SQLInsight Agent", "agent01\\PROD", "AGENT01", "FIRMA", @"NT SERVICE\SQLInsight Agent")] [InlineData(@"FIRMA\svc-sqlinsight$", "sql01", "AGENT01", "FIRMA", @"FIRMA\svc-sqlinsight$")] [InlineData("LocalSystem", "sql01", "AGENT01", "FIRMA", @"FIRMA\AGENT01$")] public void Service_account_login_on_the_server(string account, string server, string machine, string domain, string expected) => Assert.Equal(expected, ServiceAccounts.LoginFor(account, server, machine, domain)); } public sealed class GrantScriptTests { [Fact] public void Script_is_filled_in_for_the_login_and_creates_a_missing_windows_login() { var script = GrantScript.For(@"FIRMA\AGENT01$", windowsLogin: true); Assert.Contains(@"SET @LoginName = N'FIRMA\AGENT01$';", script, StringComparison.Ordinal); Assert.DoesNotContain("SET @LoginName = N'DOMÆNE", script, StringComparison.Ordinal); Assert.Contains(@"CREATE LOGIN [FIRMA\AGENT01$] FROM WINDOWS;", script, StringComparison.Ordinal); Assert.Contains("VIEW SERVER STATE", script, StringComparison.Ordinal); Assert.DoesNotContain("PXI_BATCHMONITORTABLE", script, StringComparison.OrdinalIgnoreCase); } [Fact] public void Quotes_in_a_login_are_escaped() { var script = GrantScript.For("o'brien]", windowsLogin: false); Assert.Contains("SET @LoginName = N'o''brien]';", script, StringComparison.Ordinal); Assert.Contains("CREATE LOGIN [o'brien]]]", script, StringComparison.Ordinal); Assert.DoesNotContain("IF SUSER_ID(", script, StringComparison.Ordinal); } }