// Port of Go server/accounts_test.go — TestSystemAccountDefaultCreation, // TestSystemAccountSysSubjectRouting, TestNonSystemAccountCannotSubscribeToSys. // Reference: golang/nats-server/server/accounts_test.go, server.go — initSystemAccount. using System.Net; using System.Net.Sockets; using System.Text; using Microsoft.Extensions.Logging.Abstractions; using NATS.Server.Auth; namespace NATS.Server.Tests.Auth; /// /// Tests for the $SYS system account functionality including: /// - Default system account creation with IsSystemAccount flag /// - $SYS.> subject routing to the system account's SubList /// - Non-system accounts blocked from subscribing to $SYS.> subjects /// - System account event publishing /// Reference: Go server/accounts.go — isSystemAccount, isReservedSubject. /// public class SystemAccountTests { // ─── Helpers ──────────────────────────────────────────────────────────── private static int GetFreePort() { using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.Bind(new IPEndPoint(IPAddress.Loopback, 0)); return ((IPEndPoint)sock.LocalEndPoint!).Port; } private static async Task<(NatsServer server, int port, CancellationTokenSource cts)> StartServerAsync(NatsOptions options) { var port = GetFreePort(); options.Port = port; var server = new NatsServer(options, NullLoggerFactory.Instance); var cts = new CancellationTokenSource(); _ = server.StartAsync(cts.Token); await server.WaitForReadyAsync(); return (server, port, cts); } private static async Task RawConnectAsync(int port) { var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); await sock.ConnectAsync(IPAddress.Loopback, port); var buf = new byte[4096]; await sock.ReceiveAsync(buf, SocketFlags.None); return sock; } private static async Task ReadUntilAsync(Socket sock, string expected, int timeoutMs = 5000) { using var cts = new CancellationTokenSource(timeoutMs); var sb = new StringBuilder(); var buf = new byte[4096]; while (!sb.ToString().Contains(expected, StringComparison.Ordinal)) { int n; try { n = await sock.ReceiveAsync(buf, SocketFlags.None, cts.Token); } catch (OperationCanceledException) { break; } if (n == 0) break; sb.Append(Encoding.ASCII.GetString(buf, 0, n)); } return sb.ToString(); } // ─── Tests ────────────────────────────────────────────────────────────── /// /// Verifies that the server creates a $SYS system account by default with /// IsSystemAccount set to true. /// Reference: Go server/server.go — initSystemAccount. /// [Fact] public void Default_system_account_is_created() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); server.SystemAccount.ShouldNotBeNull(); server.SystemAccount.Name.ShouldBe(Account.SystemAccountName); server.SystemAccount.IsSystemAccount.ShouldBeTrue(); } /// /// Verifies that the system account constant matches "$SYS". /// [Fact] public void System_account_name_constant_is_correct() { Account.SystemAccountName.ShouldBe("$SYS"); } /// /// Verifies that a non-system account does not have IsSystemAccount set. /// [Fact] public void Regular_account_is_not_system_account() { var account = new Account("test-account"); account.IsSystemAccount.ShouldBeFalse(); } /// /// Verifies that IsSystemAccount can be explicitly set on an account. /// [Fact] public void IsSystemAccount_can_be_set() { var account = new Account("custom-sys") { IsSystemAccount = true }; account.IsSystemAccount.ShouldBeTrue(); } /// /// Verifies that IsSystemSubject correctly identifies $SYS subjects. /// Reference: Go server/server.go — isReservedSubject. /// [Theory] [InlineData("$SYS", true)] [InlineData("$SYS.ACCOUNT.test.CONNECT", true)] [InlineData("$SYS.SERVER.abc.STATSZ", true)] [InlineData("$SYS.REQ.SERVER.PING.VARZ", true)] [InlineData("foo.bar", false)] [InlineData("$G", false)] [InlineData("SYS.test", false)] [InlineData("$JS.API.STREAM.LIST", false)] [InlineData("$SYS.", true)] public void IsSystemSubject_identifies_sys_subjects(string subject, bool expected) { NatsServer.IsSystemSubject(subject).ShouldBe(expected); } /// /// Verifies that the system account is listed among server accounts. /// [Fact] public void System_account_is_in_server_accounts() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); var accounts = server.GetAccounts().ToList(); accounts.ShouldContain(a => a.Name == Account.SystemAccountName && a.IsSystemAccount); } /// /// Verifies that IsSubscriptionAllowed blocks non-system accounts from $SYS.> subjects. /// Reference: Go server/accounts.go — isReservedForSys. /// [Fact] public void Non_system_account_cannot_subscribe_to_sys_subjects() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); var regularAccount = new Account("regular"); server.IsSubscriptionAllowed(regularAccount, "$SYS.SERVER.abc.STATSZ").ShouldBeFalse(); server.IsSubscriptionAllowed(regularAccount, "$SYS.ACCOUNT.test.CONNECT").ShouldBeFalse(); server.IsSubscriptionAllowed(regularAccount, "$SYS.REQ.SERVER.PING.VARZ").ShouldBeFalse(); } /// /// Verifies that the system account IS allowed to subscribe to $SYS.> subjects. /// [Fact] public void System_account_can_subscribe_to_sys_subjects() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); server.IsSubscriptionAllowed(server.SystemAccount, "$SYS.SERVER.abc.STATSZ").ShouldBeTrue(); server.IsSubscriptionAllowed(server.SystemAccount, "$SYS.ACCOUNT.test.CONNECT").ShouldBeTrue(); } /// /// Verifies that any account can subscribe to non-$SYS subjects. /// [Fact] public void Any_account_can_subscribe_to_regular_subjects() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); var regularAccount = new Account("regular"); server.IsSubscriptionAllowed(regularAccount, "foo.bar").ShouldBeTrue(); server.IsSubscriptionAllowed(regularAccount, "$JS.API.STREAM.LIST").ShouldBeTrue(); server.IsSubscriptionAllowed(server.SystemAccount, "foo.bar").ShouldBeTrue(); } /// /// Verifies that GetSubListForSubject routes $SYS subjects to the system account's SubList. /// Reference: Go server/server.go — sublist routing for internal subjects. /// [Fact] public void GetSubListForSubject_routes_sys_to_system_account() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); var globalAccount = server.GetOrCreateAccount(Account.GlobalAccountName); // $SYS subjects should route to the system account's SubList var sysList = server.GetSubListForSubject(globalAccount, "$SYS.SERVER.abc.STATSZ"); sysList.ShouldBeSameAs(server.SystemAccount.SubList); // Regular subjects should route to the specified account's SubList var regularList = server.GetSubListForSubject(globalAccount, "foo.bar"); regularList.ShouldBeSameAs(globalAccount.SubList); } /// /// Verifies that the EventSystem publishes to the system account's SubList /// and that internal subscriptions for monitoring are registered there. /// The subscriptions are wired up during StartAsync via InitEventTracking. /// [Fact] public async Task Event_system_subscribes_in_system_account() { var (server, _, cts) = await StartServerAsync(new NatsOptions()); try { // The system account's SubList should have subscriptions registered // by the internal event system (VARZ, HEALTHZ, etc.) server.EventSystem.ShouldNotBeNull(); server.SystemAccount.SubList.Count.ShouldBeGreaterThan(0u); } finally { await cts.CancelAsync(); server.Dispose(); } } /// /// Verifies that the global account is separate from the system account. /// [Fact] public void Global_and_system_accounts_are_separate() { var options = new NatsOptions { Port = 0 }; using var server = new NatsServer(options, NullLoggerFactory.Instance); var globalAccount = server.GetOrCreateAccount(Account.GlobalAccountName); var systemAccount = server.SystemAccount; globalAccount.ShouldNotBeSameAs(systemAccount); globalAccount.Name.ShouldBe(Account.GlobalAccountName); systemAccount.Name.ShouldBe(Account.SystemAccountName); globalAccount.IsSystemAccount.ShouldBeFalse(); systemAccount.IsSystemAccount.ShouldBeTrue(); globalAccount.SubList.ShouldNotBeSameAs(systemAccount.SubList); } }