Skip to content

Commit

Permalink
fix: NET462 requires TLS for GRPC to work (open-feature#72)
Browse files Browse the repository at this point in the history
Signed-off-by: Eliot Eikenberry <[email protected]>
  • Loading branch information
Wolftousen authored Aug 8, 2023
1 parent 33045cb commit 2322f43
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
38 changes: 29 additions & 9 deletions src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
Expand Down Expand Up @@ -539,30 +540,49 @@ private Service.ServiceClient BuildClientForPlatform(Uri url)

if (!useUnixSocket)
{
#if NET462
#if NET462_OR_GREATER
var handler = new WinHttpHandler();
#else
var handler = new HttpClientHandler();
#endif
if (_config.UseCertificate)
{
#if NET5_0_OR_GREATER
if (File.Exists(_config.CertificatePath)) {
if (File.Exists(_config.CertificatePath))
{
X509Certificate2 certificate = new X509Certificate2(_config.CertificatePath);
#if NET5_0_OR_GREATER
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, _) => {
// the the custom cert to the chain, Build returns a bool if valid.
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.CustomTrustStore.Add(certificate);
return chain.Build(cert);
};
} else {
throw new ArgumentException("Specified certificate cannot be found.");
}
#elif NET462_OR_GREATER
handler.ServerCertificateValidationCallback = (message, cert, chain, errors) => {
if (errors == SslPolicyErrors.None) { return true; }
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
chain.ChainPolicy.ExtraStore.Add(certificate);
var isChainValid = chain.Build(cert);
if (!isChainValid) { return false; }
var isValid = chain.ChainElements
.Cast<X509ChainElement>()
.Any(x => x.Certificate.RawData.SequenceEqual(certificate.GetRawCertData()));
return isValid;
};
#else
// Pre-NET5.0 APIs for custom CA validation are cumbersome.
// Looking for additional contributions here.
throw new ArgumentException("Custom certificate authorities not supported on this platform.");
throw new ArgumentException("Custom Certificates are not supported on your platform");
#endif
}
else
{
throw new ArgumentException("Specified certificate cannot be found.");
}
}
return new Service.ServiceClient(GrpcChannel.ForAddress(url, new GrpcChannelOptions
{
Expand Down
1 change: 1 addition & 0 deletions src/OpenFeature.Contrib.Providers.Flagd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ The URI of the flagd server to which the `flagd Provider` connects to can either

Note that if `FLAGD_SOCKET_PATH` is set, this value takes precedence, and the other variables (`FLAGD_HOST`, `FLAGD_PORT`, `FLAGD_TLS`, `FLAGD_SERVER_CERT_PATH`) are disregarded.

Note that if you are on `NET462` through `NET48` as the target framework for your project, you are required to enable TLS and supply a certificate path as part of your configuration. This is a limitation Microsoft has [documented](https://learn.microsoft.com/en-us/aspnet/core/grpc/netstandard?view=aspnetcore-7.0#net-framework).

If you rely on the environment variables listed above, you can use the empty constructor which then configures the provider accordingly:

Expand Down

0 comments on commit 2322f43

Please sign in to comment.