Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
- Evidence can be marked sensitive (query text, logins, hosts, programs, job error messages); rules mark it. Sensitive values and the server name are sent as [udeladt] unless the customer allows them. - Full-state submission contract (all active findings and rule outcomes per instance), idempotent by submission id - Local outbound queue in the repository (migration 0002): newest state per instance only, exponential backoff up to an hour, permanent rejections (bad license, bad request) are given up, sent items purged - Hub status (license state, last sent, last error) for the web UI - Sync runs only with a valid license (or in grace); monitoring never depends on it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
56 lines
2.3 KiB
C#
56 lines
2.3 KiB
C#
using SQLInsight.Contracts;
|
|
using SQLInsight.Core.Instances;
|
|
using SQLInsight.Repository;
|
|
using SQLInsight.Rules.Engine;
|
|
|
|
namespace SQLInsight.Agent.Hub;
|
|
|
|
/// <summary>
|
|
/// Turns an instance's current state into a hub submission, leaving out what the customer has not allowed.
|
|
/// </summary>
|
|
public static class SubmissionBuilder
|
|
{
|
|
public static readonly string AgentVersion =
|
|
typeof(SubmissionBuilder).Assembly.GetName().Version?.ToString() ?? "0.0.0";
|
|
|
|
public static FindingsSubmission Build(
|
|
string instanceName, InstanceInfo info, IReadOnlyList<RuleResult> results, IReadOnlyList<StoredFinding> activeFindings,
|
|
HubOptions options, DateTimeOffset now)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(info);
|
|
ArgumentNullException.ThrowIfNull(results);
|
|
ArgumentNullException.ThrowIfNull(activeFindings);
|
|
ArgumentNullException.ThrowIfNull(options);
|
|
|
|
return new FindingsSubmission
|
|
{
|
|
SubmissionId = Guid.NewGuid(),
|
|
AgentVersion = AgentVersion,
|
|
CollectedAt = now,
|
|
Instance = new InstanceSnapshot
|
|
{
|
|
InstanceKey = instanceName,
|
|
Release = info.Release.DisplayName(),
|
|
ProductVersion = info.Version.ToString(),
|
|
ProductLevel = info.ProductLevel,
|
|
ProductUpdateLevel = info.ProductUpdateLevel,
|
|
Edition = info.Edition,
|
|
ServerName = options.SendServerName ? info.ServerName : null,
|
|
},
|
|
Rules = results.Select(r => new RuleOutcomeDto { RuleId = r.RuleId, Outcome = r.Outcome.ToString(), Reason = r.Reason }).ToList(),
|
|
Findings = activeFindings.Select(f => new FindingDto
|
|
{
|
|
RuleId = f.RuleId,
|
|
Subject = f.Subject,
|
|
Severity = f.Severity.ToString(),
|
|
Title = f.Title,
|
|
Explanation = f.Explanation,
|
|
Recommendation = f.Recommendation,
|
|
FirstSeenAt = new DateTimeOffset(DateTime.SpecifyKind(f.FirstSeenAt, DateTimeKind.Utc)),
|
|
Evidence = f.Evidence
|
|
.Select(e => new EvidenceDto(e.Name, e.Sensitive && !options.SendSensitiveEvidence ? FindingsSubmission.Redacted : e.Value))
|
|
.ToList(),
|
|
}).ToList(),
|
|
};
|
|
}
|
|
}
|