sqlinsight-pro/tests/SQLInsight.IntegrationTests/SyntheticSqlCheckTests.cs
Søren Eggert Lundsteen Olsen 7082b278e3 Collection: Windows servers over CIM (WS-Man, DCOM fallback) and synthetic check runners
New project SQLInsight.Servers:
- CimWindowsServerSource (Microsoft.Management.Infrastructure, the API behind
  Get-CimInstance): WS-Man first, DCOM if that fails, a local session for the
  agent's own computer, as the agent's identity. Only SELECT queries (CimQueries)
  and Task Scheduler's read-only GetInfo. CPU and paging from raw counters, disks
  (Win32_Volume, Win32_LogicalDisk fallback), services, scheduled tasks, and the
  System/Application logs through the Event Log service (MS-EVEN6, XPath filter on
  the server) with Win32_NTLogEvent as fallback.
- ServerErrors: access denied, missing namespace, RPC/WinRM unreachable and
  timeouts become "ikke målbar" reasons that name the missing right and the grant
  script; never local administrator.
- WindowsServerTester: tries every area once for the web UI's test.
- SyntheticCheckRunner: TCP, HTTP(S) with expected status/text and TLS certificate
  expiry (also for refused certificates), SQL login + read-only query (re-validated,
  in a transaction that is always rolled back), DNS, and the Dynamics AX logon:
  AOS port, then a logon through the .NET Business Connector in a separate Windows
  PowerShell process with a timeout when it is installed; otherwise the result
  says clearly that only the port was tested.

Tests: error mapping, queries, AX command/parsing, runners against local TCP and
HTTP(S) servers with a self-signed certificate, the CIM source against this
computer, and the SQL check against the test instance.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 14:58:18 +02:00

51 lines
2.8 KiB
C#

using SQLInsight.Connectivity;
using SQLInsight.Core.SyntheticChecks;
using SQLInsight.Servers.Synthetic;
namespace SQLInsight.IntegrationTests;
/// <summary>The SQL login + query check against a real instance, with the least-privilege agent login.</summary>
[Collection(SqlServerTestGroup.Name)]
[Trait("Category", "Integration")]
public class SyntheticSqlCheckTests(SqlServerFixture sql)
{
private sealed class NoBusinessConnector : IBusinessConnectorLocator
{
public BusinessConnectorInstallation? Find() => null;
}
private static SyntheticCheckRunner Runner() => new(new SqlConnectionFactory(), new NoBusinessConnector(), new ProcessRunner(), TimeProvider.System);
private SyntheticCheckSettings Settings(string? query = null, string? database = null) => new()
{
Server = sql.Server, Authentication = "SqlLogin", UserName = SqlServerFixture.AgentLogin, TrustServerCertificate = true, Query = query, Database = database,
};
[Fact]
public async Task Login_and_query_with_response_time()
{
var result = await Runner().RunAsync(new SyntheticCheckRun(SyntheticCheckKind.Sql, Settings(), TimeSpan.FromSeconds(30), SqlServerFixture.AgentPassword), CancellationToken.None);
var inDatabase = await Runner().RunAsync(new SyntheticCheckRun(SyntheticCheckKind.Sql,
Settings("SELECT name FROM sys.objects", SqlServerFixture.TestDatabase), TimeSpan.FromSeconds(30), SqlServerFixture.AgentPassword), CancellationToken.None);
Assert.True(result.Success, result.Message);
Assert.Contains("Login og forespørgsel lykkedes", result.Message, StringComparison.Ordinal);
Assert.Contains(result.Details, d => d.Name == "Rækker" && d.Value == "1");
Assert.True(inDatabase.Success, inDatabase.Message);
}
[Fact]
public async Task A_wrong_password_and_a_query_without_rights_fail_with_the_reason()
{
var login = await Runner().RunAsync(new SyntheticCheckRun(SyntheticCheckKind.Sql, Settings(), TimeSpan.FromSeconds(30), "forkert"), CancellationToken.None);
var denied = await Runner().RunAsync(new SyntheticCheckRun(SyntheticCheckKind.Sql, Settings("SELECT Secret FROM dbo.CustomerData", SqlServerFixture.TestDatabase),
TimeSpan.FromSeconds(30), SqlServerFixture.AgentPassword), CancellationToken.None);
var noPassword = await Runner().RunAsync(new SyntheticCheckRun(SyntheticCheckKind.Sql, Settings(), TimeSpan.FromSeconds(30)), CancellationToken.None);
Assert.False(login.Success);
Assert.StartsWith("Login på SQL Server fejlede", login.Message, StringComparison.Ordinal);
Assert.False(denied.Success); // the least-privilege login can not read customer data
Assert.StartsWith("Forespørgslen fejlede", denied.Message, StringComparison.Ordinal);
Assert.False(noPassword.Success);
}
}