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.
135 lines
4.1 KiB
C#
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]");
|
|
}
|
|
}
|