How to connect to a gRPC Server hosted in Kestrel as HTTPS from a gRPC C++ Client using default certificates (Windows 10)? - asp.net-core

I am using ASP.Net Core (Grpc.Net) for creating a HTTPS gRPC server hosted in Kestrel. The communication between C# Client to the server (HTTPS) works fine with out adding any certificate.
It looks like they are using the default certificates for communication.
Now I have a C++ gRPC Client in Windows 10 and I'm trying to connect to the same server from a client, the endpoint is https://localhost:50051.
This is my Kestrel configuration #server.
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Any, 50051, listenOptions =>
{
listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
listenOptions.UseHttps();
});
}).UseStartup<Startup>();
As you could see I am not using certificates in the server (wanted to use default certificates) the same way I used C# gRPC Client.
i.e. connection to server works using C# Client
var channel = GrpcChannel.ForAddress("https://localhost:50051");
ecgDataClient = new Data.DataClient(channel);
But with C++ gRPC Client Client I am unable to connect (tried both InSecure & SslCredentials):
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
DataGrpcClient grpcClient( grpc::CreateChannel("localhost:50051", channel_creds));
With grpc::SslCredentials(grpc::SslCredentialsOptions()) I get this error:
E0709 19:46:20.488000000 6724 ssl_utils.cc:570] load_file: {"created":"#1625840180.488000000","description":"Failed to load file","file":"D:\DEV\vcpkg\buildtrees\grpc\src\17cc203898-db2679e7f2.clean\src\core\lib\iomgr\load_file.cc","file_line":72,"filename":"/usr/share/grpc/roots.pem","referenced_errors":[{"created":"#1625840180.488000000","description":"No such file or directory","errno":2,"file":"D:\DEV\vcpkg\buildtrees\grpc\src\17cc203898-db2679e7f2.clean\src\core\lib\iomgr\load_file.cc","file_line":45,"os_error":"No such file or directory","syscall":"fopen"}]}
E0709 19:46:20.509000000 6724 ssl_security_connector.cc:413] Could not get default pem root certs.
E0709 19:46:20.512000000 6724 secure_channel_create.cc:108] Failed to create secure subchannel for secure name 'localhost:50051'
E0709 19:46:20.517000000 6724 secure_channel_create.cc:50] Failed to create channel args during subchannel creation.
E0709 19:46:20.521000000 6724 ssl_security_connector.cc:413] Could not get default pem root certs.
E0709 19:46:20.525000000 6724 secure_channel_create.cc:108] Failed to create secure subchannel for secure name 'localhost:50051'
E0709 19:46:20.529000000 6724 secure_channel_create.cc:50] Failed to create channel args during subchannel creation.
It looks like unable to find the default certificates.
I am running my C++ gRPC Client in Windows 10, should I need to do anything so that the client picks the default certificates?
Thanks
Basanth

Related

Kestrel Fails TLS Handshake after Attempt to Download Intermediate Certificate Fails

Kestrel's web server is timing out, saying Connection Closed, after loading a publicly-signed SSL Certificate.
Background - we have a docker container that hosts a dotnet 3.1 webapi/react app, where the user can upload a custom SSL certificate. The PKCS#12 certificate is stored in our database and bound at startup using .ConfigureKestrel((context,options)) and options.ConfigureHttpsDefaults(listenOptions=>{listenOptions.ServerCertificate = certFromDatabase; }). This has been working flawless.
However, the problem now is that a user is attempting to run this app in a restrictive firewalled environment and is receiving HTTP connection closed errors when attempting to access Kestrel immediately after loading a new certificate and restarting the app.
Whenever Kestrel receives an incoming request, it begins attempting to download the intermediate certificate from the certificate's CA's public CDN repository via http on port 80. It appears to be using the URL from the Authority Information Access portion of the certificate. Since the firewall is blocking this, it retries repeatedly for about 20 seconds, during which time the client's TLS handshake sits waiting on a server response. When the server eventually fails to fetch the intermediate certificate, it cancels the TLS handshake and closes the connection.
I can't figure out why it's attempting to download this certificate, considering the same certificate is embedded in the PKCS#12 PFX bundle that is bound to Kestrel. Am I supposed to load either the root CA or intermediate into the CA trust folder in file system? (Ex. /usr/local/share/ca-certificates/ - I can't load the intermediate there, only the CA?)
public static IWebHost BuildFullWebHost(string[] args)
{
var webHostBuilder = GetBaseWebHostBuilder(args);
return webHostBuilder
.ConfigureAppConfiguration((context, builder) => { [...] })
.ConfigureLogging((hostingContext, logging) => { [...] })
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
var sp = options.ApplicationServices;
using (var scope = sp.CreateScope())
{
var dbContext = scope.ServiceProvider.GetService<DbContext>();
var cert = Example.Services.HttpsCertificateService.GetHttpsCert(dbContext);
//this returns a new X509Certificate2(certificate.HttpsCertificate, certificate.Password);
options.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.ServerCertificate = cert;
listenOptions.CheckCertificateRevocation = false;
});
}
})
.Build();
}
Not a great solution, but upgrading to .NET 5.0 resolved the issue. It seems that in .NET 5.0, Kestrel attempts to fetch the certificate chain during initial application startup only (and fails). Subsequent incoming HTTP requests don't trigger the fetch process and requests are served as expected.

