I've been looking through several examples of encrypting connectionStrings (Web.config) in an ASP.NET MVC application (.NET 4.0) and it seems that there are two general ways to achieve it (example 1 and the related example 2):
Use the aspnet_regiis tool.
The main issue with using aspnet_regiis is that I can run the tool locally (on my development machine), but the web site actually hosted on Arvixe and like any other web host: there is no way to run commands on the server. As far as I understand, if I encrypt the Web.config connectionStrings on my machine and publish the Web.config, then they can't be decrypted on the server (please correct me if this is wrong).
Note: I only used the RSAProtectedConfigurationProvider
, but I assume that the DataProtectionConfigurationProvider
will have the same issue since it's user/machine specific.
Programatically encrypt the connection string.
Programmatically encrypting the connectionStrings also has a drawback: every time I publish my web site the Web.config is updated (with the unencrypted connectionStrings) and this means that for some period of time the Web.config will not be encrypted. Even if I ensure that the Web.config is only published when there are changes to it, the issue may be minimized but not mitigated.
I thought that using a static class may further help reduce the time connectionStrings are not encrypted. Unfortunately, encrypting the connectionStrings requires the application path and it seems that the only way to get the app path is from the request (Request.ApplicationPath
) and in a static class there is (obviously) no request.
private void ProtectSection(string sectionName,
string provider)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section =
config.GetSection(sectionName);
if (section != null &&
!section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection(provider);
config.Save();
}
}
private void UnProtectSection(string sectionName)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section =
config.GetSection(sectionName);
if (section != null &&
section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
config.Save();
}
}
UnProtectSection("appSettings");
ProtectSection("appSettings",
"DataProtectionConfigurationProvider");
What's the proper way to encrypt the connectionString and eliminate/reduce the amount of time the Web.config section is not encrypted? Do you write some type of a wrapper around the OpenWebConfiguration
method which check if the section is encrypted and only use that wrapper? Users may access any page on your web site, so how do you delay the encryption until they request some data from a database or do you check if it's encrypted at the first opportunity?