public void SelfSignedTLSCertTest() { bool handshakeOccured = false; Server sv = new Server(); TLSCertificateKeyPair serverCert = TLSCertificateKeyPair.CreateServerCert("localhost"); TLSCertificateKeyPair clientCert = TLSCertificateKeyPair.CreateClientCert(); KeyCertificatePair pair = new KeyCertificatePair(serverCert.CertPEMBytes.ToUTF8String(), serverCert.KeyPEMBytes.ToUTF8String()); ServerCredentials credentials = new SslServerCredentials(new[] { pair }, clientCert.CertPEMBytes.ToUTF8String(), true); sv.Ports.Add(new ServerPort("localhost", 0, credentials)); sv.Services.Add(Endorser.BindService(new MockEndorser()).Intercept(new MultalTLSInterceptor(clientCert.CertPEMBytes, (b) => handshakeOccured = b))); sv.Start(); int port = sv.Ports.First().BoundPort; ChannelCredentials cred = new SslCredentials(serverCert.CertPEMBytes.ToUTF8String(), new KeyCertificatePair(clientCert.CertPEMBytes.ToUTF8String(), clientCert.KeyPEMBytes.ToUTF8String())); Channel chan = new Channel("localhost", port, cred); SignedProposal prop = new SignedProposal(); Endorser.EndorserClient cl = new Endorser.EndorserClient(chan); cl.ProcessProposal(prop); Assert.IsTrue(handshakeOccured, "Handshake didn't occur"); chan.ShutdownAsync().RunAndUnwrap(); sv.ShutdownAsync().RunAndUnwrap(); }
public Endpoint(string url, Properties properties) { NetworkConfig.ReplaceNettyOptions(properties); logger.Trace($"Creating endpoint for url {url}"); Url = url; string cn = null; string nt; byte[] pemBytes = null; var purl = Utils.ParseGrpcUrl(url); Protocol = purl.Protocol; Host = purl.Host; Port = purl.Port; if (properties != null) { ckp = new TLSCertificateKeyPair(properties); if ("grpcs".Equals(Protocol, StringComparison.InvariantCultureIgnoreCase)) { using (MemoryStream bis = new MemoryStream()) { try { if (properties.Contains("pemBytes")) { bis.WriteAllBytes(properties["pemBytes"].ToBytes()); } if (properties.Contains("pemFile")) { string pemFile = properties["pemFile"]; Regex r = new Regex("[ \t]*,[ \t]*"); string[] pems = r.Split(pemFile); foreach (string pem in pems) { if (!string.IsNullOrEmpty(pem)) { try { bis.WriteAllBytes(File.ReadAllBytes(Path.GetFullPath(pem))); } catch (IOException) { throw new ArgumentException($"Failed to read certificate file {Path.GetFullPath(pem)}"); } } } } bis.Flush(); pemBytes = bis.ToArray(); logger.Trace($"Endpoint {url} pemBytes: {pemBytes.ToHexString()}"); if (pemBytes.Length == 0) { pemBytes = null; } } catch (Exception e) { throw new Exception($"Failed to read CA certificates file {e}"); } } if (pemBytes == null) { logger.Warn($"Endpoint {url} is grpcs with no CA certificates"); } if (null != pemBytes) { try { cn = properties.Contains("hostnameOverride") ? properties["hostnameOverride"] : null; bool trustsv = properties.Contains("trustServerCertificate") && (properties["trustServerCertificate"]).Equals("true", StringComparison.InvariantCultureIgnoreCase); if (cn == null && trustsv) { string cnKey = pemBytes.ToUTF8String(); CN_CACHE.TryGetValue(cnKey, out cn); if (cn == null) { X509Certificate2 cert = Certificate.PEMToX509Certificate2(cnKey); cn = cert.GetNameInfo(X509NameType.DnsName, false); CN_CACHE.TryAdd(cnKey, cn); } } } catch (Exception e) { // Mostly a development env. just log it. logger.Error("Error getting Subject CN from certificate. Try setting it specifically with hostnameOverride property. " + e); } } nt = null; if (properties.Contains("negotiationType")) { nt = properties["negotiationType"]; } if (null == nt) { nt = SSLNEGOTIATION; logger.Trace($"Endpoint {url} specific Negotiation type not found use global value: {SSLNEGOTIATION}"); } if (!"TLS".Equals(nt, StringComparison.InvariantCultureIgnoreCase) && !"plainText".Equals(nt, StringComparison.InvariantCultureIgnoreCase)) { throw new ArgumentException($"Endpoint {url} property of negotiationType has to be either TLS or plainText. value:'{nt}'"); } } } try { List <ChannelOption> options = new List <ChannelOption>(); if (properties != null) { foreach (string str in properties.Keys) { if (str.StartsWith("grpc.")) { if (int.TryParse(properties[str], out int value)) { options.Add(new ChannelOption(str, value)); } else { options.Add(new ChannelOption(str, properties[str])); } } } } if (Protocol.Equals("grpc", StringComparison.InvariantCultureIgnoreCase)) { ChannelOptions = options; Credentials = null; } else if (Protocol.Equals("grpcs", StringComparison.InvariantCultureIgnoreCase)) { if (pemBytes == null) { // use root certificate ChannelOptions = options; Credentials = null; } else { if (ckp != null && ckp.CertPEMBytes != null && ckp.KeyPEMBytes != null) { creds = new SslCredentials(pemBytes.ToUTF8String(), new KeyCertificatePair(ckp.CertPEMBytes.ToUTF8String(), ckp.KeyPEMBytes.ToUTF8String())); } else { creds = new SslCredentials(pemBytes.ToUTF8String()); } if (cn != null) { options.Add(new ChannelOption("grpc.ssl_target_name_override", cn)); } Credentials = creds; ChannelOptions = options; logger.Trace($"Endpoint {url} final server pemBytes: {pemBytes.ToHexString()}"); } } else { throw new ArgumentException("invalid protocol: " + Protocol); } } catch (Exception e) { logger.ErrorException($"Endpoint {url}, exception '{e.Message}'", e); throw; } }