Not too long ago, I attended Mark Rendle’s session on gRPC in .NET. Being a bit, well, me, I decided to bring my Linux-based laptop. After all, .NET Core (and now .NET 5 and 6) supports Linux, so why not? Well, about 90 minutes into the session, I ran into a trouble that nobody else in the class had: certificate errors.

Summarizing the Error

The main error I received throughout this happened when trying to call a .NET service using gRPC. I could deploy the service just fine and have it listen, but when my web application tried to access the service, I would receive the following error:

AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot

To put it simply, .NET and Linux were okay with me connecting to my local web application via HTTPS, but when that local web application attempted to connect to the remote service (also on my laptop) via gRPC, I hit a problem with an untrusted root certificate. Now, you could potentially force gRPC to accept non-secured data, but that doesn’t seem like a reasonable answer, and so I went hunting for the true answer.

There’s a Command for That!

Fortunately, .NET has a great command: dotnet dev-certs https trust. If you run this command, it will take the development certificate that .NET uses and make it a trusted root certificate on your machine. That way, everything works beautifully…except for one small problem: it doesn’t work on Linux! The reason is that there is no central certificate store for Linux like there is for Windows. Different distributions and browsers have their own locations for these and .NET doesn’t even try to solve the problem for you.

That said, there are some instructions on how to do it. But if the instructions worked beautifully, I probably wouldn’t be writing this blog post…

Learning to Trust

I followed the instructions above but that still didn’t solve the problem. A bit more digging led me to a Stack Overflow question on the topic, and from there, a Boris Wilhelms blog post providing some guidance on what we need to do, as well as Boris’s GitHub repo which contains scripts to do the job.

I’m using Elementary OS, which is Ubuntu-based, so I ran the Ubuntu scripts. What the script does is that it creates two certificates: one for the current user and one for the root user (probably because I used sudo to run the script). After the script ran, I needed to open up my browser and go to the certificates section. Here it is in Brave, and that should be the same for any Chromium-based browser on Linux. First, navigate to the Settings page on your browser. Then, search for “manage certificates” and choose the Security option.

Looking for my certificates.

Inside there, select Manage Certificates.

Finding my certificates

This will allow you to import a certificate. The certificate you want is located in ~/.dotnet/corefx/cryptography/x509stores/my/{SHA}.pfx as a personal certificate, where {SHA} is the SHA thumbprint of your certificate. Select Import, bring it in, and you’ll see org-localhost show up here.

Importing my personal certificate

There’s one more step, and that is to add our root certificate as well. One of Boris’s steps is to register the certificate in /etc/ssl/certs/dotnet-devcert.pem, which is where it needs to be on Ubuntu. But if you read that certificate, you’ll see that it actually matches the one in /root/.dotnet/corefx/cryptography/x509stores/my/, not your personal certificate. Therefore, we need to register the pem file in the browser as well. You can do that by selecting the Authorities tab and importing /etc/ssl/certs/dotnet-devcert.pem.

Importing the root-based certificate

Restart the browser and the remote call should work when accessing your .NET web app through that browser. If you’re using a different browser, like Firefox, there are other locations for the certificate store, so this isn’t a one-size-fits-all solution.

If you want to dive a bit more into gRPC troubleshooting, Microsoft does have a guide which I found helpful.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s