Jmeter testing integration with IBM dtapower

Need your help in setting the SSL manager in Jmeter for performance testing with IBM datapower.
I tried the below steps to Add cert.
• Added (* .jks /*.p12 ) file in the jmeter GUI > Options > SSL Manager.
• I tried the setting the jks file in system.properties file too.
Path : *\jMETER\apache-jmeter-3.0\apache-jmeter-3.0\bin\system.properties
# Truststore properties (trusted certificates)
#javax.net.ssl.trustStore=/path/to/[jsse]cacerts
#javax.net.ssl.trustStorePassword
#javax.net.ssl.trustStoreProvider
#javax.net.ssl.trustStoreType [default = KeyStore.getDefaultType()]
# Keystore properties (client certificates)
# Location
javax.net.ssl.keyStore=****.jks -- Added
#
#The password to your keystore
javax.net.ssl.keyStorePassword=****-- Added
#
#javax.net.ssl.keyStoreProvider
#javax.net.ssl.keyStoreType [default = KeyStore.getDefaultType()]
I dont see the SSL handshake jMETER and datapower even after i followed ablove steps. Getting below error from datapower.
12:47:26 AM ssl error 51751363 10.123.98.73 0x806000ca valcred (###_CVC_Reverse_Server): SSL Proxy Profile '###_SSLPP_Reverse_Server': connection error: peer did not send a certificate
12:47:26 AM mpgw error 51751363 10.123.98.73 0x80e00161 source-https (###_HTTPS_FSH_CON_****): Request processing failed: Connection terminated before request headers read because of the connection error occurs, from URL: 10.123.98.73:58394
12:47:26 AM ssl error 51751363 10.123.98.73 0x8120002f sslproxy (####_SSLPP_Reverse_Server): SSL library error: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not
Can you please advice how to send the cert(.jks/ .p12) file from jmeter.
Change "Implementation" of your HTTP Request sampler(s) to Java. The fastest and the easiest way of doing this is using HTTP Request Defaults.
If you're using .p12 keystores you will need an extra line in the system.properties file like:
javax.net.ssl.keyStoreType=pkcs12
JMeter restart is required to pick the properties up.
See How to Set Your JMeter Load Test to Use Client Side Certificates article for more information.

smack SSL/TLS required by client but not supported by server

I am trying to establish secure connection between Openfire and smack client and get the error
org.jivesoftware.smack.SmackException$SecurityRequiredByClientException:
SSL/TLS required by client but not supported by server
I am using Openfire 4.0.1 and have enabled 5223. Using Smack on client side and connection configuration is as follows:
configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
configBuilder.setServiceName(service_name);
configBuilder.setHost(server);
configBuilder.setPort(5223);
setHttpsClient(); // Sets a SSL context
configBuilder.setCustomSSLContext(mSSLContext);
configBuilder.setSocketFactory(mSSLContext.getSocketFactory());
connection = new XMPPTCPConnection( configBuilder.build( ) );
connection.connect();
After initial exchange server sends
<stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism>
<mechanism>SCRAM-SHA-1</mechanism><mechanism>CRAM-MD5</mechanism>
<mechanism>DIGEST-MD5</mechanism></mechanisms><compression
xmlns="http://jabber.org/features/compress"><method>zlib</method>
</compression><auth xmlns="http://jabber.org/features/iq-auth"/><register
xmlns="http://jabber.org/features/iq-register"/></stream:features>
which does not contain starttls.

Environment specific SSL connection failures - Java to webMethods IS - bad certificate

I have a Java application that connects to webMethods IS via SSL.
public static QueueConnection createSSLEnabledQueueConnectionToWebmethods(Context context, String username, String password, Properties props, String factoryName) throws Exception
{
String pathToKeyStore = props.getProperty("keystore.path");
String pathToTrustStore = props.getProperty("truststore.path");
WmConnectionFactoryImpl factory = (WmConnectionFactoryImpl)
context.lookup(factoryName);
((WmConnectionFactoryImpl)factory).setSSLKeystore(pathToKeyStore);
((WmConnectionFactoryImpl)factory).setSSLTruststore(pathToTrustStore);
((WmConnectionFactoryImpl)factory).setSSLEncrypted(true);
return ((WmConnectionFactoryImpl)factory).createQueueConnection(username, password);
}
I have a keyStore.p12 file and a TrustStore.jks file that have been working for years in our Production environment (and still work with previous application builds).
In our Test environment, with the new application build, I can use the above keyStore and TrustStore files to establish SSL connection with webMethods. however, in the Production environment, the exact application installation results in the below error:
javax.jms.JMSSecurityException: [BRM.10.5061] JMS: SSL certificate "keystore.p12": bad certificate.
at com.webmethods.jms.protocol.link.LinkSsl.createSslContext(LinkSsl.java:377)
at com.webmethods.jms.protocol.link.LinkSsl.connect(LinkSsl.java:112)
at com.webmethods.jms.protocol.ProtocolHandler.connect(ProtocolHandler.java:218)
at com.webmethods.jms.protocol.BinaryProtocolHandler.connect(BinaryProtocolHandler.java:1950)
at com.webmethods.jms.impl.WmConnectionImpl.connect(WmConnectionImpl.java:302)
at com.webmethods.jms.impl.WmConnectionImpl.initConnection(WmConnectionImpl.java:280)
at com.webmethods.jms.impl.WmConnectionImpl.(WmConnectionImpl.java:219)
at com.webmethods.jms.impl.WmConnectionImpl.(WmConnectionImpl.java:193)
at com.webmethods.jms.impl.WmQueueConnectionImpl.(WmQueueConnectionImpl.java:44)
at com.webmethods.jms.impl.WmConnectionFactoryImpl.createQueueConnection(WmConnectionFactoryImpl.java:328)
Given the same application build and same key/truststore files (both configured to connect to PROD webMethods), I have the following test results:
In the TEST environment:
Full application start-up with SSL connection => SUCCESSFUL
Test harness performing SSL connection only => SUCCESSFUL
In the PRODUCTION environment:
Full application start-up with SSL connection => FAILURE >>> bad certificate
Test harness performing SSL connection only => SUCCESSFUL
I am wondering if there is anything in the JDK that could be causing the inconsistent behaviour in the PRODUCTION environment?
Or is there any useful knowledge out there around the very vague "bad certificate" error?

SignalR with Self-Signed SSL and Self-Host

Tried my luck at research, but so far no joy.
I would like to connect a SignalR javascript client to a self-hosted SignalR Windows Service binding to a self-signed SSL certificate.
My application works quite well over http, but the client repetitively disconnects when the Owin WebApplication starts using https.
Here is what I've done to configure SignalR with SSL.
Created a Self-Signed certificate using IIS
Imported the certificate into the Trusted Root Certification Authorities in the mmc (not sure if that helped)
Ran NETSH command to bind SSL to port 8080
netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf}
Added code in self-hosted HubConnection instances to add exported SSL like this (though this shouldn't matter because it's the client that cannot connect):
if (File.Exists("MyCert.cer")
&& Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
Starting Owin WebApplication using https (this should create the binding in http.sys)
string registerUrl = string.Format("{0}://SOME.WHERE.COM:{1}", Service.Server.SrProtocol, Service.Server.SrPort);
WebApp.Start<StartUp>(registerUrl);
In the SignalR 2.0 documentation, it says:
To start the web server, call WebApplication.Start(endpoint). You should now be able to navigate to endpoint/signalr/hubs in your browser.
When I browse to the URL http://SOME.WHERE.COM:8080/signalr/hubs I am successful receiving the javascript that drives SignalR.
When I browse to the URL https://SOME.WHERE.COM:8080/signalr/hubs I am unsuccessful and I receive "The connection to the server was reset" using FF.
Some additional points I've considered:
NETSH SHOW indicates the url is registered
URL group ID: E300000240000022
State: Active
Request queue name: Request queue is unnamed.
Properties:
Max bandwidth: inherited
Max connections: inherited
Timeouts:
Timeout values inherited
Number of registered URLs: 1
Registered URLs: HTTPS://SOME.WHERE.COM:8080/
NETSH SHOW indicates the SSL certificate is bound to 8080:
IP:port : 0.0.0.0:8080
Certificate Hash : 123456f6790a35f4b017b55d09e28f7ebe001bd
Application ID : {12345678-db90-4b66-8b01-88f7af2e36bf}
Certificate Store Name : (null)
Verify Client Certificate Revocation : Enabled
Verify Revocation Using Cached Client Certificate Only : Disabled
Usage Check : Enabled
Revocation Freshness Time : 0
URL Retrieval Timeout : 0
Ctl Identifier : (null)
Ctl Store Name : (null)
DS Mapper Usage : Disabled
Negotiate Client Certificate : Disabled
Any help is greatly appreciated!
I believe its all working for me now. Here is a run down of the steps I took to get things flowing:
SSL NOTES
SSL & SignalR (Owin WebApplication) requires binding a certificate to a port.
Use IIS to generate an self-signed cert, this should place the certificate into the LOCAL COMPUTER > Personal > Certificates folder in CERTMGR
In CERTMGR shift+drag certificate to LOCAL COMPUTER > Trusted Root Certification Authorities > Certificates folder, which should make a copy of it there
Run the following command to bind the SSL certificate to 0.0.0.0:8080
netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf}
netsh http show urlacl > D:\urlacl.txt
Output:
Reserved URL : https://*:8080/
User: SOMEWHERE\Administrator
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;S-1-5-21-138209071-46972887-2260295844-1106)
Run the following NETSH command to reserve all IP addresses for port 8080 to the My Service application ID and service account
netsh http add urlacl url=https://*:8080/ user=SOMEWHERE\Administrator listen=yes
netsh http show sslcert > D:\sslcert.txt
Output:
IP:port : 0.0.0.0:8080
Certificate Hash : 123456f6790a35f4b017b55d09e28f7ebe001bd
Application ID : {12345678-db90-4b66-8b01-88f7af2e36bf}
Certificate Store Name : (null)
Verify Client Certificate Revocation : Enabled
Verify Revocation Using Cached Client Certificate Only : Disabled
Usage Check : Enabled
Revocation Freshness Time : 0
URL Retrieval Timeout : 0
Ctl Identifier : (null)
Ctl Store Name : (null)
DS Mapper Usage : Disabled
Negotiate Client Certificate : Disabled
Update the MyServices.exe.config file to use https protocol (These are appSetting keys used to dynamically set the protocol and port of SignalR when My Service starts)
<add key="SrProtocol" value="https" />
<add key="SrPort" value="8080" />
Start the My Service using the NETSTAT START command
Run the following NETSH command to show the service state is occupying the registered url
netsh http show servicestate > D:\servicestate.txt
Output:
Server session ID: C300000320000039
Version: 2.0
State: Active
Properties:
Max bandwidth: 4294967295
Timeouts:
Entity body timeout (secs): 120
Drain entity body timeout (secs): 120
Request queue timeout (secs): 120
Idle connection timeout (secs): 120
Header wait timeout (secs): 120
Minimum send rate (bytes/sec): 150
URL groups:
URL group ID: C600000340000138
State: Active
Request queue name: Request queue is unnamed.
Properties:
Max bandwidth: inherited
Max connections: inherited
Timeouts:
Timeout values inherited
Number of registered URLs: 1
Registered URLs:
HTTPS://*:8080/
My application does NOT depend on IIS, but once I used IIS to temporarily create a port binding to my SSL certificate, my application started to work, and I was able to inspect the NETSH servicestate to see how IIS does it. I have since dropped the IIS binding and ran through the setup notes, and still have success.
My Owing startup looks somethign like this:
private void configureMessaging()
{
string registerUrl = string.Format("{0}://*:{1}", Service.Server.SrProtocol, Service.Server.SrPort);
try
{
#if DEBUG
//System.Diagnostics.Debugger.Launch();
#endif
// Starts an owin web application to host SignalR, using the protocol and port defined.
WebApp.Start<StartUp>(registerUrl);
}
catch (Exception ex)
{
Logger.Logs.Log(string.Format("Failed to configure messaging. Exception: {0}", ex.RecurseInnerException()), LogType.Error);
if (ex is HttpListenerException || ex.InnerException is HttpListenerException)
{
try
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = string.Format("netsh http delete urlacl url={0}"
, registerUrl
);
p.Start();
p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
catch (Exception exP)
{
Logger.Logs.Log(string.Format("Failed to delete urlacl {0}. Exception: {1}"
, registerUrl
, exP.RecurseInnerException()
)
, LogType.Error
)
;
retries = 5;
}
}
if (retries < 5)
{
retries++;
Logger.Logs.Log(string.Format("Attempting to configure messaging again. Attempt No. {0}", retries), LogType.Warn);
Thread.Sleep(1000);
configureMessaging();
}
else
Logger.Logs.Log(string.Format("Exceeded total number of retries to configure messaging.", retries), LogType.Error);
}
}
And self-hosted HubConnetion instances look like this:
public IHubProxy MyHubProxy
{
get
{
if (this._MyHubProxy == null)
{
var connection = new HubConnection(string.Format("{0}://{1}:{2}/"
, Settings.GetSetting(Settings.Setting.SrProtocol)
, MyHub.GetLocalhostFqdn(null)
, Settings.GetSetting(Settings.Setting.SrPort)
)
)
;
this._MyHubProxy = connection.CreateHubProxy("MyHub");
if (File.Exists("My.cer")
&& Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
connection.AddClientCertificate(X509Certificate.CreateFromCertFile("My.cer"));
connection.Start().Wait();
}
return this._MyHubProxy;
}
}
There is a little more code here than relevant, but hopefully it may be of help!