Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
beliakov-mb opened this issue Jun 6, 2024 · 5 comments

Comments

@beliakov-mb
Copy link

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.

@roji
Copy link
Member

roji commented Jun 6, 2024

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.

@beliakov-mb
Copy link
Author

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.

@roji
Copy link
Member

roji commented Jun 6, 2024

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.

@beliakov-mb
Copy link
Author

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.

@roji
Copy link
Member

roji commented Jun 7, 2024

@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.

@roji roji closed this as not planned Won't fix, can't repro, duplicate, stale Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants