public void TestParseConnectionStringSingleHostAddress() { IPEndPoint[] endpoints = SecureTransport.ParseConnectionString("localhost:99"); Assert.AreEqual(1, endpoints.Length); Assert.IsTrue(endpoints[0].Address.Equals(IPAddress.Loopback) || endpoints[0].Address.Equals(IPAddress.IPv6Loopback)); Assert.AreEqual(99, endpoints[0].Port); }
public void TestMaxConnectionIdleTime() { var connection1Established = new ManualResetEventSlim(); var connection1Lost = new ManualResetEventSlim(); var configuration = new SecureTransport.Configuration { MaxConnectionIdleTime = TimeSpan.FromSeconds(5), CommunicationProtocolVersion = 1, }; using (var cancellationTokenSource = new CancellationTokenSource()) using (var serverTransport = new SecureTransport(configuration, null, cancellationTokenSource.Token)) { serverTransport.StartServer(this.serverListenPort); using (var clientTransport1 = CreateTransport()) { serverTransport.OnNewConnection = _ => connection1Established.Set(); clientTransport1.OnConnectionLost = () => connection1Lost.Set(); clientTransport1.StartClient(this.clientEndPoints); connection1Established.Wait(); // The connections should be terminated after 5 seconds Trace.TraceInformation("Waiting for connection to be lost"); connection1Lost.Wait(); } } }
public void TestSingleClientConnection() { var connectionEstablished = new ManualResetEventSlim(); var connectionLost = new ManualResetEventSlim(); SecureTransport serverTransport = null; SecureTransport clientTransport = null; try { serverTransport = CreateTransport(); serverTransport.StartServer(this.serverListenPort); clientTransport = CreateTransport(); clientTransport.OnNewConnection = _ => connectionEstablished.Set(); clientTransport.OnConnectionLost = () => connectionLost.Set(); clientTransport.StartClient(this.clientEndPoints); connectionEstablished.Wait(); } finally { try { serverTransport.Dispose(); Assert.IsTrue(connectionLost.Wait(5000)); } finally { clientTransport?.Dispose(); } } }
private void Run(int port) { var protocol = new RingMasterCommunicationProtocol(); this.CreateBackend(); using (var cancel = new CancellationTokenSource()) { this.ringMasterServer = new RingMasterServer(protocol, null, cancel.Token); var transportConfig = new SecureTransport.Configuration { UseSecureConnection = false, IsClientCertificateRequired = false, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, }; using (var serverTransport = new SecureTransport(transportConfig)) { this.ringMasterServer.RegisterTransport(serverTransport); this.ringMasterServer.OnInitSession = initRequest => { return(new CoreRequestHandler(this.backend, initRequest)); }; serverTransport.StartServer(port); Console.WriteLine("Press ENTER to exit..."); Console.ReadLine(); cancel.Cancel(); } } }
/// <summary> /// Initializes a new instance of the <see cref="TcpCommunicationListener" /> class. /// </summary> /// <param name="server">RingMaster server</param> /// <param name="port">Port where this listener will listen</param> /// <param name="uriPublished">The specific uri to listen on</param> /// <param name="executor">RingMaster request executor</param> /// <param name="instrumentation">Instrumentation consumer</param> /// <param name="protocol">The Marshalling protocol</param> /// <param name="maximumSupportedProtocolVersion">Maximum supported version</param> public TcpCommunicationListener( RingMasterServer server, int port, string uriPublished, IRingMasterRequestExecutor executor, IRingMasterServerInstrumentation instrumentation, ICommunicationProtocol protocol, uint maximumSupportedProtocolVersion) { this.server = server; this.port = port; this.uriPublished = uriPublished; this.instrumentation = instrumentation; this.protocol = protocol; var transportConfig = new SecureTransport.Configuration { UseSecureConnection = false, IsClientCertificateRequired = false, CommunicationProtocolVersion = maximumSupportedProtocolVersion, }; this.transport = new SecureTransport(transportConfig); this.executor = executor; }
public void TestSendDecryptResponse() { String methodName = "methodOne"; String arg0 = "arg0"; String arg1 = "arg1"; TestWebServiceProxy testProxy = new TestWebServiceProxy(); ITransportProxy proxy = testProxy; FolaighKeyStore keyStore = new FolaighKeyStore(KEYSTORE, "bird8top".ToCharArray()); RSACipher encryptorVerifier = new RSACipher( keyStore, "countyKey", false); RSACipher signerDecryptor = new RSACipher( keyStore, "stateKey", true); SecureTransport transport = new SecureTransport(proxy, encryptorVerifier, signerDecryptor); String response = transport.send(methodName, new String[] { arg0, arg1 }); Assert.AreEqual(TestWebServiceProxy.THIS_IS_THE_RESPONSE, response); }
public void Initialize() { this.serverListenPort = GetAvailablePort(9000); string connectionString = string.Format("127.0.0.1:{0}", this.serverListenPort); this.clientEndPoints = SecureTransport.ParseConnectionString(connectionString); }
public void TestParseConnectionStringSingleEndpoint() { IPEndPoint[] endpoints = SecureTransport.ParseConnectionString("127.0.0.1:99"); Assert.AreEqual(1, endpoints.Length); Assert.AreEqual("127.0.0.1", endpoints[0].Address.ToString()); Assert.AreEqual(99, endpoints[0].Port); }
private void ConnectPerformanceTest(ConfigurationSection config, CancellationToken cancellationToken) { try { var instrumentation = new ConnectPerformanceInstrumentation(this.MetricsFactory); var random = new Random(); string connectionString = config.GetStringValue("TargetConnectionString"); connectionString = Helpers.GetServerAddressIfNotProvided(connectionString); IPEndPoint[] endpoints = SecureTransport.ParseConnectionString(connectionString); string testPath = config.GetStringValue("TestPath"); int numConnections = config.GetIntValue("NumberOfConnections"); int maxConcurrentRequests = config.GetIntValue("MaxConcurrentRequests"); int minConnectionLifetimeSeconds = config.GetIntValue("MinConnectionLifetimeSeconds"); int maxConnectionLifetimeSeconds = config.GetIntValue("MaxConnectionLifetimeSeconds"); Func <IRingMasterRequestHandler> createConnection = () => { var connectionConfiguration = new SecureTransport.Configuration { UseSecureConnection = false, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, MaxConnectionLifespan = TimeSpan.FromSeconds(random.Next(minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds)) }; var protocol = new RingMasterCommunicationProtocol(); var transport = new SecureTransport(connectionConfiguration, instrumentation, cancellationToken); var client = new RingMasterClient(protocol, transport); transport.StartClient(endpoints); ConnectionStressServiceEventSource.Log.CreateConnection( connectionConfiguration.UseSecureConnection, connectionConfiguration.CommunicationProtocolVersion, (long)connectionConfiguration.MaxConnectionLifespan.TotalSeconds); client.Exists("/", watcher: null).Wait(); return((IRingMasterRequestHandler)client); }; using (var connectPerformanceTest = new ConnectPerformance(instrumentation, maxConcurrentRequests, cancellationToken)) { ConnectionStressServiceEventSource.Log.ConnectPerformanceTestStarted(testPath, numConnections, minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds); connectPerformanceTest.EstablishConnections(createConnection, numConnections); connectPerformanceTest.QueueRequests(testPath); } ConnectionStressServiceEventSource.Log.ConnectPerformanceTestCompleted(); } catch (Exception ex) { ConnectionStressServiceEventSource.Log.ConnectPerformanceTestFailed(ex.ToString()); } }
public void TestClientConnectionRetryDifferentServer() { var connectionEstablished = new ManualResetEventSlim(); var connectionLost = new ManualResetEventSlim(); int server1ListenPort = GetAvailablePort(9997); int server2ListenPort = GetAvailablePort(server1ListenPort + 1); IPEndPoint[] clientEndPoints = SecureTransport.ParseConnectionString(string.Format("127.0.0.1:{0},127.0.0.1:{1}", server1ListenPort, server2ListenPort)); SecureTransport serverTransport1 = null; SecureTransport clientTransport = null; try { serverTransport1 = CreateTransport(); serverTransport1.StartServer(server1ListenPort); clientTransport = CreateTransport(); clientTransport.OnNewConnection = _ => connectionEstablished.Set(); clientTransport.OnConnectionLost = () => connectionLost.Set(); clientTransport.StartClient(clientEndPoints); connectionEstablished.Wait(); // Now stop the server to break the established connection serverTransport1.Stop(); connectionLost.Wait(); connectionEstablished.Reset(); connectionLost.Reset(); using (var serverTransport2 = CreateTransport()) { // Start a new server at a different port and verify that the client automatically connects to it serverTransport2.StartServer(server2ListenPort); connectionEstablished.Wait(); } } finally { try { serverTransport1.Dispose(); Assert.IsTrue(connectionLost.Wait(5000)); } finally { clientTransport?.Dispose(); } } }
public void TestParseConnectionStringMultipleEndpoints() { IPEndPoint[] endpoints = SecureTransport.ParseConnectionString("127.0.0.1:99,10.11.12.13:990,8.8.8.8:8"); Assert.AreEqual(3, endpoints.Length); Assert.AreEqual("127.0.0.1", endpoints[0].Address.ToString()); Assert.AreEqual(99, endpoints[0].Port); Assert.AreEqual("10.11.12.13", endpoints[1].Address.ToString()); Assert.AreEqual(990, endpoints[1].Port); Assert.AreEqual("8.8.8.8", endpoints[2].Address.ToString()); Assert.AreEqual(8, endpoints[2].Port); }
public void TestReceiveResponse() { TestWebServiceProxy testProxy = new TestWebServiceProxy(); ITransportProxy proxy = testProxy; FolaighKeyStore keyStore = new FolaighKeyStore(KEYSTORE, "bird8top".ToCharArray()); RSACipher encryptorVerifier = new RSACipher( keyStore, "stateKey", false); RSACipher signerDecryptor = new RSACipher( keyStore, "countyKey", true); SecureTransport transport = new SecureTransport(proxy, encryptorVerifier, signerDecryptor); String sender = "stateKey"; string result = transport.receive(encryptedMessage, signature, encryptedAesKey, encryptedIV, sender); // The result should be an XML document with an encrypted AES key // and // IV, // an AES-encrypted response string, and a signed hash of the // encrypted // response string. ResponseInfo objResponseInfo = ResponseInfo.decode(result); encryptorVerifier = new RSACipher( keyStore, "countyKey", false); signerDecryptor = new RSACipher( keyStore, "stateKey", true); byte[] sig = Convert.FromBase64String(objResponseInfo.Signature); byte[] hash = encryptorVerifier.decrypt(sig); byte[] encryptedResponse = Convert.FromBase64String(objResponseInfo.Response); byte[] expectedHash = Hash.getHash(encryptedResponse); Assert.AreEqual(hash, expectedHash); byte[] key = signerDecryptor.decrypt(Convert.FromBase64String(objResponseInfo.Key)); byte[] iv = signerDecryptor.decrypt(Convert.FromBase64String(objResponseInfo.IV)); AESCipher cipher = new AESCipher(key, iv); Assert.AreEqual(TestWebServiceProxy.THIS_IS_THE_RESPONSE, cipher .decrypt(encryptedResponse)); }
private static ServerSpec CreateServerSpec(string connectionString, X509Certificate[] clientCerts = null, X509Certificate[] serverCerts = null) { var server = new ServerSpec(); server.Endpoints = SecureTransport.ParseConnectionString(connectionString); server.UseSecureConnection = (clientCerts != null) && (serverCerts != null) && (clientCerts.Length > 0) && (serverCerts.Length > 0); if (server.UseSecureConnection) { server.ClientCertificate = clientCerts[0]; server.AcceptedServerCertificates = serverCerts; } return(server); }
public void TestMultipleServerConnections() { var connection1Established = new ManualResetEventSlim(); var connection1Lost = new ManualResetEventSlim(); var connection2Established = new ManualResetEventSlim(); var connection2Lost = new ManualResetEventSlim(); var port = GetAvailablePort(10000); var clientEndpoint = SecureTransport.ParseConnectionString($"127.0.0.1:{port}"); SecureTransport serverTransport = null; SecureTransport clientTransport1 = null; SecureTransport clientTransport2 = null; try { serverTransport = CreateTransport(); serverTransport.StartServer(port); clientTransport1 = CreateTransport(); serverTransport.OnNewConnection = _ => connection1Established.Set(); clientTransport1.OnConnectionLost = () => connection1Lost.Set(); clientTransport1.StartClient(clientEndpoint); connection1Established.Wait(); clientTransport2 = CreateTransport(); serverTransport.OnNewConnection = _ => connection2Established.Set(); clientTransport2.OnConnectionLost = () => connection2Lost.Set(); clientTransport2.StartClient(clientEndpoint); connection2Established.Wait(); } finally { try { serverTransport.Dispose(); Assert.IsTrue(connection1Lost.Wait(5000)); Assert.IsTrue(connection2Lost.Wait(5000)); } finally { clientTransport1?.Dispose(); clientTransport2?.Dispose(); } } }
private void ConnectPerformanceTest(SecureTransport.Configuration configuration, IPEndPoint[] endpoints, int numConnections) { var instrumentation = new ConnectPerformanceInstrumentation(); var random = new Random(); int minConnectionLifetimeSeconds = int.Parse(appSettings["ConnectPerformance.MinConnectionLifetimeSeconds"]); int maxConnectionLifetimeSeconds = int.Parse(appSettings["ConnectPerformance.MaxConnectionLifetimeSeconds"]); Func <IRingMasterRequestHandler> createConnection = () => { var connectionConfiguration = new SecureTransport.Configuration { UseSecureConnection = configuration.UseSecureConnection, ClientCertificates = configuration.ClientCertificates, ServerCertificates = configuration.ServerCertificates, CommunicationProtocolVersion = configuration.CommunicationProtocolVersion, MaxConnectionLifespan = TimeSpan.FromSeconds(random.Next(minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds)), }; var protocol = new RingMasterCommunicationProtocol(); var transport = new SecureTransport(connectionConfiguration, instrumentation, CancellationToken.None); var client = new RingMasterClient(protocol, transport); transport.StartClient(endpoints); client.Exists("/", watcher: null).Wait(); return((IRingMasterRequestHandler)client); }; using (var connectPerformanceTest = new ConnectPerformance(instrumentation, this.MaxConcurrency, CancellationToken.None)) { Trace.TraceInformation($"Connect performance test numConnections={numConnections}, path={this.TestPath}, minConnectionLifetimeSeconds={minConnectionLifetimeSeconds}, maxConnectionLifetimeSeconds={maxConnectionLifetimeSeconds}"); connectPerformanceTest.EstablishConnections(createConnection, numConnections); var task = Task.Run(() => connectPerformanceTest.QueueRequests(this.TestPath)); long lastSuccessCount = 0; var timer = Stopwatch.StartNew(); while (!task.Wait(5000)) { timer.Stop(); long rate = (long)((instrumentation.Success - lastSuccessCount) * 1000) / timer.ElapsedMilliseconds; Trace.TraceInformation($"Connections created={instrumentation.ConnectionCreatedCount}, closed={instrumentation.ConnectionClosedCount}, requestSuccess={instrumentation.Success}, requestFailure={instrumentation.Failure}, rate={rate}"); timer.Restart(); lastSuccessCount = instrumentation.Success; } } }
public void TestClientConnectionRetrySameServer() { var connectionEstablished = new ManualResetEventSlim(); var connectionLost = new ManualResetEventSlim(); SecureTransport serverTransport = null; SecureTransport clientTransport = null; try { serverTransport = CreateTransport(); serverTransport.StartServer(this.serverListenPort); clientTransport = CreateTransport(); clientTransport.OnNewConnection = _ => connectionEstablished.Set(); clientTransport.OnConnectionLost = () => connectionLost.Set(); clientTransport.StartClient(this.clientEndPoints); connectionEstablished.Wait(); // Now stop the server to break the established connection serverTransport.Stop(); connectionLost.Wait(); connectionEstablished.Reset(); connectionLost.Reset(); // Restart the server and verify that the client automatically connects to it serverTransport.StartServer(this.serverListenPort); connectionEstablished.Wait(); } finally { try { serverTransport.Dispose(); Assert.IsTrue(connectionLost.Wait(5000)); } finally { clientTransport?.Dispose(); } } }
public static void Setup(TestContext context) { var path = System.Reflection.Assembly.GetExecutingAssembly().Location; var builder = new ConfigurationBuilder().SetBasePath(Path.GetDirectoryName(path)).AddJsonFile("appSettings.json"); IConfiguration appSettings = builder.Build(); Helpers.SetupTraceLog(Path.Combine(appSettings["LogFolder"], "VegaInMemoryPerf.LogPath")); log = s => Trace.TraceInformation(s); // If a parameter is specified as follows: // te.exe VegaInMemoryPerf.dll /p:ServerAddress=127.0.0.1:99 if (!context.Properties.ContainsKey("ServerAddress")) { backendCore = CreateBackend(); backendServer = new RingMasterServer(protocol, null, CancellationToken.None); var transportConfig = new SecureTransport.Configuration { UseSecureConnection = false, IsClientCertificateRequired = false, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, }; serverTransport = new SecureTransport(transportConfig); backendServer.RegisterTransport(serverTransport); backendServer.OnInitSession = initRequest => { return(new CoreRequestHandler(backendCore, initRequest)); }; serverTransport.StartServer(10009); serverAddress = "127.0.0.1:10009"; } else { serverAddress = context.Properties["ServerAddress"] as string; } // Read the app settings minPayloadSize = int.Parse(appSettings["MinPayloadSize"]); maxPayloadSize = int.Parse(appSettings["MaxPayloadSize"]); threadCount = int.Parse(appSettings["ThreadCount"]); }
public void TestClientCertificateSelectionCallback() { var certificates = GetLocalCertificates(2); X509Certificate[] clientCertificates = new X509Certificate[] { certificates[0] }; X509Certificate[] serverCertificates = new X509Certificate[] { certificates[1] }; int port = TestSecureTransport.GetAvailablePort(10000); var serverAcceptedClient = new ManualResetEventSlim(); var clientConnected = new ManualResetEventSlim(); var clientCertificateSelectionCallbackCalled = new ManualResetEventSlim(); var configuration = new SecureTransport.Configuration() { UseSecureConnection = true, ClientCertificates = certificates, ServerCertificates = serverCertificates, CommunicationProtocolVersion = 1, MustCheckCertificateTrustChain = false, LocalCertificateSelectionCallback = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => { clientCertificateSelectionCallbackCalled.Set(); return(certificates[0]); } }; using (var server = CreateTransport(clientCertificates, serverCertificates)) using (var client = new SecureTransport(configuration, null, CancellationToken.None)) { server.OnNewConnection = _ => serverAcceptedClient.Set(); client.OnNewConnection = _ => clientConnected.Set(); server.StartServer(port); client.StartClient(new IPEndPoint(IPAddress.Loopback, port)); serverAcceptedClient.Wait(30000).Should().BeTrue(); // Client certificate selection callback must be called before // the client accepts the connection. clientCertificateSelectionCallbackCalled.Wait(3000).Should().BeTrue(); clientConnected.Wait(30000).Should().BeTrue(); } }
/// <inheritdoc /> protected override void ProcessRecord() { var serverSpec = new RingMasterClient.ServerSpec { Endpoints = SecureTransport.ParseConnectionString(this.ConnectionString), UseSecureConnection = true, MustCheckCertificateRevocation = !this.NoCertificateRevocationCheck.IsPresent, MustCheckCertificateTrustChain = !this.NoTrustChainCheck.IsPresent, CertValidationASubject = this.CertValidationASubject, CertValidationASigningThumbprints = this.CertValidationASigningThumbprints, CertValidationBSubject = this.CertValidationBSubject, CertValidationBSigningThumbprints = this.CertValidationBSigningThumbprints, }; string[] clientCerts = new string[] { this.ClientCertificateThumbprint }; serverSpec.ClientCertificate = SecureTransport.GetCertificatesFromThumbPrintOrFileName(clientCerts)[0]; serverSpec.AcceptedServerCertificates = SecureTransport.GetCertificatesFromThumbPrintOrFileName(this.AcceptedServerCertificateThumbprints); this.WriteObject(serverSpec); }
protected override void ProcessRecord() { if (this.ServerSpec == null) { this.ServerSpec = new RingMasterClient.ServerSpec { Endpoints = SecureTransport.ParseConnectionString(this.ConnectionString), UseSecureConnection = false, }; } var configuration = new RingMasterClient.Configuration { DefaultTimeout = this.DefaultTimeout, HeartBeatInterval = this.HeartBeatInterval, RequestQueueLength = this.RequestQueueLength, }; this.WriteObject(new RingMasterSession(this.ServerSpec, configuration)); }
/// <inheritdoc /> public override void Send(IRingMasterBackendRequest req) { if (req == null) { throw new ArgumentNullException("req"); } if (this.client == null) { SecureTransport transport = null; try { var endpoints = SecureTransport.ParseConnectionString(this.ConnectString); transport = new SecureTransport(this.transportConfiguration); this.client = new RingMasterClient(this.protocol, transport); this.secureTransport = transport; // The lifetime of transport is now owned by RingMasterClient transport = null; this.secureTransport.StartClient(endpoints); } finally { transport?.Dispose(); } } this.client.Request(req.WrappedRequest).ContinueWith(responseTask => { try { RequestResponse response = responseTask.Result; req.NotifyComplete(response.ResultCode, response.Content, response.Stat, response.ResponsePath); } catch (System.Exception) { req.NotifyComplete((int)RingMasterException.Code.Systemerror, null, null, null); } }); }
public void TestReceiveCall() { TestWebServiceProxy testProxy = new TestWebServiceProxy(); ITransportProxy proxy = testProxy; // This establishes the signature of the proxy's "receive" // method. We need to know if the signature was verified // and whether it came from an authorized sender. MethodInfo methodInfo = new MethodInfo(); bool validSignature = true; String sender = "sender"; String reply = proxy.receive(validSignature, methodInfo, sender); FolaighKeyStore keyStore = new FolaighKeyStore(KEYSTORE, "bird8top".ToCharArray()); RSACipher encryptorVerifier = new RSACipher( keyStore, "stateKey", false); RSACipher signerDecryptor = new RSACipher( keyStore, "countyKey", true); SecureTransport transport = new SecureTransport(proxy, encryptorVerifier, signerDecryptor); testProxy.m_validSignature = false; testProxy.m_message = null; sender = "stateKey"; String result = transport.receive(encryptedMessage, signature, encryptedAesKey, encryptedIV, sender); Assert.IsTrue(testProxy.m_validSignature); Assert.IsNotNull(testProxy.m_methodInfo); Assert.AreEqual(expectedMethodInfo.MethodName, testProxy.m_methodInfo.MethodName); Assert.AreEqual(sender, testProxy.m_senderAlias); }
/// <summary> /// Defines the entry point of the application. /// </summary> /// <param name="args">Command line arguments</param> public static void Main(string[] args) { Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); if (args == null || args.Length < 1) { Trace.TraceError("USAGE: SecureTransportClientTool.exe <connection string> [<request length>]"); return; } string connectionString = args[0]; int requestLength = 128; int waitTimeoutMs = 30000; if (args.Length > 1) { requestLength = int.Parse(args[1]); } var path = System.Reflection.Assembly.GetExecutingAssembly().Location; var builder = new ConfigurationBuilder().SetBasePath(Path.GetDirectoryName(path)).AddJsonFile("appSettings.json"); var appSettings = builder.Build(); var configuration = new SecureTransport.Configuration(); int maxConcurrentRequests = int.Parse(appSettings["MaxConcurrentRequests"]); configuration.SendBufferSize = int.Parse(appSettings["SendBufferSize"]); configuration.ReceiveBufferSize = int.Parse(appSettings["ReceiveBufferSize"]); configuration.UseSecureConnection = bool.Parse(appSettings["SSL.UseSSL"]); if (configuration.UseSecureConnection) { string[] clientThumbprints = appSettings["SSL.ClientCerts"].Split(new char[] { ';', ',' }); string[] serviceThumbprints = appSettings["SSL.ServerCerts"].Split(new char[] { ';', ',' }); configuration.ClientCertificates = SecureTransport.GetCertificatesFromThumbPrintOrFileName(clientThumbprints); configuration.ServerCertificates = SecureTransport.GetCertificatesFromThumbPrintOrFileName(serviceThumbprints); } Trace.TraceInformation( "Connecting to {0}. Using SSL={1} RequestLength={2} MaxConcurrentRequests={3}, SendBufferSize={4}, ReceiveBufferSize={5}", connectionString, configuration.UseSecureConnection, requestLength, maxConcurrentRequests, configuration.SendBufferSize, configuration.ReceiveBufferSize); var connectionAvailable = new ManualResetEvent(false); IPEndPoint[] endpoints = SecureTransport.ParseConnectionString(connectionString); using (var transport = new SecureTransport(configuration)) { transport.StartClient(endpoints); Console.CancelKeyPress += (sender, eventArgs) => { Trace.TraceInformation("Attempting to close client transport"); transport.Close(); }; IConnection currentConnection = null; transport.OnNewConnection = connection => { currentConnection = connection; connectionAvailable.Set(); }; transport.OnConnectionLost = () => { connectionAvailable.Reset(); }; var random = new Random(); var timer = new Stopwatch(); timer.Start(); long requestsSent = 0; byte[] request = new byte[requestLength]; random.NextBytes(request); var sendSemaphore = new SemaphoreSlim(maxConcurrentRequests, maxConcurrentRequests); while (true) { if (!connectionAvailable.WaitOne(waitTimeoutMs)) { Trace.TraceWarning("Connection is not available. retrying..."); continue; } currentConnection.OnPacketReceived = packet => { }; try { if (!sendSemaphore.Wait(waitTimeoutMs)) { Trace.TraceError("Timedout waiting for send semaphore..."); continue; } currentConnection.SendAsync(request).ContinueWith(_ => sendSemaphore.Release()); } catch (IOException ex) { Trace.TraceError("IO Exception: {0}", ex.Message); } Interlocked.Increment(ref requestsSent); if (timer.ElapsedMilliseconds > 5000) { long rate = (requestsSent * 1000) / timer.ElapsedMilliseconds; int inflightCount = maxConcurrentRequests - sendSemaphore.CurrentCount; Trace.TraceInformation($"Send rate={rate} InFlight={inflightCount}"); requestsSent = 0; timer.Restart(); } } } }
/// <summary> /// Entry point /// </summary> /// <param name="args">Arguments provided to the program</param> public static void Main(string[] args) { string testType = "getdata"; string ringMasterAddress = "127.0.0.1:99"; string path = "/Performance"; var assemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location; var builder = new ConfigurationBuilder().SetBasePath(Path.GetDirectoryName(assemblyPath)).AddJsonFile("appSettings.json"); appSettings = builder.Build(); if (args.Length > 0) { testType = args[0].ToLower(); } if (args.Length > 1) { ringMasterAddress = args[1]; } if (args.Length > 2) { path = args[2]; } bool useSecureConnection = false; X509Certificate[] clientCertificates = null; X509Certificate[] acceptedServerCertificates = null; if (bool.Parse(appSettings["SSL.UseSSL"])) { useSecureConnection = true; string[] clientCertificateThumbprints = appSettings["SSL.ClientCerts"].Split(new char[] { ';', ',' }); clientCertificates = RingMasterClient.GetCertificatesFromThumbPrintOrFileName(clientCertificateThumbprints); acceptedServerCertificates = Certificates.GetDecodedCertificates(appSettings["SSL.ServerCerts"]); foreach (var certificate in clientCertificates) { Trace.TraceInformation($"Client certificate: subject={certificate.Subject} thumbprint={certificate.GetCertHashString()}"); } foreach (var certificate in acceptedServerCertificates) { Trace.TraceInformation($"Server certificate: subject={certificate.Subject} thumbprint={certificate.GetCertHashString()}"); } } else { Trace.TraceInformation("Not using SSL"); } var performanceTest = new RingMasterPerformance(); performanceTest.TestPath = path; performanceTest.TimeStreamId = ulong.Parse(appSettings["TimeStream"]); performanceTest.MaxConcurrency = int.Parse(appSettings["MaxConcurrency"]); performanceTest.MaxDataSize = int.Parse(appSettings["MaxDataSize"]); performanceTest.MinDataSize = int.Parse(appSettings["MinDataSize"]); performanceTest.MinChildrenPerNode = int.Parse(appSettings["MinChildrenPerNode"]); performanceTest.MaxChildrenPerNode = int.Parse(appSettings["MaxChildrenPerNode"]); performanceTest.BatchLength = int.Parse(appSettings["BatchLength"]); performanceTest.MaxAllowedCodePoint = int.Parse(appSettings["MaxAllowedCodePoint"]); performanceTest.MaxGetChildrenEnumerationCount = int.Parse(appSettings["MaxGetChildrenEnumerationCount"]); performanceTest.MaxSetOperations = int.Parse(appSettings["MaxSetOperations"]); performanceTest.MaxNodes = int.Parse(appSettings["MaxNodes"]); performanceTest.TestMaxRunTimeInSeconds = int.Parse(appSettings["TestMaxRunTimeInSeconds"]); int requestTimeout = int.Parse(appSettings["RequestTimeout"]); Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); var serverSpec = new RingMasterClient.ServerSpec { Endpoints = SecureTransport.ParseConnectionString(ringMasterAddress), UseSecureConnection = useSecureConnection, }; if (useSecureConnection) { serverSpec.ClientCertificate = clientCertificates[0]; serverSpec.AcceptedServerCertificates = acceptedServerCertificates; serverSpec.MustCheckCertificateRevocation = false; serverSpec.MustCheckCertificateTrustChain = false; } var clientConfiguration = new RingMasterClient.Configuration { DefaultTimeout = TimeSpan.FromMilliseconds(requestTimeout), }; var cancellation = new CancellationTokenSource(); cancellation.CancelAfter(TimeSpan.FromSeconds(performanceTest.TestMaxRunTimeInSeconds)); try { using (var client = new RingMasterClient(serverSpec, clientConfiguration, instrumentation: null, watcher: null, cancellationToken: CancellationToken.None)) using (var ringMaster = client.OpenTimeStream(performanceTest.TimeStreamId)) { if (testType == "setdata") { performanceTest.SetDataPerformanceTest(ringMaster).Wait(); } else if (testType == "create") { int numNodes = 500000; if (args.Length > 3) { numNodes = int.Parse(args[3]); } performanceTest.CreatePerformanceTest(ringMaster, numNodes); } else if (testType == "createflat") { int numNodes = 1000000; if (args.Length > 3) { numNodes = int.Parse(args[3]); } performanceTest.CreateFlatPerformanceTest(ringMaster, numNodes); } else if (testType == "getchildren") { int maxChildren = 1000; if (args.Length > 3) { maxChildren = int.Parse(args[3]); } performanceTest.GetChildrenPerformanceTest(ringMaster, maxChildren); } else if (testType == "delete") { performanceTest.DeletePerformanceTest(ringMaster).Wait(); } else if (testType == "scheduleddelete") { performanceTest.ScheduledDeletePerformanceTest(ringMaster); } else if (testType == "connect") { int numConnections = 100; if (args.Length > 3) { numConnections = int.Parse(args[3]); } var configuration = new SecureTransport.Configuration { UseSecureConnection = useSecureConnection, ClientCertificates = clientCertificates, ServerCertificates = acceptedServerCertificates, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, }; IPEndPoint[] endpoints = SecureTransport.ParseConnectionString(ringMasterAddress); performanceTest.ConnectPerformanceTest(configuration, endpoints, numConnections); } else if (testType == "exists") { performanceTest.ExistsPerformanceTest(ringMaster).Wait(); } else if (testType == "watchers") { int maxWatchers = 1000; if (args.Length > 3) { maxWatchers = int.Parse(args[3]); } performanceTest.WatcherPerformanceTest(ringMaster, maxWatchers, cancellation).Wait(); } else { performanceTest.GetDataPerformanceTest(ringMaster, cancellation).Wait(); } } } catch (OperationCanceledException) { } catch (AggregateException ex) { if (!ex.Flatten().InnerExceptions.Any(e => e is OperationCanceledException)) { throw ex; } } }
public void TestSecureTransport() { String methodName = "methodOne"; String arg0 = "arg0"; String arg1 = "arg1"; TestWebServiceProxy testProxy = new TestWebServiceProxy(); ITransportProxy proxy = testProxy; FolaighKeyStore keyStore = new FolaighKeyStore(KEYSTORE, "bird8top".ToCharArray()); RSACipher encryptorVerifier = new RSACipher( keyStore, "countyKey", false); RSACipher signerDecryptor = new RSACipher( keyStore, "stateKey", true); SecureTransport transport = new SecureTransport( proxy, encryptorVerifier, signerDecryptor); // Test for the proxy method String message = "message"; String signature = "signature"; String aesKey = "key"; String iv = "iv"; String senderAlias = "alias"; String retval = proxy.send(message, signature, aesKey, iv, senderAlias); String returnVal = transport.send(methodName, new String[] { arg0, arg1 }); // First, just check to see if something got to the proxy. Assert.IsNotNull(returnVal); Assert.IsNotNull(testProxy.m_aesKey); Assert.IsNotNull(testProxy.m_iv); Assert.IsNotNull(testProxy.m_message); Assert.IsNotNull(testProxy.m_senderAlias); Assert.IsNotNull(testProxy.m_signature); Console.WriteLine("Encrypted AES Key:" + testProxy.m_aesKey); Console.WriteLine("Encrypted IV:" + testProxy.m_iv); Console.WriteLine("Encrypted Message:" + testProxy.m_message); Console.WriteLine("Sender Alias:" + testProxy.m_senderAlias); Console.WriteLine("Signature:" + testProxy.m_signature); // Decrypt the AES Key RSACipher testDecryptor = new RSACipher( keyStore, "countyKey", true); byte[] testKey = testDecryptor.decrypt(Convert.FromBase64String(testProxy.m_aesKey)); byte[] testIV = testDecryptor.decrypt(Convert.FromBase64String(testProxy.m_iv)); Console.WriteLine("Decrypted Key:" + Convert.ToBase64String(testKey)); Console.WriteLine("Decrypted IV:" + Convert.ToBase64String(testIV)); AESCipher cipher = new AESCipher(testKey, testIV); // Independently encrypt the message and make sure they're the same MethodInfo mInfo = new MethodInfo(methodName, new String[] { arg0, arg1 }); String xml = mInfo.encode(); String testEncryptedMessage = Convert.ToBase64String(cipher.encrypt(xml)); Assert.AreEqual(xml, cipher.decrypt(Convert.FromBase64String(testEncryptedMessage))); Assert.AreEqual(testEncryptedMessage, testProxy.m_message); string decryptedMessage = cipher.decrypt(Convert.FromBase64String(testProxy.m_message)); string expectedMessage = expectedMethodInfo.encode(); Assert.AreEqual(expectedMessage, decryptedMessage); }
/// <summary> /// Gets a list of <see cref="X509Certificate"/>s that corresponds to the given thumbprint or file paths. /// </summary> /// <param name="paths">List of thumbprint or file paths</param> /// <returns> A list of <see cref="X509Certificate"/>s that correspond to the given paths</returns> public static X509Certificate[] GetCertificatesFromThumbPrintOrFileName(string[] paths) { return(SecureTransport.GetCertificatesFromThumbPrintOrFileName(paths)); }
public RingMasterClient( ServerSpec serverSpec, Configuration configuration, IRingMasterClientInstrumentation instrumentation, IWatcher watcher, CancellationToken cancellationToken) { if (serverSpec == null) { throw new ArgumentNullException(nameof(serverSpec)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } IPEndPoint[] endpoints = serverSpec.Endpoints; if ((endpoints == null) || (endpoints.Length == 0)) { throw new ArgumentException("Endpoints were not specified"); } if (watcher != null) { this.SetWatcher(watcher); } SecureTransport secureTransport = null; try { var transportConfiguration = new SecureTransport.Configuration(); transportConfiguration.UseSecureConnection = serverSpec.UseSecureConnection; transportConfiguration.ClientCertificates = new X509Certificate[] { serverSpec.ClientCertificate }; transportConfiguration.ServerCertificates = serverSpec.AcceptedServerCertificates; transportConfiguration.RemoteCertificateValidationCallback = serverSpec.ServerCertificateValidationCallback; transportConfiguration.LocalCertificateSelectionCallback = serverSpec.ClientCertificationSelectionCallback; transportConfiguration.MustCheckCertificateRevocation = serverSpec.MustCheckCertificateRevocation; transportConfiguration.MustCheckCertificateTrustChain = serverSpec.MustCheckCertificateTrustChain; transportConfiguration.CommunicationProtocolVersion = serverSpec.CommunicationProtocolVersion; transportConfiguration.SendBufferSize = configuration.BufferSize; transportConfiguration.ReceiveBufferSize = configuration.BufferSize; transportConfiguration.SendQueueLength = configuration.RequestQueueLength; transportConfiguration.AuthAsClient = true; List <SecureTransport.SubjectRuleValidation> subjectRules = new List <SecureTransport.SubjectRuleValidation>(); if (!string.IsNullOrWhiteSpace(serverSpec.CertValidationASubject) && serverSpec.CertValidationASigningThumbprints != null) { SecureTransport.SubjectValidation subjectA = new SecureTransport.SubjectValidation() { CertificateSubject = serverSpec.CertValidationASubject, SigningCertThumbprints = serverSpec.CertValidationASigningThumbprints, }; subjectRules.Add(new SecureTransport.SubjectRuleValidation(CertificateRules.AbstractCertificateRule.RoleToApply.ServerCert, subjectA)); } if (!string.IsNullOrWhiteSpace(serverSpec.CertValidationBSubject) && serverSpec.CertValidationBSigningThumbprints != null) { SecureTransport.SubjectValidation subjectB = new SecureTransport.SubjectValidation() { CertificateSubject = serverSpec.CertValidationBSubject, SigningCertThumbprints = serverSpec.CertValidationBSigningThumbprints, }; subjectRules.Add(new SecureTransport.SubjectRuleValidation(CertificateRules.AbstractCertificateRule.RoleToApply.ServerCert, subjectB)); } if (subjectRules != null && subjectRules.Count > 0) { transportConfiguration.SubjectValidations = subjectRules; } secureTransport = new SecureTransport(transportConfiguration, instrumentation: null, cancellationToken: cancellationToken); ICommunicationProtocol protocol = new RingMasterCommunicationProtocol(); var handlerConfiguration = new RingMasterRequestHandler.Configuration(); handlerConfiguration.DefaultTimeout = configuration.DefaultTimeout; handlerConfiguration.HeartBeatInterval = configuration.HeartBeatInterval; handlerConfiguration.RequestQueueLength = configuration.RequestQueueLength; handlerConfiguration.RequireLockForReadOnlyOperations = configuration.RequireLockForReadOnlyOperations; handlerConfiguration.MustTransparentlyForwardRequests = configuration.MustTransparentlyForwardRequests; var handlerInstrumentation = new RingMasterRequestHandlerInstrumentation(instrumentation); this.requestHandler = new RingMasterRequestHandler( handlerConfiguration, handlerInstrumentation, protocol, secureTransport, cancellationToken); foreach (var endpoint in endpoints) { RingMasterClientEventSource.Log.Start(endpoint.ToString()); } secureTransport.StartClient(endpoints); secureTransport = null; } finally { if (secureTransport != null) { secureTransport.Dispose(); } } }
private static void SecureTransportInternal(Action <string> log, string testCaseName, int numberOfClients) { var packetCount = 0; log($"Starting {testCaseName} ..."); SecureTransport server = null; SecureTransport[] clients = new SecureTransport[0]; try { // Start the service server = new SecureTransport(new SecureTransport.Configuration { UseSecureConnection = false, IsClientCertificateRequired = false, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, }); var serverSendTask = Task.CompletedTask; server.OnNewConnection = connection => { connection.OnPacketReceived = packet => { Interlocked.Increment(ref packetCount); serverSendTask.GetAwaiter().GetResult(); serverSendTask = connection.SendAsync(packet); }; Trace.TraceInformation("Server accepted a new connection: {0}", connection.RemoteIdentity); }; server.StartServer(Port); // Start the client clients = Enumerable.Range(0, numberOfClients).Select( _ => new SecureTransport(new SecureTransport.Configuration { UseSecureConnection = false, IsClientCertificateRequired = false, CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion, })) .ToArray(); Parallel.ForEach( clients, client => client.OnNewConnection = connection => { var clientSendTask = Task.CompletedTask; connection.OnPacketReceived = packet => { clientSendTask.GetAwaiter().GetResult(); clientSendTask = connection.SendAsync(packet); }; clientSendTask = connection.SendAsync(new byte[PacketLength]); }); Parallel.ForEach( clients, client => client.StartClient(new IPEndPoint(IPAddress.Loopback, Port))); log($" Warming up for {WarmupMilliSeconds / 1000} seconds"); Thread.Sleep(WarmupMilliSeconds); log($" Start measuring for {MeasureMilliSeconds} seconds"); var sw = new Stopwatch(); int gen0 = GC.CollectionCount(0), gen1 = GC.CollectionCount(1), gen2 = GC.CollectionCount(2); sw.Start(); Interlocked.Exchange(ref packetCount, 0); for (int i = 0; i < MeasureMilliSeconds / PrintStatusInterval; i++) { Thread.Sleep(PrintStatusInterval); log($" {DateTime.Now.ToString()} count={packetCount}"); } sw.Stop(); var totalCount = packetCount; var rate = totalCount / sw.Elapsed.TotalSeconds; Parallel.ForEach(clients, client => client.Close()); server.Close(); log($"{testCaseName}: {totalCount} in {sw.Elapsed} with {numberOfClients} clients. QPS={rate}"); log($" Gen0={GC.CollectionCount(0) - gen0} Gen1={GC.CollectionCount(1) - gen1} Gen2={GC.CollectionCount(2) - gen2}\n"); log(string.Empty); } finally { server?.Dispose(); Parallel.ForEach(clients, client => client.Dispose()); } }
/// <summary> /// Defines the entry point of the application. /// </summary> /// <param name="args">Command line arguments</param> public static void Main(string[] args) { Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); if (args == null || args.Length < 1) { Trace.TraceError("USAGE: SecureTransportServiceTool.exe <port>"); return; } int port = int.Parse(args[0]); var configuration = new SecureTransport.Configuration(); var path = System.Reflection.Assembly.GetExecutingAssembly().Location; var builder = new ConfigurationBuilder().SetBasePath(Path.GetDirectoryName(path)).AddJsonFile("appSettings.json"); IConfiguration appSettings = builder.Build(); int maxConcurrentRequests = int.Parse(appSettings["MaxConcurrentRequests"]); configuration.UseSecureConnection = bool.Parse(appSettings["SSL.UseSSL"]); configuration.SendBufferSize = int.Parse(appSettings["SendBufferSize"]); configuration.ReceiveBufferSize = int.Parse(appSettings["ReceiveBufferSize"]); if (configuration.UseSecureConnection) { string[] clientThumbprints = appSettings["SSL.ClientCerts"].Split(new char[] { ';', ',' }); string[] serviceThumbprints = appSettings["SSL.ServerCerts"].Split(new char[] { ';', ',' }); configuration.ClientCertificates = SecureTransport.GetCertificatesFromThumbPrintOrFileName(clientThumbprints); configuration.ServerCertificates = SecureTransport.GetCertificatesFromThumbPrintOrFileName(serviceThumbprints); } Trace.TraceInformation( "Listening on port {0}. Using SSL={1}, MaxConcurentRequests={2}, SendBufferSize={3}, ReceiveBufferSize={4}", port, configuration.UseSecureConnection, maxConcurrentRequests, configuration.SendBufferSize, configuration.ReceiveBufferSize); using (var transport = new SecureTransport(configuration)) { var timer = Stopwatch.StartNew(); long activeConnections = 0; long packetsReceived = 0; Task serverTask = transport.StartServer(port); Console.CancelKeyPress += (sender, eventArgs) => { Trace.TraceInformation("Attempting to close server transport"); transport.Close(); }; var semaphore = new SemaphoreSlim(maxConcurrentRequests, maxConcurrentRequests); transport.OnNewConnection = connection => { Trace.TraceInformation("Connection Established with {0}", connection.RemoteEndPoint); Interlocked.Increment(ref activeConnections); connection.OnPacketReceived = packet => { semaphore.Wait(); Interlocked.Increment(ref packetsReceived); connection.SendAsync(packet).ContinueWith(_ => semaphore.Release()); }; connection.OnConnectionLost = () => { Trace.TraceInformation("Connection with {0} was lost", connection.RemoteEndPoint); Interlocked.Decrement(ref activeConnections); }; }; while (!serverTask.Wait(5000)) { timer.Stop(); long rate = (long)(packetsReceived * 1000) / timer.ElapsedMilliseconds; int inflightCount = maxConcurrentRequests - semaphore.CurrentCount; Trace.TraceInformation($"ActiveConnections={activeConnections}, RequestRate {rate} InFlight count={inflightCount}"); packetsReceived = 0; timer.Restart(); } } }