using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using NATS.Server.Auth; namespace NATS.Server.Tests; public class TlsMapAuthenticatorTests { private static X509Certificate2 CreateSelfSignedCert(string cn) { using var rsa = RSA.Create(2048); var req = new CertificateRequest($"CN={cn}", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1)); } private static X509Certificate2 CreateCertWithDn(string dn) { using var rsa = RSA.Create(2048); var req = new CertificateRequest(dn, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1)); } [Fact] public void Matches_user_by_cn() { var users = new List { new() { Username = "alice", Password = "" }, }; var auth = new TlsMapAuthenticator(users); var cert = CreateSelfSignedCert("alice"); var ctx = new ClientAuthContext { Opts = new Protocol.ClientOptions(), Nonce = [], ClientCertificate = cert, }; var result = auth.Authenticate(ctx); result.ShouldNotBeNull(); result.Identity.ShouldBe("alice"); } [Fact] public void Returns_null_when_no_cert() { var users = new List { new() { Username = "alice", Password = "" }, }; var auth = new TlsMapAuthenticator(users); var ctx = new ClientAuthContext { Opts = new Protocol.ClientOptions(), Nonce = [], ClientCertificate = null, }; var result = auth.Authenticate(ctx); result.ShouldBeNull(); } [Fact] public void Returns_null_when_cn_doesnt_match() { var users = new List { new() { Username = "alice", Password = "" }, }; var auth = new TlsMapAuthenticator(users); var cert = CreateSelfSignedCert("bob"); var ctx = new ClientAuthContext { Opts = new Protocol.ClientOptions(), Nonce = [], ClientCertificate = cert, }; var result = auth.Authenticate(ctx); result.ShouldBeNull(); } [Fact] public void Matches_by_full_dn_string() { var users = new List { new() { Username = "CN=alice, O=TestOrg", Password = "" }, }; var auth = new TlsMapAuthenticator(users); var cert = CreateCertWithDn("CN=alice, O=TestOrg"); var ctx = new ClientAuthContext { Opts = new Protocol.ClientOptions(), Nonce = [], ClientCertificate = cert, }; var result = auth.Authenticate(ctx); result.ShouldNotBeNull(); result.Identity.ShouldBe("CN=alice, O=TestOrg"); } [Fact] public void Returns_permissions_from_matched_user() { var perms = new Permissions { Publish = new SubjectPermission { Allow = ["foo.>"] }, }; var users = new List { new() { Username = "alice", Password = "", Permissions = perms }, }; var auth = new TlsMapAuthenticator(users); var cert = CreateSelfSignedCert("alice"); var ctx = new ClientAuthContext { Opts = new Protocol.ClientOptions(), Nonce = [], ClientCertificate = cert, }; var result = auth.Authenticate(ctx); result.ShouldNotBeNull(); result.Permissions.ShouldNotBeNull(); result.Permissions.Publish!.Allow!.ShouldContain("foo.>"); } }