diff --git a/src/NATS.Server/NatsServer.cs b/src/NATS.Server/NatsServer.cs index 157cc21..3b509aa 100644 --- a/src/NATS.Server/NatsServer.cs +++ b/src/NATS.Server/NatsServer.cs @@ -5,6 +5,7 @@ using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; using System.Text; using Microsoft.Extensions.Logging; +using NATS.NKeys; using NATS.Server.Auth; using NATS.Server.Monitoring; using NATS.Server.Protocol; @@ -25,6 +26,7 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable private readonly AuthService _authService; private readonly ConcurrentDictionary _accounts = new(StringComparer.Ordinal); private readonly Account _globalAccount; + private readonly Account _systemAccount; private readonly SslServerAuthenticationOptions? _sslOptions; private readonly TlsRateLimiter? _tlsRateLimiter; private Socket? _listener; @@ -39,6 +41,8 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable public string ServerName => _serverInfo.ServerName; public int ClientCount => _clients.Count; public int Port => _options.Port; + public Account SystemAccount => _systemAccount; + public string ServerNKey { get; } public IEnumerable GetClients() => _clients.Values; public Task WaitForReadyAsync() => _listeningStarted.Task; @@ -51,6 +55,15 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable _authService = AuthService.Build(options); _globalAccount = new Account(Account.GlobalAccountName); _accounts[Account.GlobalAccountName] = _globalAccount; + + // Create $SYS system account (stub -- no internal subscriptions yet) + _systemAccount = new Account("$SYS"); + _accounts["$SYS"] = _systemAccount; + + // Generate Ed25519 server NKey identity + using var serverKeyPair = KeyPair.CreatePair(PrefixByte.Server); + ServerNKey = serverKeyPair.GetPublicKey(); + _serverInfo = new ServerInfo { ServerId = Guid.NewGuid().ToString("N")[..20].ToUpperInvariant(), diff --git a/tests/NATS.Server.Tests/ServerTests.cs b/tests/NATS.Server.Tests/ServerTests.cs index e3a6757..b4f3618 100644 --- a/tests/NATS.Server.Tests/ServerTests.cs +++ b/tests/NATS.Server.Tests/ServerTests.cs @@ -525,3 +525,25 @@ public class CloseReasonTests : IAsyncLifetime natsClient.CloseReason.ShouldBe(ClosedState.ClientClosed); } } + +public class ServerIdentityTests +{ + [Fact] + public void Server_creates_system_account() + { + var server = new NatsServer(new NatsOptions { Port = 0 }, NullLoggerFactory.Instance); + server.SystemAccount.ShouldNotBeNull(); + server.SystemAccount.Name.ShouldBe("$SYS"); + server.Dispose(); + } + + [Fact] + public void Server_generates_nkey_identity() + { + var server = new NatsServer(new NatsOptions { Port = 0 }, NullLoggerFactory.Instance); + server.ServerNKey.ShouldNotBeNullOrEmpty(); + // Server NKey public keys start with 'N' + server.ServerNKey[0].ShouldBe('N'); + server.Dispose(); + } +}