sqlinsight-pro/tests/SQLInsight.Licensing.Tests/LicenseTests.cs
Claude 1ba274d699
Some checks are pending
CI / Build og unit tests (push) Waiting to run
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
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
Fase 3: offline-verifiable signed licenses and license tool
- SQLInsight.Licensing: ECDSA P-256 signed documents (SQLI1.payload.sig),
  licenses with plan, expiry, instance count and key id for rotation;
  30-day grace; invalid or missing licenses are states, never errors,
  and never stop monitoring (a license only adds hub sync and support)
- Trusted public keys are embedded; the source ships with none, so a
  published key can never mint licenses. The vendor adds its own.
- tools/SQLInsight.LicenseTool: keygen, issue, verify
- *.private.pem ignored by git

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:30:28 +00:00

125 lines
4.3 KiB
C#

using System.Security.Cryptography;
namespace SQLInsight.Licensing.Tests;
public class LicenseTests
{
private static readonly DateTimeOffset Now = new(2026, 9, 29, 12, 0, 0, TimeSpan.Zero);
private sealed class FixedTime(DateTimeOffset now) : TimeProvider
{
public override DateTimeOffset GetUtcNow() => now;
}
private static (ECDsa Key, TrustedKeys Trusted) NewKey(string kid = "test1")
{
var key = ECDsa.Create(ECCurve.NamedCurves.nistP256);
return (key, new TrustedKeys([KeyValuePair.Create(kid, Convert.ToBase64String(key.ExportSubjectPublicKeyInfo()))]));
}
private static License Sample(DateTimeOffset expires, LicensePlan plan = LicensePlan.Professional, string kid = "test1") => new()
{
LicenseId = "lic-1", Customer = "Kunde A/S", Plan = plan, IssuedAt = Now.AddDays(-10), ExpiresAt = expires, MaxInstances = 5, KeyId = kid,
};
private static LicenseStatus Check(string text, TrustedKeys keys, DateTimeOffset? now = null) => new LicenseVerifier(keys, new FixedTime(now ?? Now)).Check(text);
[Fact]
public void Valid_license_round_trips()
{
var (key, trusted) = NewKey();
var text = SignedDocument.Sign(Sample(Now.AddYears(1)), key);
var status = Check(text, trusted);
Assert.StartsWith("SQLI1.", text, StringComparison.Ordinal);
Assert.Equal(LicenseState.Valid, status.State);
Assert.Equal("Kunde A/S", status.License!.Customer);
Assert.True(status.AllowsFindingsSync);
}
[Fact]
public void No_license_is_community_and_not_an_error()
{
var status = Check("", NewKey().Trusted);
Assert.Equal(LicenseState.None, status.State);
Assert.False(status.AllowsFindingsSync);
}
[Fact]
public void Tampered_payload_is_invalid()
{
var (key, trusted) = NewKey();
var parts = SignedDocument.Sign(Sample(Now.AddYears(1)), key).Split('.');
var forged = SignedDocument.Sign(Sample(Now.AddYears(10), LicensePlan.Enterprise), ECDsa.Create(ECCurve.NamedCurves.nistP256)).Split('.');
// Enterprise payload with the original, genuine signature.
Assert.Equal(LicenseState.Invalid, Check($"{parts[0]}.{forged[1]}.{parts[2]}", trusted).State);
}
[Fact]
public void License_signed_with_an_untrusted_key_is_invalid()
{
var (_, trusted) = NewKey();
var (other, _) = NewKey();
Assert.Equal(LicenseState.Invalid, Check(SignedDocument.Sign(Sample(Now.AddYears(1)), other), trusted).State);
}
[Fact]
public void Unknown_key_id_is_invalid()
{
var (key, trusted) = NewKey("test1");
Assert.Equal(LicenseState.Invalid, Check(SignedDocument.Sign(Sample(Now.AddYears(1), kid: "other"), key), trusted).State);
}
[Theory]
[InlineData("garbage")]
[InlineData("SQLI1.x.y")]
[InlineData("SQLI1.@@@.###")]
[InlineData("SQLI2.a.b")]
public void Garbage_is_invalid_not_an_exception(string text)
{
Assert.Equal(LicenseState.Invalid, Check(text, NewKey().Trusted).State);
}
[Fact]
public void Expired_license_keeps_syncing_during_grace_then_stops()
{
var (key, trusted) = NewKey();
var text = SignedDocument.Sign(Sample(Now), key);
var grace = Check(text, trusted, Now.AddDays(10));
var expired = Check(text, trusted, Now.AddDays(31));
Assert.Equal(LicenseState.ExpiredInGrace, grace.State);
Assert.True(grace.AllowsFindingsSync);
Assert.Equal(LicenseState.Expired, expired.State);
Assert.False(expired.AllowsFindingsSync);
}
[Fact]
public void Community_plan_does_not_include_sync()
{
var (key, trusted) = NewKey();
Assert.False(Check(SignedDocument.Sign(Sample(Now.AddYears(1), LicensePlan.Community), key), trusted).AllowsFindingsSync);
}
[Fact]
public void Plans()
{
Assert.True(Sample(Now, LicensePlan.Enterprise).IncludesPhoneSupport);
Assert.False(Sample(Now, LicensePlan.Professional).IncludesPhoneSupport);
Assert.True(Sample(Now, LicensePlan.Professional).IncludesPrioritySupport);
}
[Fact]
public void Source_ships_without_trusted_keys()
{
// The vendor adds its public key before a release; a published test key would let anyone mint licenses.
Assert.Equal(0, TrustedKeys.Embedded().Count);
}
}