feat: session B — auth implementation + signals (26 stubs complete)
Implement ConfigureAuthorization, CheckAuthentication, and full auth dispatch in NatsServer.Auth.cs; add HandleSignals in NatsServer.Signals.cs; extend AuthHandler with GetAuthErrClosedState, ValidateProxies, GetTlsAuthDcs, CheckClientTlsCertSubject, ProcessUserPermissionsTemplate; add ReadOperatorJwt/ValidateTrustedOperators to JwtProcessor; add AuthCallout stub; add auth accessor helpers to ClientConnection; add NATS.NKeys package for NKey signature verification; 12 new tests pass.
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
// Copyright 2012-2025 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.Auth;
|
||||
|
||||
using ZB.MOM.NatsNet.Server;
|
||||
using ZB.MOM.NatsNet.Server.Auth;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
public class AuthHandlerExtendedTests
|
||||
{
|
||||
[Fact]
|
||||
public void ValidateProxies_ProxyRequiredWithoutProtocol_ReturnsError()
|
||||
{
|
||||
var opts = new ServerOptions { ProxyRequired = true, ProxyProtocol = false };
|
||||
var err = AuthHandler.ValidateProxies(opts);
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldContain("proxy_required");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateProxies_ProxyRequiredWithProtocol_ReturnsNull()
|
||||
{
|
||||
var opts = new ServerOptions { ProxyRequired = true, ProxyProtocol = true };
|
||||
var err = AuthHandler.ValidateProxies(opts);
|
||||
err.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAuthErrClosedState_ExpiredMessage_ReturnsExpiredState()
|
||||
{
|
||||
var err = new InvalidOperationException("token is expired");
|
||||
AuthHandler.GetAuthErrClosedState(err).ShouldBe(ClosedState.AuthenticationExpired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAuthErrClosedState_NullError_ReturnsTimeout()
|
||||
{
|
||||
AuthHandler.GetAuthErrClosedState(null).ShouldBe(ClosedState.AuthenticationTimeout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAuthErrClosedState_RevokedMessage_ReturnsRevoked()
|
||||
{
|
||||
var err = new InvalidOperationException("credential was revoked");
|
||||
AuthHandler.GetAuthErrClosedState(err).ShouldBe(ClosedState.AuthRevoked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckClientTlsCertSubject_NullCert_ReturnsFalse()
|
||||
{
|
||||
AuthHandler.CheckClientTlsCertSubject(null, _ => true).ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessUserPermissionsTemplate_ExpandsAccountVariable()
|
||||
{
|
||||
var lim = new Permissions
|
||||
{
|
||||
Publish = new SubjectPermission { Allow = new List<string> { "{{account}}.events" } },
|
||||
};
|
||||
var (result, err) = AuthHandler.ProcessUserPermissionsTemplate(lim, "myaccount", null);
|
||||
err.ShouldBeNull();
|
||||
result.Publish!.Allow![0].ShouldBe("myaccount.events");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessUserPermissionsTemplate_ExpandsTagVariable()
|
||||
{
|
||||
var lim = new Permissions
|
||||
{
|
||||
Subscribe = new SubjectPermission { Allow = new List<string> { "{{tag.region}}.alerts" } },
|
||||
};
|
||||
var tags = new Dictionary<string, string> { ["region"] = "us-east" };
|
||||
var (result, err) = AuthHandler.ProcessUserPermissionsTemplate(lim, "acc", tags);
|
||||
err.ShouldBeNull();
|
||||
result.Subscribe!.Allow![0].ShouldBe("us-east.alerts");
|
||||
}
|
||||
}
|
||||
|
||||
public class JwtProcessorOperatorTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReadOperatorJwtInternal_EmptyString_ReturnsError()
|
||||
{
|
||||
var (claims, err) = JwtProcessor.ReadOperatorJwtInternal(string.Empty);
|
||||
claims.ShouldBeNull();
|
||||
err.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadOperatorJwtInternal_InvalidPrefix_ReturnsFormatError()
|
||||
{
|
||||
var (claims, err) = JwtProcessor.ReadOperatorJwtInternal("NOTAJWT.payload.sig");
|
||||
claims.ShouldBeNull();
|
||||
err.ShouldBeOfType<FormatException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadOperatorJwt_FileNotFound_ReturnsError()
|
||||
{
|
||||
var (claims, err) = JwtProcessor.ReadOperatorJwt("/nonexistent/operator.jwt");
|
||||
claims.ShouldBeNull();
|
||||
err.ShouldBeOfType<IOException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateTrustedOperators_EmptyList_ReturnsNull()
|
||||
{
|
||||
var opts = new ServerOptions();
|
||||
JwtProcessor.ValidateTrustedOperators(opts).ShouldBeNull();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user