- ABP Framework version: v9.0.4
- UI Type: Blazor WASM
- Database System: MongoDB
- Tiered (for MVC) or Auth Server Separated (for Angular): yes/no
- Exception message and full stack trace:
- Steps to reproduce the issue:
I don't find a way to connect into my mongo atlas cluster using a authMechanism=MONGODB-X509 like in this example with standard MongoDB.Driver Version="2.30.0"
//.... var connectionString ="mongodb+srv://xx-mongo.xx.mongodb.net/xx-app-db?retryWrites=true&w=majority&appName=xx-mongo&tls=true&authMechanism=MONGODB-X509"; var settings = MongoClientSettings.FromConnectionString(connectionString); settings.ServerApi = new ServerApi(ServerApiVersion.V1); var cert = new X509Certificate2("atlas-user-cert.pfx","changeit"); settings.SslSettings = new SslSettings { ClientCertificates = new List<X509Certificate>() { cert } }; var client = new MongoClient(settings);
//......
Can you help me?
Thanks Giuseppe
5 Answer(s)
-
0
hi
Can you connect your MongoDB in another app/code?
Do you have any example code of
authMechanism=MONGODB-X509
?Thanks.
-
0
Yes follow a console app that works fine whith the same cluster
using MongoDB.Bson; using MongoDB.Driver; using System; using System.IO; using System.Threading.Tasks; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using AtlasCertConnection; using AtlasCertConnection.Model.Report; using MongoDB.Driver.Linq; using TransitalyApp.Shipments; using AtlasCertConnection.Model.Types; using System.Linq; using AtlasCertConnection.Data; using AtlasCertConnection.Model; using MongoDB.Bson.Serialization; class Program { static void Main(string[] args) { BsonSerializer.RegisterSerializationProvider( new CustomTypeSerializationProvider()); MainAsync().Wait(); } static async Task MainAsync() { var connectionString = "mongodb+srv://ibl-mongo.dizxt.mongodb.net/tri-app-db?retryWrites=true&w=majority&appName=ibl-mongo&tls=true&authMechanism=MONGODB-X509&authSource=%24external"; var settings = MongoClientSettings.FromConnectionString(connectionString); settings.ServerApi = new ServerApi(ServerApiVersion.V1); var cert = new X509Certificate2( "C:\\projects\\development\\IBL\\Trabsitaly\\TransitalyApp\\src\\TransitalyApp.HttpApi.Host\\atlas-user-cert.pfx", "changeit"); settings.SslSettings = new SslSettings { ClientCertificates = new List<X509Certificate>() { cert } }; var client = new MongoClient(settings); var database = client.GetDatabase("tri-app-db"); var collection = database.GetCollection<Shipment>("AppShipments"); var deliveryMinDateThreshold = new DateTime(2025, 3, 1); var deliveryMaxDateThreshold = new DateTime(2026, 3, 1); var result = collection.Aggregate<Shipment>() .Match(Builders<Shipment>.Filter.And( Builders<Shipment>.Filter.Eq("Status", "DELIVERED"), Builders<Shipment>.Filter.Gte("DeliveryExecutedDate", deliveryMinDateThreshold), Builders<Shipment>.Filter.Lte("DeliveryExecutedDate", deliveryMaxDateThreshold) )) .Sort(new BsonDocument("CreationTime desc", 1)) .Skip(0) .Limit(2000).ToList() ?? []; Console.WriteLine(result.Count); result = PatchNotifyRecipient(result); ShippingCostCalculator.GenerateReport(result); } private static List<Shipment> PatchNotifyRecipient(List<Shipment> result) { result.ForEach(shipment => { if (shipment.AccessoryServices.FirstOrDefault(s => s.Type == AccessoryServiceType.NOTIFY_RECIPIENT) is null) { shipment.AccessoryServices.Add(new AccessoryService { Type = AccessoryServiceType.NOTIFY_RECIPIENT, Description = "Call" }); } }); return result; } }
-
0
hi
You can override the
UnitOfWorkMongoDbContextProvider's CreateMongoClient
method to change the code of creatingMongoClient
.Add
YourUnitOfWorkMongoDbContextProvider : UnitOfWorkMongoDbContextProvider
Then replace it in DI.
context.Services.TryAddTransient( typeof(IMongoDbContextProvider<>), typeof(UnitOfWorkMongoDbContextProvider<>) );
https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs#L300-L306
var connectionString = "mongodb+srv://ibl-mongo.dizxt.mongodb.net/tri-app-db?retryWrites=true&w=majority&appName=ibl-mongo&tls=true&authMechanism=MONGODB-X509&authSource=%24external"; var settings = MongoClientSettings.FromConnectionString(connectionString); settings.ServerApi = new ServerApi(ServerApiVersion.V1); var cert = new X509Certificate2("C:\\projects\\development\\IBL\\Trabsitaly\\TransitalyApp\\src\\TransitalyApp.HttpApi.Host\\atlas-user-cert.pfx", "changeit"); settings.SslSettings = new SslSettings { ClientCertificates = new List<X509Certificate>() { cert } }; var client = new MongoClient(settings);
-
0
the complete solution for future framework improvement:
`using System; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MongoDB.Driver; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; using Volo.Abp.Data; using Volo.Abp.MongoDB; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Uow; using Volo.Abp.Uow.MongoDB;
public class X509CertificateUnitOfWorkMongoDbContextProvider
public X509CertificateUnitOfWorkMongoDbContextProvider(IUnitOfWorkManager unitOfWorkManager, IConnectionStringResolver connectionStringResolver, ICancellationTokenProvider cancellationTokenProvider, ICurrentTenant currentTenant, IOptions<AbpMongoDbContextOptions> options, IMongoDbContextTypeProvider dbContextTypeProvider, IConfiguration configuration) : base(unitOfWorkManager, connectionStringResolver, cancellationTokenProvider, currentTenant, options, dbContextTypeProvider) { _configuration = configuration; this.SetX509AuthenticationMechanism(); } private void SetX509AuthenticationMechanism() { var connectionString = _configuration["ConnectionStrings:Default"]; if (connectionString is not null && connectionString.Contains("authMechanism=MONGODB-X509")) { useX509Certificate = true; this._certPassword = Guid.NewGuid().ToString(); var certFilePath = _configuration["ConnectionStrings:X509Certificate:CertFile"]; var keyFilePath = _configuration["ConnectionStrings:X509Certificate:KeyFile"]; this._certificate = LoadCertificateFromPem(certFilePath, keyFilePath); } } protected override MongoClient CreateMongoClient(MongoUrl mongoUrl) { var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl); if (useX509Certificate) { try { mongoClientSettings.ServerApi = new ServerApi(ServerApiVersion.V1); mongoClientSettings.SslSettings = new SslSettings { ClientCertificates = new List<X509Certificate>() { _certificate }, }; Options.MongoClientSettingsConfigurer?.Invoke(mongoClientSettings); return new MongoClient(mongoClientSettings); } catch (Exception e) { Logger.LogError(e, "Error while creating MongoClient with X509 certificate"); throw; } } return base.CreateMongoClient(mongoUrl); } /// <summary> /// Load X509 certificate from PEM file /// </summary> private X509Certificate2 LoadCertificateFromPem(string? pemFilePath, string? keyFilePath) { if (pemFilePath is null || keyFilePath is null || !File.Exists(pemFilePath) || !File.Exists(keyFilePath)) { throw new FileNotFoundException($"PEM or Key file not found at {pemFilePath} or {keyFilePath}"); } var certificate = X509Certificate2.CreateFromPemFile(pemFilePath, keyFilePath); return new X509Certificate2(certificate.Export(X509ContentType.Pfx, _certPassword), _certPassword); }
}`
to replace in a correct way the provider use this code:
private void ConfigureMongoX509CertificateProvider(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.Replace(ServiceDescriptor.Transient( typeof(IMongoDbContextProvider<>), typeof(X509CertificateUnitOfWorkMongoDbContextProvider<>))); }
Thanks Giuseppe
-
0
Many Thanks Giuseppe