dotnet / wcf

This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
MIT License
1.71k stars 558 forks source link

Unable to use CreateMutualCertificateBindingElement #5615

Open ShlomiKo opened 3 months ago

ShlomiKo commented 3 months ago

Describe the bug I'm trying to migrate a project using WCF from .net 4.5 to .net 8 Must of it is already migrated but I am facing a problem in implementing the CreateMutualCertificateBindingElement functionality. From the docs it looks like it should be supported in the latest .net 8 version with the latest 8.0 package image

but when I try to implement it in the code it does not find the CreateMutualCertificateBindingElement implementation. image

What am I missing here? Any help will be greatly appreciated.

To Reproduce Steps to reproduce the behavior:

  1. Create a .net 8 console app
  2. dotnet add package System.ServiceModel.Primitives --version 8.0.0
  3. try to create the security binging element - SecurityBindingElement security = SecurityBindingElement.CreateMutualCertificateBindingElement();
mconnew commented 3 months ago

The docs say this method is supported because the documentation scanning/publishing process behind the dotnet docs was mistakenly scanning the System.Private.ServiceModel package from the 4.10.3 release. This package isn't present on the latest releases, but when it was being released it contained the actual implementation, and each of our packages type forwarded to it. It contained some api's which weren't implemented yet because in the past a lot of code was copied over inelegantly and the pieces that weren't implemented just stubbed out with a PlatformNotSupportedException. Part of the reason for this is to make lighting up those features easier. For example, BasicHttpMessageSecurity has code that if you set the right options will try to call this method. The idea being once it's implemented, all the call points are still there. It turns out that wasn't a great time saving and just made it harder to see what's supported when reading the code so that's not done any more.
We made sure anything in the reference assembly of the non-private packages (e.g. System.ServiceModel.Primitives) is implemented. There were a few exceptions, eg around configuration, but this mostly holds true, and we marked those api's as obsolete (they've since been removed in 8.0). By scanning the private package, some api's were marked as present when they really aren't.

We're currently working on fixing the documentation situation and it should be correctly reflected as only available for .NET Framework in the next few weeks.

As for making this api available, it requires full message security support which we don't have. We haven't got to porting it yet as this area of the code requires quite a bit of rework. .NET Framework WCF uses an internal implementation of SignedXml, owned by a different team who aren't planning to port it to .NET, so I reworked WCF Client to use the .NET runtime System.Security.Cryptography.Xml.SignedXml implementation instead. This works fine for TransportWithMessageCredential, but to support full message security, we need to support for STR-Transform. The .NET Framework implementation has a cheater implementation and does it without applying a transform. There isn't an implementation for the runtime SignedXml. I either need to work out a cheater implementation to using with the runtime SigneXml, or implement it using STR-Transform.

If you have the flexibility of modifying your binding, you could switch to using TransportWithMessageCredential as that can mutually validate the certificate. The main purpose of using Message with mutual cert auth is to have intermediaries (such as a network border reverse proxy) not hide the auth info (SSL terminating host is the one which gets to see the remotes certificate, not the forwarded to host), or it's to enable the message to be stored and read later keeping the auth info with the body. E.g. putting it in some queue storage (eg MSMQ) or saving to disk/blob storage. If you don't have either of these scenarios, you have equivalent security using either Transport security with client certificates, or TransportWithMessageCredential.

ShlomiKo commented 3 months ago

@mconnew Thank you for the detailed answer. Unfortunately we do have this constraint and we must use that binding since we are working and integrating with a legacy gov software and this is mandatory on their end. Given this constraint, can you help with any solution or direction of still porting to .net 8 or are we stuck on .net 4.5 in this case?