1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.examples.helloworldtls; 18 19 import io.grpc.Server; 20 import io.grpc.examples.helloworld.GreeterGrpc; 21 import io.grpc.examples.helloworld.HelloReply; 22 import io.grpc.examples.helloworld.HelloRequest; 23 import io.grpc.netty.GrpcSslContexts; 24 import io.grpc.netty.NettyServerBuilder; 25 import io.grpc.stub.StreamObserver; 26 import io.netty.handler.ssl.ClientAuth; 27 import io.netty.handler.ssl.SslContextBuilder; 28 import io.netty.handler.ssl.SslProvider; 29 30 import java.io.File; 31 import java.io.IOException; 32 import java.net.InetSocketAddress; 33 import java.util.logging.Logger; 34 35 /** 36 * Server that manages startup/shutdown of a {@code Greeter} server with TLS enabled. 37 */ 38 public class HelloWorldServerTls { 39 private static final Logger logger = Logger.getLogger(HelloWorldServerTls.class.getName()); 40 41 private Server server; 42 43 private final String host; 44 private final int port; 45 private final String certChainFilePath; 46 private final String privateKeyFilePath; 47 private final String trustCertCollectionFilePath; 48 HelloWorldServerTls(String host, int port, String certChainFilePath, String privateKeyFilePath, String trustCertCollectionFilePath)49 public HelloWorldServerTls(String host, 50 int port, 51 String certChainFilePath, 52 String privateKeyFilePath, 53 String trustCertCollectionFilePath) { 54 this.host = host; 55 this.port = port; 56 this.certChainFilePath = certChainFilePath; 57 this.privateKeyFilePath = privateKeyFilePath; 58 this.trustCertCollectionFilePath = trustCertCollectionFilePath; 59 } 60 getSslContextBuilder()61 private SslContextBuilder getSslContextBuilder() { 62 SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(new File(certChainFilePath), 63 new File(privateKeyFilePath)); 64 if (trustCertCollectionFilePath != null) { 65 sslClientContextBuilder.trustManager(new File(trustCertCollectionFilePath)); 66 sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE); 67 } 68 return GrpcSslContexts.configure(sslClientContextBuilder, 69 SslProvider.OPENSSL); 70 } 71 start()72 private void start() throws IOException { 73 server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)) 74 .addService(new GreeterImpl()) 75 .sslContext(getSslContextBuilder().build()) 76 .build() 77 .start(); 78 logger.info("Server started, listening on " + port); 79 Runtime.getRuntime().addShutdownHook(new Thread() { 80 @Override 81 public void run() { 82 // Use stderr here since the logger may have been reset by its JVM shutdown hook. 83 System.err.println("*** shutting down gRPC server since JVM is shutting down"); 84 HelloWorldServerTls.this.stop(); 85 System.err.println("*** server shut down"); 86 } 87 }); 88 } 89 stop()90 private void stop() { 91 if (server != null) { 92 server.shutdown(); 93 } 94 } 95 96 /** 97 * Await termination on the main thread since the grpc library uses daemon threads. 98 */ blockUntilShutdown()99 private void blockUntilShutdown() throws InterruptedException { 100 if (server != null) { 101 server.awaitTermination(); 102 } 103 } 104 105 /** 106 * Main launches the server from the command line. 107 */ main(String[] args)108 public static void main(String[] args) throws IOException, InterruptedException { 109 110 if (args.length < 4 || args.length > 5) { 111 System.out.println( 112 "USAGE: HelloWorldServerTls host port certChainFilePath privateKeyFilePath " + 113 "[trustCertCollectionFilePath]\n Note: You only need to supply trustCertCollectionFilePath if you want " + 114 "to enable Mutual TLS."); 115 System.exit(0); 116 } 117 118 final HelloWorldServerTls server = new HelloWorldServerTls(args[0], 119 Integer.parseInt(args[1]), 120 args[2], 121 args[3], 122 args.length == 5 ? args[4] : null); 123 server.start(); 124 server.blockUntilShutdown(); 125 } 126 127 static class GreeterImpl extends GreeterGrpc.GreeterImplBase { 128 129 @Override sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver)130 public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { 131 HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); 132 responseObserver.onNext(reply); 133 responseObserver.onCompleted(); 134 } 135 } 136 } 137