I'm trying to connect a .Net Core API to my SSL protected MongoDB. I can connect using Mongo Compass so I am confident the problem is not in my MongoDB configuration.
Everything was working fine before the certificates were added to the MongoDB and as you'll see the stack points right to the certificates. I just don't know how to correct it.
I wasn't able to find a lot of documentation on how to implement the SslSettings in the MongoDB driver so I'm piecing this together from different sources and SO questions.
The problem seems to come when my API goes to connect to Mongo. I get the following exception.
Value cannot be null. (Parameter 'source')
The stack dump points right to the X509 certificates being the missing / null value.
at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Linq.Enumerable.Cast[TResult](IEnumerable source)
at MongoDB.Driver.SslSettings.X509CertificateCollectionEqualityComparer.Equals(X509CertificateCollection lhs, X509CertificateCollection rhs)
at MongoDB.Driver.SslSettings.Equals(Object obj)
at System.Object.Equals(Object objA, Object objB)
at MongoDB.Driver.ClusterKey.Equals(Object obj)
at System.Collections.Generic.ObjectEqualityComparer`1.Equals(T x, T y)
at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
at MongoDB.Driver.ClusterRegistry.GetOrCreateCluster(ClusterKey clusterKey)
at MongoDB.Driver.MongoClient..ctor(MongoClientSettings settings)
at MongoDB.Driver.MongoClient..ctor(String connectionString)
at Bullies.API.Endpoints.Users.UserService..ctor(IOptions`1 config, IMediator mediator) in C:\Users\...\Demo.API\Endpoints\Users\UserService.cs:line 38
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Demo.API.HostedServices.SubscriptionHostedService.<ExecuteAsync>d__2.MoveNext() in C:\Users\...\Demo.API\HostedServices\SubscriptionHostedService.cs:line 32
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__9.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Demo.API.Program.Main(String[] args) in C:\...\Demo.API\Program.cs:line 22
appsettings.json connection string
mongodb://user:pass@localmongo:12345/MyDb?authSource=admin&readPreference=primary&appname=demoapi&ssl=true
AccessMongoClass.cs
MongoCredential creds = MongoCredential.CreateMongoCRCredential("localmongo:12345", "user", "pass");
var clientCertificate = new List<X509Certificate>()
{ new X509Certificate("Path\\...\\mysite_com.pfx", "privateKeyPassword") };
MongoClientSettings settingz = new MongoClientSettings();
settingz.ApplicationName = "demo-api";
settingz.Credential = creds;
settingz.SslSettings = new SslSettings()
{
CheckCertificateRevocation = false,
//EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12,
ClientCertificates = clientCertificate,
ClientCertificateSelectionCallback =
(sender, host, certificates, certificate, issuers) => clientCertificate.ToList()[0],
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true
};
MongoClient client = new MongoClient(settingz);
On the mongodb side I see this error:
"ctx":"conn7","msg":"Interrupted operation as its client disconnected","attr":{"opId":1731}}
The Mongo log is VERY long so I'm just picking out what I think is the key line. If you want to see something else I can easily add it.
I would have thought I provided the X509 certificates but clearly I'm missing something.