Selaa lähdekoodia

Merge branch 'master' into metadata-tests

Tim Burks 7 vuotta sitten
vanhempi
commit
97e2fe965a

+ 5 - 1
Sources/CgRPC/shim/cgrpc.h

@@ -166,6 +166,8 @@ cgrpc_channel *cgrpc_channel_create(const char *address,
                                     int num_args);
 cgrpc_channel *cgrpc_channel_create_secure(const char *address,
                                            const char *pem_root_certs,
+                                           const char *client_certs,
+                                           const char *client_key,
                                            grpc_arg *args,
                                            int num_args);
 
@@ -188,7 +190,9 @@ void cgrpc_channel_watch_connectivity_state(cgrpc_channel *channel,
 cgrpc_server *cgrpc_server_create(const char *address);
 cgrpc_server *cgrpc_server_create_secure(const char *address,
                                          const char *private_key,
-                                         const char *cert_chain);
+                                         const char *cert_chain,
+                                         const char *root_certs,
+                                         int force_client_auth);
 void cgrpc_server_stop(cgrpc_server *server);
 void cgrpc_server_destroy(cgrpc_server *s);
 void cgrpc_server_start(cgrpc_server *s);

+ 11 - 1
Sources/CgRPC/shim/channel.c

@@ -39,6 +39,8 @@ cgrpc_channel *cgrpc_channel_create(const char *address,
 
 cgrpc_channel *cgrpc_channel_create_secure(const char *address,
                                            const char *pem_root_certs,
+                                           const char *client_certs,
+                                           const char *client_private_key,
                                            grpc_arg *args,
                                            int num_args) {
   cgrpc_channel *c = (cgrpc_channel *) malloc(sizeof (cgrpc_channel));
@@ -47,7 +49,15 @@ cgrpc_channel *cgrpc_channel_create_secure(const char *address,
   channel_args.args = args;
   channel_args.num_args = num_args;
 
-  grpc_channel_credentials *creds = grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
+  grpc_ssl_pem_key_cert_pair client_credentials;
+  grpc_ssl_pem_key_cert_pair *client_credentials_pointer = NULL;
+  if (client_certs != NULL && client_private_key != NULL) {
+    client_credentials.cert_chain = client_certs;
+    client_credentials.private_key = client_private_key;
+    client_credentials_pointer = &client_credentials;
+  }
+  grpc_channel_credentials *creds = grpc_ssl_credentials_create(pem_root_certs, client_credentials_pointer, NULL);
+
   c->channel = grpc_secure_channel_create(creds, address, &channel_args, NULL);
   c->completion_queue = grpc_completion_queue_create_for_next(NULL);
   return c;

+ 5 - 3
Sources/CgRPC/shim/server.c

@@ -33,7 +33,9 @@ cgrpc_server *cgrpc_server_create(const char *address) {
 
 cgrpc_server *cgrpc_server_create_secure(const char *address,
                                          const char *private_key,
-                                         const char *cert_chain) {
+                                         const char *cert_chain,
+                                         const char *root_certs,
+                                         int force_client_auth) {
   cgrpc_server *server = (cgrpc_server *) malloc(sizeof (cgrpc_server));
   server->server = grpc_server_create(NULL, NULL);
   server->completion_queue = grpc_completion_queue_create_for_next(NULL);
@@ -44,10 +46,10 @@ cgrpc_server *cgrpc_server_create_secure(const char *address,
   server_credentials.cert_chain = cert_chain;
 
   grpc_server_credentials *credentials = grpc_ssl_server_credentials_create
-  (NULL,
+  (root_certs,
    &server_credentials,
    1,
-   0,
+   force_client_auth,
    NULL);
   
   // prepare the server to listen

+ 29 - 6
Sources/RootsEncoder/main.swift

@@ -52,22 +52,45 @@ s += "// GENERATED: DO NOT EDIT\n"
 
 if CommandLine.arguments.contains("test") {
   s += "//\n"
-  s += "// This file contain a function that returns the contents of Tests/ssl.crt and Tests/ssl.key.\n"
+  s += "// This file contain a function that returns the contents of certificates and keys in Tests/.\n"
   s += "//\n"
   s += "import Foundation\n"
   s += "\n"
 
-  s += "let certificateForTests = "
-  let certificateURL = URL(fileURLWithPath: "Tests/ssl.crt")
+  // server.crt
+  s += "let serverCertificate = "
+  let certificateURL = URL(fileURLWithPath: "Tests/server.crt")
   let certificateData = try Data(contentsOf: certificateURL)
   let encodedCertificate = certificateData.base64EncodedString()
   s += "Data(base64Encoded: \"\(encodedCertificate)\", options:[])!\n"
 
-  s += "let keyForTests = "
-  let keyURL = URL(fileURLWithPath: "Tests/ssl.key")
+  // server.pem
+  s += "let serverKey = "
+  let keyURL = URL(fileURLWithPath: "Tests/server.pem")
   let keyData = try Data(contentsOf: keyURL)
   let encodedKey = keyData.base64EncodedString()
-  s += "Data(base64Encoded: \"\(encodedKey)\", options:[])!"
+  s += "Data(base64Encoded: \"\(encodedKey)\", options:[])!\n"
+
+  // ca.crt
+  s += "let trustCollectionCertificate = "
+  let caURL = URL(fileURLWithPath: "Tests/ca.crt")
+  let caData = try Data(contentsOf: caURL)
+  let caEncoded = caData.base64EncodedString()
+  s += "Data(base64Encoded: \"\(caEncoded)\", options:[])!\n"
+
+  // client.crt
+  s += "let clientCertificate = "
+  let clientCertURL = URL(fileURLWithPath: "Tests/client.crt")
+  let clientCertData = try Data(contentsOf: clientCertURL)
+  let clientCertEncoded = clientCertData.base64EncodedString()
+  s += "Data(base64Encoded: \"\(clientCertEncoded)\", options:[])!\n"
+
+  // client.pem
+  s += "let clientKey = "
+  let clientKeyURL = URL(fileURLWithPath: "Tests/client.pem")
+  let clientKeyData = try Data(contentsOf: clientKeyURL)
+  let clientKeyEncoded = clientKeyData.base64EncodedString()
+  s += "Data(base64Encoded: \"\(clientKeyEncoded)\", options:[])!"
 } else {
   s += "//\n"
   s += "// This file contain a function that returns the default roots.pem.\n"

+ 5 - 3
Sources/SwiftGRPC/Core/Channel.swift

@@ -48,7 +48,7 @@ public class Channel {
     var argumentValues = argumentWrappers.map { $0.wrapped }
 
     if secure {
-      underlyingChannel = cgrpc_channel_create_secure(address, roots_pem(), &argumentValues, Int32(arguments.count))
+      underlyingChannel = cgrpc_channel_create_secure(address, roots_pem(), nil, nil, &argumentValues, Int32(arguments.count))
     } else {
       underlyingChannel = cgrpc_channel_create(address, &argumentValues, Int32(arguments.count))
     }
@@ -60,14 +60,16 @@ public class Channel {
   ///
   /// - Parameter address: the address of the server to be called
   /// - Parameter certificates: a PEM representation of certificates to use
+  /// - Parameter clientCertificates: a PEM representation of the client certificates to use
+  /// - Parameter clientKey: a PEM representation of the client key to use
   /// - Parameter arguments: list of channel configuration options
-  public init(address: String, certificates: String, arguments: [Argument] = []) {
+  public init(address: String, certificates: String, clientCertificates: String? = nil, clientKey: String? = nil, arguments: [Argument] = []) {
     gRPC.initialize()
     host = address
     let argumentWrappers = arguments.map { $0.toCArg() }
     var argumentValues = argumentWrappers.map { $0.wrapped }
 
-    underlyingChannel = cgrpc_channel_create_secure(address, certificates, &argumentValues, Int32(arguments.count))
+    underlyingChannel = cgrpc_channel_create_secure(address, certificates, clientCertificates, clientKey, &argumentValues, Int32(arguments.count))
     completionQueue = CompletionQueue(underlyingCompletionQueue: cgrpc_channel_completion_queue(underlyingChannel), name: "Client")
     completionQueue.run() // start a loop that watches the channel's completion queue
   }

+ 3 - 2
Sources/SwiftGRPC/Core/Server.swift

@@ -50,8 +50,9 @@ public class Server {
   /// - Parameter address: the address where the server will listen
   /// - Parameter key: the private key for the server's certificates
   /// - Parameter certs: the server's certificates
-  public init(address: String, key: String, certs: String) {
-    underlyingServer = cgrpc_server_create_secure(address, key, certs)
+  /// - Parameter rootCerts: used to validate client certificates; will enable enforcing valid client certificates when provided
+  public init(address: String, key: String, certs: String, rootCerts: String? = nil) {
+    underlyingServer = cgrpc_server_create_secure(address, key, certs, rootCerts, rootCerts == nil ? 0 : 1)
     completionQueue = CompletionQueue(
       underlyingCompletionQueue: cgrpc_server_get_completion_queue(underlyingServer), name: "Server " + address)
   }

+ 2 - 2
Sources/SwiftGRPC/Runtime/ServiceClient.swift

@@ -62,9 +62,9 @@ open class ServiceClientBase: ServiceClient {
   }
   
   /// Create a client that makes secure connections with a custom certificate.
-  required public init(address: String, certificates: String, arguments: [Channel.Argument] = []) {
+  required public init(address: String, certificates: String, clientCertificates: String? = nil, clientKey: String? = nil, arguments: [Channel.Argument] = []) {
     gRPC.initialize()
-    channel = Channel(address: address, certificates: certificates, arguments: arguments)
+    channel = Channel(address: address, certificates: certificates, clientCertificates: clientCertificates, clientKey: clientKey, arguments: arguments)
     metadata = Metadata()
   }
 }

+ 11 - 4
Sources/SwiftGRPC/Runtime/ServiceServer.swift

@@ -35,21 +35,28 @@ open class ServiceServer {
   }
 
   /// Create a server that accepts secure connections.
-  public init(address: String, certificateString: String, keyString: String, serviceProviders: [ServiceProvider]) {
+  public init(address: String, certificateString: String, keyString: String, rootCerts: String? = nil, serviceProviders: [ServiceProvider]) {
     gRPC.initialize()
     self.address = address
-    server = Server(address: address, key: keyString, certs: certificateString)
+    server = Server(address: address, key: keyString, certs: certificateString, rootCerts: rootCerts)
     servicesByName = Dictionary(uniqueKeysWithValues: serviceProviders.map { ($0.serviceName, $0) })
   }
 
   /// Create a server that accepts secure connections.
-  public init?(address: String, certificateURL: URL, keyURL: URL, serviceProviders: [ServiceProvider]) {
+  public init?(address: String, certificateURL: URL, keyURL: URL, rootCertsURL: URL? = nil, serviceProviders: [ServiceProvider]) {
     guard let certificate = try? String(contentsOf: certificateURL, encoding: .utf8),
       let key = try? String(contentsOf: keyURL, encoding: .utf8)
       else { return nil }
+    var rootCerts: String?
+    if let rootCertsURL = rootCertsURL {
+      guard let rootCertsString = try? String(contentsOf: rootCertsURL, encoding: .utf8) else {
+        return nil
+      }
+      rootCerts = rootCertsString
+    }
     gRPC.initialize()
     self.address = address
-    server = Server(address: address, key: key, certs: certificate)
+    server = Server(address: address, key: key, certs: certificate, rootCerts: rootCerts)
     servicesByName = Dictionary(uniqueKeysWithValues: serviceProviders.map { ($0.serviceName, $0) })
   }
 

+ 2 - 0
Tests/LinuxMain.swift

@@ -25,6 +25,8 @@ XCTMain([
   testCase(CompletionQueueTests.allTests),
   testCase(ConnectionFailureTests.allTests),
   testCase(EchoTests.allTests),
+  testCase(EchoTestsSecure.allTests),
+  testCase(EchoTestsMutualAuth.allTests),
   testCase(MetadataTests.allTests),
   testCase(ServerCancellingTests.allTests),
   testCase(ServerTestExample.allTests),

+ 30 - 13
Tests/SwiftGRPCTests/BasicEchoTestCase.swift

@@ -31,6 +31,12 @@ extension Echo_EchoResponse {
 }
 
 class BasicEchoTestCase: XCTestCase {
+  enum Security {
+    case none
+    case ssl
+    case tlsMutualAuth
+  }
+
   func makeProvider() -> Echo_EchoProvider { return EchoProvider() }
 
   var provider: Echo_EchoProvider!
@@ -38,38 +44,49 @@ class BasicEchoTestCase: XCTestCase {
   var client: Echo_EchoServiceClient!
   
   var defaultTimeout: TimeInterval { return 1.0 }
-  var secure: Bool { return false }
+  var security: Security { return .none }
   var address: String { return "localhost:5050" }
 
   override func setUp() {
     super.setUp()
     
     provider = makeProvider()
-    
-    if secure {
-      let certificateString = String(data: certificateForTests, encoding: .utf8)!
+
+    let serverCertificateString = String(data: serverCertificate, encoding: .utf8)!
+    let serverKeyString = String(data: serverKey, encoding: .utf8)!
+    let rootCerts = String(data: trustCollectionCertificate, encoding: .utf8)!
+    let clientCertificateString = String(data: clientCertificate, encoding: .utf8)!
+    let clientKeyString = String(data: clientKey, encoding: .utf8)!
+
+    switch security {
+    case .ssl:
       server = ServiceServer(address: address,
-                             certificateString: certificateString,
-                             keyString: String(data: keyForTests, encoding: .utf8)!,
-                             serviceProviders: [provider])
+                               certificateString: serverCertificateString,
+                               keyString: serverKeyString,
+                               serviceProviders: [provider])
+      server.start()
+      client = Echo_EchoServiceClient(address: address, certificates: rootCerts, arguments: [.sslTargetNameOverride("example.com")])
+      client.host = "example.com"
+    case .tlsMutualAuth:
+      server = ServiceServer(address: address, certificateString: serverCertificateString, keyString: serverKeyString, rootCerts: rootCerts, serviceProviders: [provider])
       server.start()
-      client = Echo_EchoServiceClient(address: address, certificates: certificateString, arguments: [.sslTargetNameOverride("example.com")])
+      client = Echo_EchoServiceClient(address: address, certificates: rootCerts, clientCertificates: clientCertificateString, clientKey: clientKeyString, arguments: [.sslTargetNameOverride("example.com")])
       client.host = "example.com"
-    } else {
+    case .none:
       server = ServiceServer(address: address, serviceProviders: [provider])
       server.start()
       client = Echo_EchoServiceClient(address: address, secure: false)
     }
-    
+
     client.timeout = defaultTimeout
   }
-  
+
   override func tearDown() {
     client = nil
-    
+
     server.server.stop()
     server = nil
-    
+
     super.tearDown()
   }
 }

+ 5 - 1
Tests/SwiftGRPCTests/EchoTests.swift

@@ -38,7 +38,11 @@ class EchoTests: BasicEchoTestCase {
 }
 
 class EchoTestsSecure: EchoTests {
-  override var secure: Bool { return true }
+  override var security: Security { return .ssl }
+}
+
+class EchoTestsMutualAuth: EchoTests {
+  override var security: Security { return .tlsMutualAuth }
 }
 
 extension EchoTests {

+ 3 - 3
Tests/SwiftGRPCTests/GRPCTests.swift

@@ -101,8 +101,8 @@ func runTest(useSSL: Bool) {
   let server: Server
   if useSSL {
     server = Server(address: address,
-                    key: String(data: keyForTests, encoding: .utf8)!,
-                    certs: String(data: certificateForTests, encoding: .utf8)!)
+                    key: String(data: serverKey, encoding: .utf8)!,
+                    certs: String(data: serverCertificate, encoding: .utf8)!)
   } else {
     server = Server(address: address)
   }
@@ -145,7 +145,7 @@ func runClient(useSSL: Bool) throws {
 
   if useSSL {
     channel = Channel(address: address,
-                      certificates: String(data: certificateForTests, encoding: .utf8)!,
+                      certificates: String(data: trustCollectionCertificate, encoding: .utf8)!,
                       arguments: [.sslTargetNameOverride(host)])
   } else {
     channel = Channel(address: address, secure: false)

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 2
Tests/SwiftGRPCTests/TestKeys.swift


+ 16 - 0
Tests/ca.crt

@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICmDCCAYACCQCRdp7l+x1YRTANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDDANm
+b28wHhcNMTgwNjEyMTUzNTQ0WhcNMTkwNjEyMTUzNTQ0WjAOMQwwCgYDVQQDDANm
+b28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNUPtXcBkvWRLKLuAI
+AbmXFwInhGo71UqBwl0cxxWl0+FtGawbXF2ipZsKSrdI9gFEAv6V3z4FblAK86TH
+mQ17F94PCNdjQa26CExg77y9ot58P2D++3r3wbh8cyAvmuGgOpgXv1hwwm94rIl7
+BZls7enT8xjH4p93rtz7dCrtjCiFtUWDsYy7vjX65YU6HUAQtujRSOM8gVP++Yp0
+4nm7t8lNCEEqARYjskrTgVaD/RC60Q+tYfB+cATno02QJlczl8vpSUdzPz4W3A9q
+msWZ0+Wjvv1v1sbI53DCPG3eoDnDdtP7EtD5HdFAUeldkU/8aHKmPHH0ZOFuCA5t
+63x9AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHQW8RlUk5tcb38jDB1OWS6GfWUV
+9kS8bUtFuisinCd3nlhRcB76nqrlMF0Ii4OyYQ8kyzMa10dyqdVYk88FL20NbNde
+j1pzixXFRP5q4HpeUif6W/UkKHR5AN4wkTHrqAjEj76u3zTk1g173x7cvQzzrfZq
+nbg2UwPpFBqLDJHW/2kHjb+Sbdq6g5BKNyjVBpIJckjJ3V1XPZ/XvZft4HYBjQ5u
+ymDXWBw0ntdy8wM3S6c9AIisvZrTGyHNxdN69XVkgeyba1XPP08xpReMnD2pd/yF
+VRTqmM9r3spMGPE+yKUK7z4OpYvscq5agQISblYY0itN1EevEjnmtjmo9QE=
+-----END CERTIFICATE-----

+ 16 - 0
Tests/client.crt

@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICljCCAX4CAQEwDQYJKoZIhvcNAQEFBQAwDjEMMAoGA1UEAwwDZm9vMB4XDTE4
+MDYxMjE1MzU0N1oXDTE5MDYxMjE1MzU0N1owFDESMBAGA1UEAwwJbG9jYWxob3N0
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzwtCR53jheCf/vUuPq/Z
+Q2PyWWy8yh9+0ALxa30nUTLokzXXOpRsu4szaTW88xyfp1aHnjZgNO4igv5xD0cY
+ANqcdgAReGt7J4+KK/keao7cpt2h6uD5991n56kW5pKIJ7P6QHvYxheFl98akPBx
+BmvJ/9iKcq4pE+gNyWZ/ViY1hYOtGZaPgabhXGWYhRl0ajO3xehYmqU2fkhNhEbu
+S9LoRhfHCfm+g+/M5blnFAo/kbKVex/Iy+mBnOUssDrZTdQe2jLI0F6JsX672Hx/
+cF6QQ7BsDLWfF/0KGxj3t9EMXSKYSZeOp27C7Fy2kYLgwcvhRkESTPimnrTmqTKk
+/QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAfXQ07saJyeFryUqL+HMxfdCo5IGvv
+dSb4UFZ/8WHJ0IE52xueaFh2/ftyAcBRFpDkHWiEvpyLp20LI1iba1nR1AyKrcTL
+JdsbNiF1uMjfGdXA0mPVljkLluLOD4+V8Idtrf5PEzMPzaIsCMNbNyv5BB+87gSm
+D2u4dKYtlnaSIWKOkWu1Oz5o2HB+nIzoaKCjztamaYlE2T4clWTt78iA2tIhyjs2
+neRjXmXeCliMmy6D8re2qJk8rHLBwQutP+jc+TpQUeIUEJqWLlZBPYi9BD3jrdU6
+rbNJQO3wLnzrCldRgjLGLm8hHYOXn7gTL+vTpDT8aMuIfK2qXRj/Eg+A
+-----END CERTIFICATE-----

+ 28 - 0
Tests/client.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPC0JHneOF4J/+
+9S4+r9lDY/JZbLzKH37QAvFrfSdRMuiTNdc6lGy7izNpNbzzHJ+nVoeeNmA07iKC
+/nEPRxgA2px2ABF4a3snj4or+R5qjtym3aHq4Pn33WfnqRbmkogns/pAe9jGF4WX
+3xqQ8HEGa8n/2IpyrikT6A3JZn9WJjWFg60Zlo+BpuFcZZiFGXRqM7fF6FiapTZ+
+SE2ERu5L0uhGF8cJ+b6D78zluWcUCj+RspV7H8jL6YGc5SywOtlN1B7aMsjQXomx
+frvYfH9wXpBDsGwMtZ8X/QobGPe30QxdIphJl46nbsLsXLaRguDBy+FGQRJM+Kae
+tOapMqT9AgMBAAECggEAV3ckKukSgy4fqS+et7DGEegZK5n6L1Ea23lCz+vxPiZJ
+hlcKc57cSGZH87xV9EY1VBYD+NxzzCiFv90JmjCofUPdMSRaPQr63f2Pm4AET3PG
+119t1bHxJ7sK+BzApetlRZCMuc0YCKdLMpt3t587wECs9z5dTpEwnU489MYuKQ/8
+oCNp6cxfQ4fedoXE3FI+rBk66d8ropHtYiY20/JQXDXMCh57MmX1tRXOmxbqEx0i
+EGVbAQjQk90BJRYw8THTFIO1iGUhn0q0uuLdtKpcC9HeCv5Zn3HEiE2eyrfZpybw
+KS9x6DjszAputDBmERztNyXS+sNrMLH4pM/DyCRPKQKBgQDrMHApGkn7BvqJfkEe
+hWlG6pa4WrOAX2JnRudv0iVQZE7i2mAysC/rW92T83p5AaBXgzlPuZrTb3tfIRDn
+pHTMylYcVZ0lwIGiQyK8Ox1x6uXCy2xmNqwIuff7V/711HQCClPY2a0AWhEPrzl+
+QSSlc2fnjmdsheOPlK0cseVbOwKBgQDhXUSwM/u8oOzKsBLzZ7hcaY1JqIwZg7iS
+7Zg5rdSSXBz+aaQc0lpKveNmmPJzQky2pbc2ICsyTtwyQeo4g2q6N1lM86Ejtu0y
+PU0IN+YoJlgbq02T+diBw+pTM7M83zJwRljOpD5317hT9OSxQ2nqkIyah1uLJYQS
+vdXHMWNNJwKBgQChwwsh+ibwNXiUoPYBHBmw4SERY7EaloCEMEx2qL9pb9SiSzjn
+JC+RXfolDM4r9GZoSqVcpHhM/NyKLaAG8yIyyOg5TNltYd7H0A1QEgjKlZm6RVgl
+ZW0mA2MAySFfy+SOkrPg7rcDCu+5LfgJUpz1/050AYo5Jk3CL6xxlBoAiQKBgHQj
+yrg7sendzOoPn1SNCTemtcdV8w1bEo21oBNpf/kFO3PpIUgxJ5MJFN3UyG2Zp0sh
+T6+3GEvO1C+aRIhnQWNCDuVXUJ3FMawIZ2Bq3lOmnxVzTIGL6oXFX0cNh7tBEw9F
+UZL8lazRIQ8zT4ACy9y0LaGdTBIDfXLjHf6PdytVAoGAcHZN0A9J2FASD1CyIyUq
+Zm8RyZzUCF1SHXcKeUKfnvyLyOenK/Si4pWzO97no+KVHShJ66caCdHBPwUTwbS0
+XEqOaCivbzUhfjOv5j+SiYzWk55WOdpBYZUcoO0gQJNCQrjPlV0s8lwVgq+6sPC/
+fCAX5DBJIuC9Jlflrw56KLQ=
+-----END PRIVATE KEY-----

+ 16 - 0
Tests/server.crt

@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICmDCCAYACAQEwDQYJKoZIhvcNAQEFBQAwDjEMMAoGA1UEAwwDZm9vMB4XDTE4
+MDYxMjE1MzU0NloXDTE5MDYxMjE1MzU0NlowFjEUMBIGA1UEAwwLZXhhbXBsZS5j
+b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyVMhjqfkIQT2eN1rG
+ZHiZgqOD7kk61+jFE6XDGx0awku/VF3rQJOl8vaDksDsRfa0V4JtWfspj/4+Xrdg
+1wxXorNwXBvQ41VKGt6rgznIf/REHXGcidI2PxQP2RIQG4LqOTJAr8JOQ/XQkJmH
+98myHlWoR42qRZ7fJLeQs7gXig4NvCk9+oaOIty5JME7obDSrpEE0zDIuRTao5S6
+AhCJQRxwgHVfCgssUIUNB2MoHEFkCeX25/8kJrTgan+0XzIka1BVcVfRDu0WOR62
+kdQbBIuMfR0PrLkhbO+hnYudPw9sZfLgLwQlxbB/fyUzIBSNJzK5sRKIOP+COQs6
+G5KfAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEEcLWf1Lzu67tzYaLSzkSk+3U4a
+jRdm5Mh25HRPguSmDZycW6LWTfBIirgi98YAdf86XnLrOapty5+OS1vOXfmRum9W
+ZgJPj6dVs6mZk5/ppegj7FYuroQ/ItYiO6MCRpouDcDuCAie5ts1dDUfjHIb978X
+RO7ZFjQ+8eXqWbwc82q1cYjuLLROG/TJjmd8VZ4eK9XmZ/xtB43xllKcQfwqPVzr
+eIo45ydBmKuhAaEZnWrpcmi1mBZK42Z4P9zBmWPrtr5Sg/QIktEkNtCfJSixKZ9p
+OuupDH9yxlspVyeq0140pRGO1+fB/K0/KEPu+uwXNItClCLwYNRwvCLL0HU=
+-----END CERTIFICATE-----

+ 28 - 0
Tests/server.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCyVMhjqfkIQT2e
+N1rGZHiZgqOD7kk61+jFE6XDGx0awku/VF3rQJOl8vaDksDsRfa0V4JtWfspj/4+
+Xrdg1wxXorNwXBvQ41VKGt6rgznIf/REHXGcidI2PxQP2RIQG4LqOTJAr8JOQ/XQ
+kJmH98myHlWoR42qRZ7fJLeQs7gXig4NvCk9+oaOIty5JME7obDSrpEE0zDIuRTa
+o5S6AhCJQRxwgHVfCgssUIUNB2MoHEFkCeX25/8kJrTgan+0XzIka1BVcVfRDu0W
+OR62kdQbBIuMfR0PrLkhbO+hnYudPw9sZfLgLwQlxbB/fyUzIBSNJzK5sRKIOP+C
+OQs6G5KfAgMBAAECggEBAIp0LMjENKbmEDMAgye45bE5rj5GCPD4pK4t3Oqn6GbY
+Jvs7Q1fc4UVcZ2wrykEm6K2Hq6m+zLOuKhS+cN1s2RZJKcu4l5gMiDFqvyqmTXyP
+a1RfD9AbaOvY+Xh8bfu3gGLdWVjDnLYrKXRub+USyrPRvWtTcneaagiRdzuPbQRI
+TIrbswGlxm1Wr7XzYYA4ev7z1bXp1jUEwYItJjwE5Cmghj3IVj7NsxQ8F07H3Pgx
+rrLf/fpd2lS/a34tXL6OcH4JneOg/savhdK4O0hEn3b6d/T7V88B01NfPGCFbaz/
+bh38y/3bk51SXdsuoIzTWVqQLQ3FBB18bxO1hjBG6eECgYEA5d0sOWokK9uDiO0q
+77NeuIw/vs5tqGrAHa/s4VbhUr0Ne+jRq1TQB1w0EEnnuFXHgFOae2SewRo3lF8H
+dIu5Ciz0v/wDqI+wQWZCFv1kzqsHFmgDwckH5dFJN808+NaWpCcHqrh6wSswbP2l
+ftQpRKw5IrsdCui3tVTXe77HQSkCgYEAxpubG1xzsO2ApDkeRxWZeyaccPCI87rI
+vkyKXQE+i6x7MTUBojTzx30UYNLyNMc1b2d7fz+Atp/v3tHILVdsc9XiUD61RGSq
+5DoxdoyW4974PZHv+rbnJUvXCwmhAzjm5DcOCJZF5hjzp3CuX1ewfpBkXoMr4i2Q
+iqrG4+1fRocCgYEA3Ctl8bSF4vBGY//vMVsYbiH/6M4m4LsnOwhIF2q1Nh/Y64eM
+VNRO0c3yHGv9pGWdSoBJpskw+nsXI2mGZY5zdZir8bv88RZ4V5wPz590UDQm/MIy
+XwokI2+79tQCA8Le1WqBAHflNGMe5jZprzqeMKXZsDeTUOCpHeme4GtSxUkCgYBz
+viFRe7qMZIzwp7zmbkcIxwKqqvMVH0h35oFIHD6IBZexoJN4JWXgXxtuJeEzMtkI
+OIV3LdnkFCclcpo3GljA1OfUHgdjeUtCQEutK9ePqtR+hTsWoFrqmF0VOKJWD2Y3
+n4IVLQZFR0tPzFJCjAb2a02i6sy7PhSbS1UnZaF9pwKBgQC4U+hj2/bMA7TQ+duN
+akEn7+hwBKYfpn9Pc6ZR3IEXNgVMRtdML0CJItPmlGS95mR1AxvDGMxhawnTsAeS
+NduQAztM615fcJd6C9dcapW6fyns61vqcWKJmXcR2GBT31VIz98l24lz3EhVrsQO
+nOxD7wW4fmzFBXNgIYJUTeFA1g==
+-----END PRIVATE KEY-----

+ 32 - 7
scripts/makecert

@@ -1,8 +1,33 @@
-#!/bin/sh
-# 
-# Use this script to create a self-signed certificate (ssl.crt) and key file (ssl.key)
+#!/bin/bash
+#
+# Creates a trust collection certificate (ca.crt)
+# and self-signed server certificate (server.crt) and private key (server.pem)
+# and client certificate (client.crt) and key file (client.pem) for mutual TLS.
 # Replace "example.com" with the host name you'd like for your certificate.
-# 
-openssl genrsa -out ssl.key 2048
-openssl req -new -key ssl.key -out ssl.csr -subj "/CN=example.com"
-openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt
+#
+# https://github.com/grpc/grpc-java/tree/master/examples
+#
+SIZE=2048
+
+CN_CA=foo
+CN_SERVER=example.com
+CN_CLIENT=localhost
+
+# CA
+openssl genrsa -out ca.key $SIZE
+openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=${CN_CA}"
+
+# Server
+openssl genrsa -out server.key $SIZE
+openssl req -new -key server.key -out server.csr -subj "/CN=${CN_SERVER}"
+openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
+
+# Client
+openssl genrsa -out client.key $SIZE
+openssl req -new -key client.key -out client.csr -subj "/CN=${CN_CLIENT}"
+openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
+
+# netty only supports PKCS8 keys. openssl is used to convert from PKCS1 to PKCS8
+# http://netty.io/wiki/sslcontextbuilder-and-private-key.html
+openssl pkcs8 -topk8 -nocrypt -in client.key -out client.pem
+openssl pkcs8 -topk8 -nocrypt -in server.key -out server.pem

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä