Open Closed

Replace default connection string to Azure Key Vault #2900


User avatar
0
hein.pauwelyn@savaco.com created

We've uploaded my ABP Framework site to an Azure Web application but the default connection string is stored inside the configuration of the web app. Now we want to replace that to an Azure Key Vault and store only the URL inside the configuration.

Where using this code:

using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using System;

namespace OurNamespace.Utils
{
    public static class AppAzureKeyVaultConfigurer
    {
        public static IConfigurationBuilder ConfigureAzureKeyVault(this IConfigurationBuilder builder, string azureKeyVaultUrl)
        {
            SecretClient keyVaultClient = new SecretClient(
                new Uri(azureKeyVaultUrl),
                new DefaultAzureCredential()
            ); 
            
            AzureKeyVaultConfigurationOptions options = new AzureKeyVaultConfigurationOptions()
            {
                ReloadInterval = TimeSpan.FromHours(1)
            };

            return builder.AddAzureKeyVault(keyVaultClient, options);
        }
    }
}

Inside the Program class of the OurNamespace.HttpApi.Host project, next code will be called:

internal static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .AddAppSettingsSecretsJson()
        .ConfigureAppConfiguration(build =>
        {
            IConfigurationBuilder configuration = build
                .AddJsonFile("appsettings.secrets.json", optional: true)
                .ConfigureAzureKeyVault("☺ --> the url to the key vault");
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
        .UseAutofac()
        .UseSerilog();

To get the assess token inside the OurApplicationDbContext:

[ReplaceDbContext(typeof(IIdentityProDbContext), typeof(ISaasDbContext), typeof(ILanguageManagementDbContext), typeof(IAuditLoggingDbContext), typeof(ITextTemplateManagementDbContext), typeof(IIdentityServerDbContext), typeof(IPaymentDbContext), typeof(IPermissionManagementDbContext), typeof(ISettingManagementDbContext), typeof(IFeatureManagementDbContext), typeof(IBackgroundJobsDbContext), typeof(IBlobStoringDbContext))]
[ConnectionStringName("Default")]
public class OurApplicationDbContext : AbpDbContext<OurApplicationDbContext>, IOurApplicationDbContext, IIdentityProDbContext, ISaasDbContext, ILanguageManagementDbContext, IAuditLoggingDbContext, ITextTemplateManagementDbContext, IIdentityServerDbContext, IPaymentDbContext, IPermissionManagementDbContext, ISettingManagementDbContext, IFeatureManagementDbContext, IBackgroundJobsDbContext, IBlobStoringDbContext
{
    private readonly IConfiguration _configuration;

    // All implementations of all interfaces here

    public OurApplicationDbContext(DbContextOptions<OurApplicationDbContext> options, IConfiguration configuration)
        : base(options)
    {
        _configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured) // <-- also a break point here will not be hit.
            optionsBuilder.UseSqlServer(_configuration.GetConnectionString("Default"));
    }
}

Inside the appsettings.json the Connectionstring:Default is removed because it must be taken from the Key Vault.

Also in the DbContext of the OurNamespace.EntityFrameworkCore project, all these DbContexts are replaced:

  • IIdentityProDbContext
  • ISaasDbContext
  • ILanguageManagementDbContext
  • IAuditLoggingDbContext
  • ITextTemplateManagementDbContext
  • IIdentityServerDbContext
  • IPaymentDbContext
  • IPermissionManagementDbContext
  • ISettingManagementDbContext
  • IFeatureManagementDbContext
  • IBackgroundJobsDbContext
  • IBlobStoringDbContext

It will give next error:

ArgumentNullException: Value cannot be null. (Parameter connectionString)

DependencyResolutionException: An exception was thrown while activating: Volo.Abp.LanguageManagement.EntityFrameworkCore.ILanguageManagementDbContextOurNamespace.EntityFrameworkCore.OurApplicationDbContextMicrosoft.EntityFrameworkCore.DbContextOptions<OurNamespace.EntityFrameworkCore.OurApplicationDbContext>.

Specifications

  • ABP Framework version: 5.0.0
  • UI type: Angular
  • DB provider: EF Core

5 Answer(s)
  • User Avatar
    1
    EngincanV created
    Support Team .NET Developer

    Hi, I guess you are storing your connection string as a user secret. Can you replace the Default keyword with your user secret key on your ConnectionStringName attribute?

    It's defined top of your DbContext class:

    [ConnectionStringName("<user-secret-key>")]
    public class MyProjectNameDbContext {}
    
  • User Avatar
    0
    hein.pauwelyn@savaco.com created

    Hi, I guess you are storing your connection string as a user secret. Can you replace the Default keyword with your user secret key on your ConnectionStringName attribute?

    It's defined top of your DbContext class:

    [ConnectionStringName("<user-secret-key>")] 
    public class MyProjectNameDbContext {} 
    

    By adding [ConnectionStringName("Default")] to the DbContext I can see that the break point inside the ConfigureAzureKeyVault method is hit but the error is not solved. Same error.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Did you also change the _configuration.GetConnectionString("Default") to _configuration.GetConnectionString("<user-secret-key>")?

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured) 
                optionsBuilder.UseSqlServer(_configuration.GetConnectionString("<user-secret-key>"));
        }
    
  • User Avatar
    0
    hein.pauwelyn@savaco.com created

    Did you also change the _configuration.GetConnectionString("Default") to _configuration.GetConnectionString("<user-secret-key>")?

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        { 
            if (!optionsBuilder.IsConfigured)  
                optionsBuilder.UseSqlServer(_configuration.GetConnectionString("<user-secret-key>")); 
        } 
    

    Both keys are the same. See the code from the question.

    Breakpoints inside OnConfiguring will not be hit.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Hi, to ensure the Azure Key Vault configurations are correct, can you run your project in DEBUG mode and try to obtain your value (any value that you've defined in Azure) from the IConfiguration interface?

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11