Files
natsdotnet/tests/NATS.Server.Transport.Tests/TlsOcspParityBatch1Tests.cs
Joseph Doherty d2c04fcca5 refactor: extract NATS.Server.Transport.Tests project
Move TLS, OCSP, WebSocket, Networking, and IO test files from
NATS.Server.Tests into a dedicated NATS.Server.Transport.Tests
project. Update namespaces, replace private GetFreePort/ReadUntilAsync
with shared TestUtilities helpers, extract TestCertHelper to
TestUtilities, and replace Task.Delay polling loops with
PollHelper.WaitUntilAsync/YieldForAsync for proper synchronization.
2026-03-12 14:57:35 -04:00

135 lines
4.1 KiB
C#

using System.Security.Cryptography;
using System.Text.Json;
using NATS.Server.Configuration;
using NATS.Server.TestUtilities;
using NATS.Server.Tls;
namespace NATS.Server.Transport.Tests;
public class TlsOcspParityBatch1Tests
{
[Fact]
public void OCSPPeerConfig_defaults_match_go_reference()
{
var cfg = OCSPPeerConfig.NewOCSPPeerConfig();
cfg.Verify.ShouldBeFalse();
cfg.Timeout.ShouldBe(2d);
cfg.ClockSkew.ShouldBe(30d);
cfg.WarnOnly.ShouldBeFalse();
cfg.UnknownIsGood.ShouldBeFalse();
cfg.AllowWhenCAUnreachable.ShouldBeFalse();
cfg.TTLUnsetNextUpdate.ShouldBe(3600d);
}
[Fact]
public void OCSPPeerConfig_parse_map_parses_supported_fields()
{
var cfg = OCSPPeerConfig.Parse(new Dictionary<string, object?>
{
["verify"] = true,
["allowed_clockskew"] = "45s",
["ca_timeout"] = 1.5d,
["cache_ttl_when_next_update_unset"] = 120L,
["warn_only"] = true,
["unknown_is_good"] = true,
["allow_when_ca_unreachable"] = true,
});
cfg.Verify.ShouldBeTrue();
cfg.ClockSkew.ShouldBe(45d);
cfg.Timeout.ShouldBe(1.5d);
cfg.TTLUnsetNextUpdate.ShouldBe(120d);
cfg.WarnOnly.ShouldBeTrue();
cfg.UnknownIsGood.ShouldBeTrue();
cfg.AllowWhenCAUnreachable.ShouldBeTrue();
}
[Fact]
public void OCSPPeerConfig_parse_unknown_field_throws()
{
var ex = Should.Throw<FormatException>(() =>
OCSPPeerConfig.Parse(new Dictionary<string, object?> { ["bogus"] = true }));
ex.Message.ShouldContain("unknown field [bogus]");
}
[Fact]
public void ConfigProcessor_parses_ocsp_peer_short_form()
{
var opts = ConfigProcessor.ProcessConfig("""
tls {
ocsp_peer: true
}
""");
opts.OcspPeerVerify.ShouldBeTrue();
}
[Fact]
public void ConfigProcessor_parses_ocsp_peer_long_form_verify()
{
var opts = ConfigProcessor.ProcessConfig("""
tls {
ocsp_peer {
verify: true
ca_timeout: 2s
allowed_clockskew: 30s
}
}
""");
opts.OcspPeerVerify.ShouldBeTrue();
}
[Fact]
public void GenerateFingerprint_uses_raw_certificate_sha256()
{
var (cert, _) = TestCertHelper.GenerateTestCert();
var expected = Convert.ToBase64String(SHA256.HashData(cert.RawData));
TlsHelper.GenerateFingerprint(cert).ShouldBe(expected);
}
[Fact]
public void GetWebEndpoints_filters_non_web_uris()
{
var urls = TlsHelper.GetWebEndpoints(
["http://a.example", "https://b.example", "ftp://bad.example", "not a uri"]);
urls.Count.ShouldBe(2);
urls[0].Scheme.ShouldBe(Uri.UriSchemeHttp);
urls[1].Scheme.ShouldBe(Uri.UriSchemeHttps);
}
[Fact]
public void Subject_and_issuer_dn_helpers_return_values_and_empty_for_null()
{
var (cert, _) = TestCertHelper.GenerateTestCert();
TlsHelper.GetSubjectDNForm(cert).ShouldNotBeNullOrWhiteSpace();
TlsHelper.GetIssuerDNForm(cert).ShouldNotBeNullOrWhiteSpace();
TlsHelper.GetSubjectDNForm(null).ShouldBe(string.Empty);
TlsHelper.GetIssuerDNForm(null).ShouldBe(string.Empty);
}
[Fact]
public void StatusAssertion_json_converter_uses_string_values_and_unknown_fallback()
{
var revokedJson = JsonSerializer.Serialize(StatusAssertion.Revoked);
revokedJson.ShouldBe("\"revoked\"");
var unknown = JsonSerializer.Deserialize<StatusAssertion>("\"nonsense\"");
unknown.ShouldBe(StatusAssertion.Unknown);
}
[Fact]
public void OcspPeer_messages_match_go_literals()
{
OcspPeerMessages.MsgTLSClientRejectConnection.ShouldBe("client not OCSP valid");
OcspPeerMessages.MsgTLSServerRejectConnection.ShouldBe("server not OCSP valid");
OcspPeerMessages.MsgCacheOnline.ShouldBe("OCSP peer cache online, type [%s]");
OcspPeerMessages.MsgCacheOffline.ShouldBe("OCSP peer cache offline, type [%s]");
}
}