3

Scenario:

  1. Web Api application in NET Core 2.2, it is deployed on multiple containers.
  2. In Startup, I read from the database password from HashiCorp Vault and put it into my connection string.
  3. I add the Entity Framework Core context to the Service Collection.
  4. I use the context in multiple controllers.

If I change the database password in Vault, all the the requests to the database will fail due to authentication errors.

I can bring all the containers down and when they restart they will have the new password, but that is not what I want to do. There are a few hacky ways of getting around this problem but they involve not using the Service Collection and I want to use it.

Question:

Does EF Core support password rotation, or is there a way to achieve this while still using the Service Collection?

Bryan
  • 5,065
  • 10
  • 51
  • 68
  • Are you basically asking on how to control db context connection string at runtime? – Vidmantas Blazevicius Apr 26 '19 at 20:16
  • That the context resides in the service collection is a big part of this, and there is also a concern about failed requests when the password changes. So it is more than just changing the connection string at runtime. But if you have a suggestion on doing that, it might be helpful. – Bryan Apr 26 '19 at 20:46
  • 1
    So you can just add a dbcontext as transient service and pass a delegate which would create the instance of the db context. This way you would remove the static nature of connection string and would be able to take control of db context object creation at runtime. – Vidmantas Blazevicius Apr 26 '19 at 20:58
  • Interesting, if you have a one or two liner example, please add it an answer and I'll try it out and accept if it works. Thanks. – Bryan Apr 26 '19 at 21:05
  • 2
    You've already marked an answer, but the solution [here](https://stackoverflow.com/questions/54490808/configure-connection-string-from-controller-asp-net-core-mvc-2-1/54497955#54497955) may also be interesting for you. I think that when the password changes, the IOptions will replace it automatically. –  Apr 30 '19 at 21:47
  • Thanks @RuardvanElburg – Bryan May 09 '19 at 15:18

3 Answers3

3

You should be able to add the DbContext into DI and pass a delegate which creates the instance essentially taking control of the static nature of the connection string and work out the correct one at runtime.

services.AddScoped<YourDbContext>(svc =>
     {
         var connString = ... logic to get the conn string with the right password from HashiCorp vault;
         var dbContextOptions = new DbContextOptionsBuilder<YourDbContext>();
         dbContextOptions.UseSqlServer(connString); //Or w/e ef provider for db you use
         return new YourDbContext(dbContextOptions.Options);
     });
Vidmantas Blazevicius
  • 4,652
  • 2
  • 11
  • 30
1

Since the database password is read from HashiCorp vault during the start up, perhaps you could consider using healthcheck feature (https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-2.2) to set up a live health check endpoint.

Then use your container management tool to probe the endpoint and restart the container should it fails (i.e., unable to connect to the DB due to connection string being obsolete).

frostshoxx
  • 538
  • 1
  • 7
  • 24
1

The simplest solution is to get the username and password from the vault. Then treat it like a key rotation, switching the config to a different username/password, and waiting for the app to stop using the old credentials before changing the password.

Another approach is to re-fetch the credentials before retrying after a failure.

David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67