npgsql / efcore.pg

Entity Framework Core provider for PostgreSQL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: Correct way to rotate database credentials when using a datasource

beliakov-mb opened this issue · comments

What is the correct way to rotate login and password when using a datasource? I am using an external system (vault) for credential rotation and faced the following issue:

I create a new datasource every time the credentials change, but this causes the EF model to be rebuilt, which affects performance and breaks other logic in my application. I have seen that the password can be changed on the datasource using a timer, but I need to change both the login and the password, so that doesn't work for me.

Previously, I used the method DbContext.Database.SetConnectionString("connectionString"), but now I need to use TypeResolverFactory and I am forced to use a datasource.

Thank you very much for your assistance.

I have seen that the password can be changed on the datasource using a timer, but I need to change both the login and the password, so that doesn't work for me.

Can you point to the system which requires the username to be rotated? I'm not familiar with this requirement. Typically the same data source can be used while rotating passwords (via a timer), but this doesn't support usernames (again, we've never seen a requirement for that).

but this causes the EF model to be rebuilt, which affects performance and breaks other logic in my application.

A new data source shouldn't mean that the EF model needs to be rebuilt - you should be able to initialize a DbContext with two different data sources, and for them to still use the same EF model without rebuilding.

Previously, I used the method DbContext.Database.SetConnectionString("connectionString"), but now I need to use TypeResolverFactory and I am forced to use a datasource.

You can still register TypeResolverFactory on NpgsqlConnection.GlobalTypeMapper just like you're doing on NpgsqlDataSourceBuilder; this creates an obsoletion warning but you can absolutely still do it.

Can you point to the system which requires the username to be rotated? I'm not familiar with this requirement. Typically the same data source can be used while rotating passwords (via a timer), but this doesn't support usernames (again, we've never seen a requirement for that).

We use HashiCorp Vault. Credentials are created at a certain interval. Since the credential update is not synchronous, we cannot change the password for an account; instead, we create a new account with a new password.

A new data source shouldn't mean that the EF model needs to be rebuilt - you should be able to initialize a DbContext with two different data sources, and for them to still use the same EF model without rebuilding.

I am using the method DbContextOptionsBuilder.UseNpgsql(datasource) in the DbContext.OnConfiguring() method. This causes the model to be recreated (EF 7). I would appreciate it if you could suggest how to avoid recreating the model.

You can still register TypeResolverFactory on NpgsqlConnection.GlobalTypeMapper just like you're doing on NpgsqlDataSourceBuilder; this creates an obsoletion warning but you can absolutely still do it.

Our team is concerned that this method is marked as obsolete.

Can you point to the system which requires the username to be rotated? I'm not familiar with this requirement. Typically the same data source can be used while rotating passwords (via a timer), but this doesn't support usernames (again, we've never seen a requirement for that).

We use HashiCorp Vault. Credentials are created at a certain interval. Since the credential update is not synchronous, we cannot change the password for an account; instead, we create a new account with a new password.

Can you point to e.g. HashiCorp resources documenting/recommending this practice? If this is a best practice, we can consider allowing rotating the username on NpgsqlDataSource much like we support rotating the password currently.

You can still register TypeResolverFactory on NpgsqlConnection.GlobalTypeMapper just like you're doing on NpgsqlDataSourceBuilder; this creates an obsoletion warning but you can absolutely still do it.

Our team is concerned that this method is marked as obsolete.

It's indeed discouraged, but this method works and will not be removed in the near future - so you can use it as a workaround if other methods fail.

A new data source shouldn't mean that the EF model needs to be rebuilt - you should be able to initialize a DbContext with two different data sources, and for them to still use the same EF model without rebuilding.

I am using the method DbContextOptionsBuilder.UseNpgsql(datasource) in the DbContext.OnConfiguring() method. This causes the model to be recreated (EF 7). I would appreciate it if you could suggest how to avoid recreating the model.

Right, in EF 8 (and 7), the data source is managed as a "singleton option", which means that different data sources cause different EF service providers to get created, and the model cache is stored there. So indeed, by default different data sources would cause the model to be rebuilt.

In 9 (in preview), we just merged a change (#3167) that stops the data source from being a singleton option, so that shouldn't be a problem there. I'd probably recommend using the obsolete NpgsqlConnection.GlobalTypeMapper (see above) for now, until 9 is released and the problem goes away.

Otherwise, even with 7/8 you should be able to generate the EF model yourself (this isn't very difficult), and then pass it to the DbContext configuration via UseModel() - that should allow reusing the same model across all your DbContexts regardless of the data source.

Can you point to e.g. HashiCorp resources documenting/recommending this practice? If this is a best practice, we can consider allowing rotating the username on NpgsqlDataSource much like we support rotating the password currently.

We use dynamic credentials. Dynamic login is important for us, including from a security perspective. For example, here is a tutorial about dynamic secrets from HashiCorp Vault, where both the login and password are rotated.

Thank you for your detailed response regarding the EF model. We have decided to use GlobalTypeMapper.

@beliakov-mb thanks for the link, I've opened npgsql/npgsql#5745 to track allowing username rotation at the Npgsql level as well.

I think using GlobalTypeMapper makes sense for now - when you transition to EFCore.PG you should be able to go back to switching data sources, as that should no longer cause a model rebuild etc.