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>
51 lines
2.8 KiB
C#
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);
|
|
}
|
|
}
|