From ea3f84b830f38c7c3f005c69853a4c951ee868bf Mon Sep 17 00:00:00 2001 From: Aidan Hahn Date: Tue, 21 May 2019 15:04:18 -0700 Subject: [PATCH] refactored server for dependancy injection, combined tests to run correctly in a multithreaded build --- build.gradle | 22 ++- src/main/java/JobServ/JobServServer.java | 44 +++--- .../JobServ/JobServerAuthenticationTest.java | 136 +++++++----------- 3 files changed, 95 insertions(+), 107 deletions(-) diff --git a/build.gradle b/build.gradle index 7dae974..ba5b8d2 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ plugins { id 'java' id 'com.google.protobuf' version '0.8.8' id 'application' + id 'com.adarshr.test-logger' version '1.6.0' } def grpcVersion = '1.20.0' @@ -49,6 +50,25 @@ dependencies { compile 'io.netty:netty-tcnative-boringssl-static:2.0.22.Final' } +test { + testLogging.showStandardStreams = true + testLogging.exceptionFormat = 'full' +} + +testlogger { + theme 'standard' + showExceptions true + slowThreshold 2000 + showSummary true + showPassed true + showSkipped true + showFailed true + showStandardStreams false + showPassedStandardStreams true + showSkippedStandardStreams true + showFailedStandardStreams true +} + // Define the main class for the application mainClassName = 'JobServ.JobServClient' @@ -88,4 +108,4 @@ applicationDistribution.into('bin') { from(Server) from(Client) fileMode = 0755 -} \ No newline at end of file +} diff --git a/src/main/java/JobServ/JobServServer.java b/src/main/java/JobServ/JobServServer.java index 483e865..07e41fa 100644 --- a/src/main/java/JobServ/JobServServer.java +++ b/src/main/java/JobServ/JobServServer.java @@ -32,25 +32,17 @@ public class JobServServer { private static final Logger logger = Logger.getLogger(JobServServer.class.getName()); private Server server; - private final int port; - private final SslContext ssl; /* * Constructor - * Sets port and builds sslContext + * builds server object */ - public JobServServer(int port, - String serverCert, - String privateKey, - String trustStore) throws SSLException { - this.port = port; - SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(new File(serverCert), new File(privateKey)); - - // Mutual TLS trust store and require client auth - sslContextBuilder.trustManager(new File(trustStore)); - sslContextBuilder.clientAuth(ClientAuth.REQUIRE); - - this.ssl = GrpcSslContexts.configure(sslContextBuilder).build(); + public JobServServer(SslContext ssl, int port) throws IOException { + this.server = NettyServerBuilder.forPort(port) + .addService(new ShellServerService()) + .sslContext(ssl) + .build() + .start(); } /* @@ -59,11 +51,7 @@ public class JobServServer { */ private void start() throws IOException { // TODO: this should be passed in from a configuration manager - server = NettyServerBuilder.forPort(port) - .addService(new ShellServerService()) - .sslContext(this.ssl) - .build() - .start(); + server.start(); logger.info("Server initialized!"); Runtime.getRuntime().addShutdownHook(new Thread() { @@ -112,7 +100,14 @@ public class JobServServer { JobServServer server; try { - server = new JobServServer(Integer.parseInt(args[0]), args[1], args[2], args[3]); + SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(new File(args[1]), new File(args[2])); + + // Mutual TLS trust store and require client auth + sslContextBuilder.trustManager(new File(args[3])); + sslContextBuilder.clientAuth(ClientAuth.REQUIRE); + + server = new JobServServer(GrpcSslContexts.configure(sslContextBuilder).build(), + Integer.parseInt(args[0])); } catch (InputMismatchException e) { System.out.println("Invalid port!"); @@ -121,9 +116,12 @@ public class JobServServer { } catch (SSLException e) { System.out.println(e.getMessage()); return; - } + + } catch (IOException e) { + System.out.println(e.getMessage()); + return; + } - server.start(); server.blockUntilShutdown(); } } diff --git a/src/test/java/JobServ/JobServerAuthenticationTest.java b/src/test/java/JobServ/JobServerAuthenticationTest.java index 2173801..e332cfe 100644 --- a/src/test/java/JobServ/JobServerAuthenticationTest.java +++ b/src/test/java/JobServ/JobServerAuthenticationTest.java @@ -10,6 +10,7 @@ package JobServ; import java.io.File; import javax.net.ssl.SSLException; +import java.io.IOException; import static org.junit.Assert.assertEquals; import static org.mockito.AdditionalAnswers.delegatesTo; @@ -17,8 +18,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import io.grpc.ManagedChannel; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.netty.NettyChannelBuilder; +import io.grpc.StatusRuntimeException; +import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver; import io.grpc.testing.GrpcCleanupRule; import io.grpc.netty.GrpcSslContexts; @@ -28,7 +30,7 @@ import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,44 +48,40 @@ import org.mockito.ArgumentMatchers; @RunWith(JUnit4.class) public class JobServerAuthenticationTest { + private final String projectRoot = ""; + // Authorized client key/cert/ca - private final String clientCa = "resources/client/ca.crt"; - private final String clientKey = "resources/client/private.pem"; - private final String clientCert = "resources/client/client.crt"; + private final String clientCa = projectRoot + "resources/client/ca.crt"; + private final String clientKey = projectRoot + "resources/client/private.pem"; + private final String clientCert = projectRoot + "resources/client/client.crt"; // Authorized server key/cert/ca - private final String serverCa = "resources/server/ca.crt"; - private final String serverKey = "resources/server/private.pem"; - private final String serverCert = "resources/server/server.crt"; + private final String serverCa = projectRoot + "resources/server/ca.crt"; + private final String serverKey = projectRoot + "resources/server/private.pem"; + private final String serverCert = projectRoot + "resources/server/server.crt"; // controlled failure key/cert/ca - private final String badCa = "resources/test/ca.crt"; - private final String badKey = "resources/test/private.pem"; - private final String badCert = "resources/test/test.crt"; - - // Automates (graceful) shutdown at end of tests - @Rule - public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); - - private final ShellServerGrpc.ShellServerImplBase serviceImpl= mock(ShellServerGrpc.ShellServerImplBase.class, - delegatesTo(new ShellServerGrpc.ShellServerImplBase() {})); + private final String badCa = projectRoot + "resources/test/ca.crt"; + private final String badKey = projectRoot + "resources/test/private.pem"; + private final String badCert = projectRoot + "resources/test/test.crt"; // badClient uses unauthorized certs private JobServClient goodClient; private JobServClient badClient; + private JobServServer server; // was setUp able to use SSL Certs - private Boolean serverSslInitialized; - private Boolean clientSslInitialized; + private Boolean serverSslInitialized = true; + private Boolean clientSslInitialized = true; /* - * setUp() + * test constructor * generates both clients and the server */ - @Before - public void setUp() throws Exception { - String serverName = InProcessServerBuilder.generateName(); + public JobServerAuthenticationTest() throws Exception { + System.out.println("Ctrl print"); + try { // generate SSL contexts SslContextBuilder serverContextBuilder = SslContextBuilder.forServer(new File(serverCert), @@ -91,42 +89,38 @@ public class JobServerAuthenticationTest { serverContextBuilder.trustManager(new File(clientCa)); serverContextBuilder.clientAuth(ClientAuth.REQUIRE); - grpcCleanup.register(InProcessServerBuilder.forName(serverName) - .sslContext(serverContextBuilder.build()) - .directExecutor() - .addService(this.serviceImpl) - .build().start()); - + this.server = new JobServServer(GrpcSslContexts.configure(serverContextBuilder).build(), 8448); this.serverSslInitialized = true; } catch (SSLException e) { - // One of the certs or keys was bad, ssl cannot be used this.serverSslInitialized = false; - grpcCleanup.register(InProcessServerBuilder.forName(serverName) - .directExecutor() - .addService(this.serviceImpl).build().start()); + System.err.println(e.getMessage()); + + } catch (IOException e) { + this.serverSslInitialized = false; + System.err.println(e.getMessage()); } // generate ssl for clients if (this.serverSslInitialized) { try { - SslContextBuilder goodClientBuilder = SslContextBuilder.forClient(); + SslContextBuilder goodClientBuilder = GrpcSslContexts.forClient(); goodClientBuilder.trustManager(new File(serverCa)); goodClientBuilder.keyManager(new File(clientCert), new File(clientKey)); - SslContextBuilder badClientBuilder = SslContextBuilder.forClient(); + SslContextBuilder badClientBuilder = GrpcSslContexts.forClient(); badClientBuilder.trustManager(new File(serverCa)); badClientBuilder.keyManager(new File(badCert), new File(badKey)); - ManagedChannel goodChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) - .sslContext(goodClientBuilder.build()) - .directExecutor() - .build()); + ManagedChannel goodChannel = NettyChannelBuilder.forAddress("localhost", 8448) + .sslContext(goodClientBuilder.build()) + .directExecutor() + .build(); - ManagedChannel badChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) - .sslContext(badClientBuilder.build()) - .directExecutor() - .build()); + ManagedChannel badChannel = NettyChannelBuilder.forAddress("localhost", 8448) + .sslContext(badClientBuilder.build()) + .directExecutor() + .build(); goodClient = new JobServClient(goodChannel); badClient = new JobServClient(badChannel); @@ -134,53 +128,29 @@ public class JobServerAuthenticationTest { } catch (SSLException e) { this.clientSslInitialized = false; - ManagedChannel nonSslChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) - .directExecutor() - .build()); - goodClient = new JobServClient(nonSslChannel); - badClient = null; // + System.err.println(e.getMessage()); } + + } else { + this.clientSslInitialized = false; } } /* - * Server TLS Test - * fails if server SslContext generation threw an SSLException + * TLS Cert Auth Test + * this needed to be one test because running multiple tests at the same time + * fails as the server tries to rebind to the same port. */ @Test - public void serverTlsTest() { - assertEquals(this.serverSslInitialized, true); - } - - /* - * Client TLS Test - * fails if client SslContext generation threw an SSL Exception - */ - @Test - public void clientTlsTest() { - assertEquals(this.clientSslInitialized, true); - } - - /* - * TLS Cert Auth Negative Test - * fails if badClient can successfully make requests of the server - */ - @Test - public void certAuthNegTest() { - assertEquals(clientSslInitialized, true); + public void certificateAuthenticationTest() { + assertEquals(true, serverSslInitialized); + assertEquals(true, clientSslInitialized); + int result = badClient.sendNewJobMessage("test command"); - assertEquals(result, -2); - } + assertEquals(-2, result); - /* - * TLS Cert Auth Positive Test - * fails if goodClient cannot make requests of the server - */ - @Test - public void certAuthPosTest() { - assertEquals(clientSslInitialized, true); - int result = goodClient.sendNewJobMessage("test command"); + result = goodClient.sendNewJobMessage("test command"); Boolean assertCondition = result == -2; - assertEquals(result, false); + assertEquals(assertCondition, false); } }