I'm trying to make secure grpc calls from the client side but I can't seem to get my code to work; here are the steps and implementations I've taken.
My specs: I'm running visual studio on mac m1 pro and I'm using Protobuf-net Grpc
Step 1 - Install OpenSSL
brew install openssl
Step 2 - Create a certificate and key
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes
this asked a couple of questions. and then created the crt and key files.
I've also confirmed that certificate and key pair are created correctly by running the below commands.
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
Implementations
Server:
Program.cs file
var builder = WebApplication.CreateBuilder(args);
X509Certificate2 cert = new X509Certificate2("/Users/asimgunduz/server.crt", "/Users/asimgunduz/server.key");
builder.WebHost.ConfigureKestrel(opt =>
{
opt.Listen(IPAddress.Any, 5010, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1;
listenOptions.UseHttps(cert);
});
});
Client Side
public static void RegisterGrpcService<TService>(this IServiceCollection Services) where TService : class
{
X509Certificate2 certificate = new X509Certificate2("/Users/asimgunduz/server.crt", "/Users/asimgunduz/server.key");
var socketsHandler = new SocketsHttpHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,
KeepAlivePingDelay = TimeSpan.FromSeconds(60),
KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
EnableMultipleHttp2Connections = true,
};
socketsHandler.SslOptions.RemoteCertificateValidationCallback = (message, cert, chain, errors) =>
{
// Perform custom validation here and return a boolean indicating whether the certificate is valid
return certificate.Equals(cert);
};
var hand = new GrpcWebHandler(GrpcWebMode.GrpcWeb, socketsHandler);
//hand.HttpVersion = HttpVersion.Version11;
Services.AddCodeFirstGrpcClient<TService>(x =>
{
x.ChannelOptionsActions.Add(x => new GrpcChannelOptions
{
HttpHandler = hand,
MaxReceiveMessageSize = null, //30000000
MaxSendMessageSize = null, //30000000
Credentials = ChannelCredentials.Insecure,
UnsafeUseInsecureChannelCallCredentials = true,
ServiceConfig = new ServiceConfig { LoadBalancingConfigs = { new RoundRobinConfig() } }
});
x.Address = new Uri("http://localhost:5010");
})
.ConfigurePrimaryHttpMessageHandler(x => hand);
}
public static void RegisterGrpcServiceWithSsl2<TService>(this IServiceCollection services, string address) where TService : class
{
X509Certificate2 certificate = new X509Certificate2("/Users/asimgunduz/server.crt", "/Users/asimgunduz/server.key");
var handler = new SocketsHttpHandler
{
SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
{
X509Chain x509Chain = new X509Chain();
x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
bool isChainValid = x509Chain.Build(new X509Certificate2(cert));
return isChainValid;
},
ClientCertificates = new X509Certificate2Collection { certificate }
},
PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,
KeepAlivePingDelay = TimeSpan.FromSeconds(60),
KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
EnableMultipleHttp2Connections = true
};
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
HttpHandler = handler,
});
services.AddCodeFirstGrpcClient<TService>(x =>
{
x.Address = new Uri(address);
x.ChannelOptionsActions.Add(options =>
{
options.HttpHandler = handler;
});
});
}
When I run Server it throws the following exception
"The server mode SSL must use a certificate with the associated private key."
any help is much appreciated.
Aright after an hour of hard work, I've managed to make my code work: just leaving here in case future me or someone else needs it..
Changes made in my code
(SERVER) program.cs I've changed port number from 5010 => 7178
and this is How I updated my extension methods in client side