refactored server for dependancy injection, combined tests to run correctly in a multithreaded build

This commit is contained in:
Aidan Hahn 2019-05-21 15:04:18 -07:00
parent c599902ad5
commit ea3f84b830
No known key found for this signature in database
GPG key ID: 327711E983899316
3 changed files with 95 additions and 107 deletions

View file

@ -20,6 +20,7 @@ plugins {
id 'java' id 'java'
id 'com.google.protobuf' version '0.8.8' id 'com.google.protobuf' version '0.8.8'
id 'application' id 'application'
id 'com.adarshr.test-logger' version '1.6.0'
} }
def grpcVersion = '1.20.0' def grpcVersion = '1.20.0'
@ -49,6 +50,25 @@ dependencies {
compile 'io.netty:netty-tcnative-boringssl-static:2.0.22.Final' 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 // Define the main class for the application
mainClassName = 'JobServ.JobServClient' mainClassName = 'JobServ.JobServClient'

View file

@ -32,25 +32,17 @@ public class JobServServer {
private static final Logger logger = Logger.getLogger(JobServServer.class.getName()); private static final Logger logger = Logger.getLogger(JobServServer.class.getName());
private Server server; private Server server;
private final int port;
private final SslContext ssl;
/* /*
* Constructor * Constructor
* Sets port and builds sslContext * builds server object
*/ */
public JobServServer(int port, public JobServServer(SslContext ssl, int port) throws IOException {
String serverCert, this.server = NettyServerBuilder.forPort(port)
String privateKey, .addService(new ShellServerService())
String trustStore) throws SSLException { .sslContext(ssl)
this.port = port; .build()
SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(new File(serverCert), new File(privateKey)); .start();
// Mutual TLS trust store and require client auth
sslContextBuilder.trustManager(new File(trustStore));
sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
this.ssl = GrpcSslContexts.configure(sslContextBuilder).build();
} }
/* /*
@ -59,11 +51,7 @@ public class JobServServer {
*/ */
private void start() throws IOException { private void start() throws IOException {
// TODO: this should be passed in from a configuration manager // TODO: this should be passed in from a configuration manager
server = NettyServerBuilder.forPort(port) server.start();
.addService(new ShellServerService())
.sslContext(this.ssl)
.build()
.start();
logger.info("Server initialized!"); logger.info("Server initialized!");
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@ -112,7 +100,14 @@ public class JobServServer {
JobServServer server; JobServServer server;
try { 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) { } catch (InputMismatchException e) {
System.out.println("Invalid port!"); System.out.println("Invalid port!");
@ -121,9 +116,12 @@ public class JobServServer {
} catch (SSLException e) { } catch (SSLException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
return; return;
} catch (IOException e) {
System.out.println(e.getMessage());
return;
} }
server.start();
server.blockUntilShutdown(); server.blockUntilShutdown();
} }
} }

View file

@ -10,6 +10,7 @@ package JobServ;
import java.io.File; import java.io.File;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import java.io.IOException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalAnswers.delegatesTo; import static org.mockito.AdditionalAnswers.delegatesTo;
@ -17,8 +18,9 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import io.grpc.ManagedChannel; import io.grpc.ManagedChannel;
import io.grpc.inprocess.InProcessChannelBuilder; import io.grpc.netty.NettyChannelBuilder;
import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.StatusRuntimeException;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import io.grpc.testing.GrpcCleanupRule; import io.grpc.testing.GrpcCleanupRule;
import io.grpc.netty.GrpcSslContexts; 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.SslContextBuilder;
import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.SslProvider;
import org.junit.Before; import org.junit.BeforeClass;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -46,43 +48,39 @@ import org.mockito.ArgumentMatchers;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class JobServerAuthenticationTest { public class JobServerAuthenticationTest {
private final String projectRoot = "";
// Authorized client key/cert/ca // Authorized client key/cert/ca
private final String clientCa = "resources/client/ca.crt"; private final String clientCa = projectRoot + "resources/client/ca.crt";
private final String clientKey = "resources/client/private.pem"; private final String clientKey = projectRoot + "resources/client/private.pem";
private final String clientCert = "resources/client/client.crt"; private final String clientCert = projectRoot + "resources/client/client.crt";
// Authorized server key/cert/ca // Authorized server key/cert/ca
private final String serverCa = "resources/server/ca.crt"; private final String serverCa = projectRoot + "resources/server/ca.crt";
private final String serverKey = "resources/server/private.pem"; private final String serverKey = projectRoot + "resources/server/private.pem";
private final String serverCert = "resources/server/server.crt"; private final String serverCert = projectRoot + "resources/server/server.crt";
// controlled failure key/cert/ca // controlled failure key/cert/ca
private final String badCa = "resources/test/ca.crt"; private final String badCa = projectRoot + "resources/test/ca.crt";
private final String badKey = "resources/test/private.pem"; private final String badKey = projectRoot + "resources/test/private.pem";
private final String badCert = "resources/test/test.crt"; private final String badCert = projectRoot + "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() {}));
// badClient uses unauthorized certs // badClient uses unauthorized certs
private JobServClient goodClient; private JobServClient goodClient;
private JobServClient badClient; private JobServClient badClient;
private JobServServer server;
// was setUp able to use SSL Certs // was setUp able to use SSL Certs
private Boolean serverSslInitialized; private Boolean serverSslInitialized = true;
private Boolean clientSslInitialized; private Boolean clientSslInitialized = true;
/* /*
* setUp() * test constructor
* generates both clients and the server * generates both clients and the server
*/ */
@Before public JobServerAuthenticationTest() throws Exception {
public void setUp() throws Exception {
String serverName = InProcessServerBuilder.generateName(); System.out.println("Ctrl print");
try { try {
// generate SSL contexts // generate SSL contexts
@ -91,42 +89,38 @@ public class JobServerAuthenticationTest {
serverContextBuilder.trustManager(new File(clientCa)); serverContextBuilder.trustManager(new File(clientCa));
serverContextBuilder.clientAuth(ClientAuth.REQUIRE); serverContextBuilder.clientAuth(ClientAuth.REQUIRE);
grpcCleanup.register(InProcessServerBuilder.forName(serverName) this.server = new JobServServer(GrpcSslContexts.configure(serverContextBuilder).build(), 8448);
.sslContext(serverContextBuilder.build())
.directExecutor()
.addService(this.serviceImpl)
.build().start());
this.serverSslInitialized = true; this.serverSslInitialized = true;
} catch (SSLException e) { } catch (SSLException e) {
// One of the certs or keys was bad, ssl cannot be used
this.serverSslInitialized = false; this.serverSslInitialized = false;
grpcCleanup.register(InProcessServerBuilder.forName(serverName) System.err.println(e.getMessage());
.directExecutor()
.addService(this.serviceImpl).build().start()); } catch (IOException e) {
this.serverSslInitialized = false;
System.err.println(e.getMessage());
} }
// generate ssl for clients // generate ssl for clients
if (this.serverSslInitialized) { if (this.serverSslInitialized) {
try { try {
SslContextBuilder goodClientBuilder = SslContextBuilder.forClient(); SslContextBuilder goodClientBuilder = GrpcSslContexts.forClient();
goodClientBuilder.trustManager(new File(serverCa)); goodClientBuilder.trustManager(new File(serverCa));
goodClientBuilder.keyManager(new File(clientCert), new File(clientKey)); goodClientBuilder.keyManager(new File(clientCert), new File(clientKey));
SslContextBuilder badClientBuilder = SslContextBuilder.forClient(); SslContextBuilder badClientBuilder = GrpcSslContexts.forClient();
badClientBuilder.trustManager(new File(serverCa)); badClientBuilder.trustManager(new File(serverCa));
badClientBuilder.keyManager(new File(badCert), new File(badKey)); badClientBuilder.keyManager(new File(badCert), new File(badKey));
ManagedChannel goodChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) ManagedChannel goodChannel = NettyChannelBuilder.forAddress("localhost", 8448)
.sslContext(goodClientBuilder.build()) .sslContext(goodClientBuilder.build())
.directExecutor() .directExecutor()
.build()); .build();
ManagedChannel badChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) ManagedChannel badChannel = NettyChannelBuilder.forAddress("localhost", 8448)
.sslContext(badClientBuilder.build()) .sslContext(badClientBuilder.build())
.directExecutor() .directExecutor()
.build()); .build();
goodClient = new JobServClient(goodChannel); goodClient = new JobServClient(goodChannel);
badClient = new JobServClient(badChannel); badClient = new JobServClient(badChannel);
@ -134,53 +128,29 @@ public class JobServerAuthenticationTest {
} catch (SSLException e) { } catch (SSLException e) {
this.clientSslInitialized = false; this.clientSslInitialized = false;
ManagedChannel nonSslChannel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName) System.err.println(e.getMessage());
.directExecutor()
.build());
goodClient = new JobServClient(nonSslChannel);
badClient = null; //
} }
} else {
this.clientSslInitialized = false;
} }
} }
/* /*
* Server TLS Test * TLS Cert Auth Test
* fails if server SslContext generation threw an SSLException * 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 @Test
public void serverTlsTest() { public void certificateAuthenticationTest() {
assertEquals(this.serverSslInitialized, true); assertEquals(true, serverSslInitialized);
} assertEquals(true, clientSslInitialized);
/*
* 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);
int result = badClient.sendNewJobMessage("test command"); int result = badClient.sendNewJobMessage("test command");
assertEquals(result, -2); assertEquals(-2, result);
}
/* result = goodClient.sendNewJobMessage("test command");
* 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");
Boolean assertCondition = result == -2; Boolean assertCondition = result == -2;
assertEquals(result, false); assertEquals(assertCondition, false);
} }
} }