feat(batch10): task3 implement ocsp cache core stats and compression

This commit is contained in:
Joseph Doherty
2026-02-28 12:59:26 -05:00
parent 4b2875141c
commit 98cf350383
7 changed files with 534 additions and 64 deletions

View File

@@ -0,0 +1,18 @@
using Shouldly;
using ZB.MOM.NatsNet.Server;
namespace ZB.MOM.NatsNet.Server.Tests.Auth;
public sealed class OcspResponseCacheParserTests
{
[Fact]
public void NewOCSPResponseCacheConfig_Defaults_ReturnExpectedValues()
{
var config = OcspHandler.NewOCSPResponseCacheConfig();
config.Type.ShouldBe("local");
config.LocalStore.ShouldBe("_rc_");
config.PreserveRevoked.ShouldBeFalse();
config.SaveInterval.ShouldBe(TimeSpan.FromMinutes(5).TotalSeconds);
}
}

View File

@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0
using Shouldly;
using ZB.MOM.NatsNet.Server.Auth.CertificateIdentityProvider;
using ZB.MOM.NatsNet.Server.Auth.Ocsp;
namespace ZB.MOM.NatsNet.Server.Tests.Auth;
@@ -9,25 +10,86 @@ namespace ZB.MOM.NatsNet.Server.Tests.Auth;
public sealed class OcspResponseCacheTests
{
[Fact]
public void LocalDirCache_GetPutRemove_ShouldPersistToDisk()
public void LocalDirCache_PutReplaceDelete_AdjustsStats()
{
var dir = Path.Combine(Path.GetTempPath(), $"ocsp-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
try
{
var cache = new LocalDirCache(dir);
cache.Get("abc").ShouldBeNull();
var cache = new LocalDirCache(Path.Combine(Path.GetTempPath(), $"ocsp-{Guid.NewGuid():N}"));
cache.Start();
cache.Put("abc", [1, 2, 3]);
cache.Get("abc").ShouldBe([1, 2, 3]);
cache.Put("k1", CreateResponse(OcspStatusAssertion.Good, [1, 2, 3]), "subj");
cache.Put("k1", CreateResponse(OcspStatusAssertion.Revoked, [4, 5, 6]), "subj");
cache.Put("k2", CreateResponse(OcspStatusAssertion.Unknown, [7, 8]), "subj");
cache.Remove("abc");
cache.Get("abc").ShouldBeNull();
}
finally
{
Directory.Delete(dir, recursive: true);
}
var statsAfterPut = cache.Stats();
statsAfterPut.ShouldNotBeNull();
statsAfterPut.Responses.ShouldBe(2);
statsAfterPut.Goods.ShouldBe(0);
statsAfterPut.Revokes.ShouldBe(1);
statsAfterPut.Unknowns.ShouldBe(1);
cache.Delete("k1", wasMiss: false);
var statsAfterDelete = cache.Stats();
statsAfterDelete.ShouldNotBeNull();
statsAfterDelete.Responses.ShouldBe(1);
statsAfterDelete.Revokes.ShouldBe(0);
statsAfterDelete.Unknowns.ShouldBe(1);
}
[Fact]
public void LocalDirCache_DeletePreserveRevoked_WithMiss_AdjustsHitToMiss()
{
var config = OcspHandler.NewOCSPResponseCacheConfig();
config.PreserveRevoked = true;
var cache = new LocalDirCache(config);
cache.Start();
cache.Put("k1", CreateResponse(OcspStatusAssertion.Revoked, [9, 9, 9]), "subj");
cache.Get("k1").ShouldNotBeNull();
cache.Delete("k1", wasMiss: true);
var stats = cache.Stats();
stats.ShouldNotBeNull();
stats.Responses.ShouldBe(1);
stats.Revokes.ShouldBe(1);
stats.Hits.ShouldBe(0);
stats.Misses.ShouldBe(1);
cache.Get("k1").ShouldNotBeNull();
}
[Fact]
public void LocalDirCache_OnlineTypeConfigStats_FollowLifecycle()
{
var config = OcspHandler.NewOCSPResponseCacheConfig();
var cache = new LocalDirCache(config);
cache.Online().ShouldBeFalse();
cache.Type().ShouldBe("local");
cache.Config().LocalStore.ShouldBe(config.LocalStore);
cache.Stats().ShouldBeNull();
cache.Start();
cache.Online().ShouldBeTrue();
cache.Stats().ShouldNotBeNull();
cache.Stop();
cache.Online().ShouldBeFalse();
}
[Fact]
public void LocalDirCache_CompressDecompress_RoundTripsPayload()
{
var cache = new LocalDirCache(Path.Combine(Path.GetTempPath(), $"ocsp-{Guid.NewGuid():N}"));
var payload = "ocsp-cache-roundtrip-data"u8.ToArray();
var (compressed, compressError) = cache.Compress(payload);
compressError.ShouldBeNull();
compressed.ShouldNotBeNull();
var (decompressed, decompressError) = cache.Decompress(compressed!);
decompressError.ShouldBeNull();
decompressed.ShouldNotBeNull();
decompressed.ShouldBe(payload);
}
[Fact]
@@ -45,37 +107,19 @@ public sealed class OcspResponseCacheTests
noOp.Put("k", [5]);
noOp.Get("k").ShouldBeNull();
noOp.Remove("k"); // alias to Delete
noOp.Remove("k");
noOp.Delete("k");
noOp.Stop();
noOp.Online().ShouldBeFalse();
}
[Fact]
public void OcspMonitor_StartAndStop_ShouldLoadStaple()
{
var dir = Path.Combine(Path.GetTempPath(), $"ocsp-monitor-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
try
private static OcspResponse CreateResponse(OcspStatusAssertion status, byte[] raw) =>
new()
{
var stapleFile = Path.Combine(dir, "staple.bin");
File.WriteAllBytes(stapleFile, [9, 9]);
var monitor = new OcspMonitor
{
OcspStapleFile = stapleFile,
CheckInterval = TimeSpan.FromMilliseconds(10),
};
monitor.Start();
Thread.Sleep(30);
monitor.GetStaple().ShouldBe([9, 9]);
monitor.Stop();
}
finally
{
Directory.Delete(dir, recursive: true);
}
}
Status = status,
ThisUpdate = DateTime.UtcNow.AddMinutes(-1),
NextUpdate = DateTime.UtcNow.AddMinutes(10),
Raw = raw,
};
}