24

Is there a way where I can add a connection string to the ConnectionStringCollection returned by the ConfigurationManager at runtime in an Asp.Net application?

I have tried the following but am told that the configuration file is readonly.

ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings(params));

Is there another way to do this at runtime? I know at design time I can add a connection string to the web.config; however, I'm looking to add something to that collection at run time.

Thanks

EDIT: One of the reasons why I'm attempting to do this is due to a security requirement that prevents me from placing ConnectionStrings in the web.config (even encrypted). I would like to use elements like Membership and Profiles on my project; however, I am looking into an alternative to doing such w/o writing a custom provider. Custom Provider's aren't all that bad, but if I can find an easier solution, I'm all for it.

JamesEggers
  • 12,885
  • 14
  • 59
  • 86
  • You can move the connection strings out of web.config. See Best practices for deploying passwords and other sensitive data to ASP.NET and Azure Websites http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure – RickAndMSFT Mar 17 '15 at 03:36

8 Answers8

38

You can use reflection to disable the private bReadOnly field (bad idea, etc.):

typeof(ConfigurationElementCollection)
    .GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(ConfigurationManager.ConnectionStrings, false);
ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings());

This is similar to the technique required to modify an existing connection string, and added as a comment there by Brian Rodgers.

user423430
  • 3,654
  • 3
  • 26
  • 22
  • Awesome hack! You are correct, this is a bad idea - but it does work for adding con strs. The motivation for the question is how to remove conStrs from web.config - which is a security best practice so the secrets don't leak out of the source code. See http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure for how to move them out ( Best practices for deploying passwords and other sensitive data to ASP.NET and Azure Websites) – RickAndMSFT Mar 20 '15 at 06:11
12
var cfg = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(@"/");
cfg.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings(params));

cfg.Save();

Be Advised this will cause your website to recycle since it modifies the config file. Check out http://msdn.microsoft.com/en-us/library/4c2kcht0(VS.80).aspx

c24w
  • 7,421
  • 7
  • 39
  • 47
JoshBerke
  • 66,142
  • 25
  • 126
  • 164
  • The motivation for the question was moving the connection string out of web.config - which is a security best practice because you don't want to leak secrets to everyone with access to the source code. See Best practices for deploying passwords and other sensitive data to ASP.NET and Azure Websites http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure – RickAndMSFT Mar 20 '15 at 06:12
11

Just to point out whoever gave you the "security requirement" that you can't place the connection string in the web.config is an idiot. The web.config can never be accessed by anything other than your application or remote access to the server.

This sounds entirely like a requirements problem and should be solved there.

Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
  • I've tried on this one. That particular requirement came from the team in charge of DMZ security and doesn't want to risk having it exposed in case of a machine breech...even in an encrypted state since they would have the machine key at that point in a worst case scenario as well. – JamesEggers Dec 10 '08 at 21:08
  • 3
    Hmm if they have breached that box, they'll find your SQL server soon enough...you have to have the connection string on the server in some form or another...this is a silly requirement – JoshBerke Dec 10 '08 at 21:20
  • I fully agree with Josh, once they root your webserver your database will be soon to follow. This is protected by proper intrusion detection systems that you have a change to disable your servers which is at that point the only fool proof solution to the database being compromised. – Chris Marisic Dec 10 '08 at 21:42
  • 2
    I feel your pain, but the credentials of the ASP.NET user needs to have the right to whatever method your code uses to get the connection string. So even if your custom code is getting the connection string from a remote server or via some webservice, the hacker will be able to use the same method. – joshperry Dec 11 '08 at 14:35
  • web.config is considered source code, and secrets should never be checked into source see Best practices for deploying passwords and other sensitive data to ASP.NET and Azure Websites http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure – RickAndMSFT Mar 17 '15 at 03:35
  • @RickAnd-MSFT that merely stores them in a *separate* config file. Nowhere did i say the connection strings **must** be recorded in your source control system. – Chris Marisic Mar 17 '15 at 14:22
  • *separate* config file virtually impossible to get into source control and our secrets out of source control. web.config is part of your source, are you saying it would not be under source control? The web.config with secrets can be accessed by everyone with access to your source control, which is why you move them out. – RickAndMSFT Mar 18 '15 at 18:02
  • You act as if you can't have a build process that merges in config data from a walled garden. They built the entire config transformation concept to directly achieve this. This question was just worded very poorly as the accepted answer contradicts the premise of the question which is to directly add the data to the web.config (which further validates my answer, it's idiotic to not put them in the web.config). Ultimately no matter what, the keys will exist on disk somewhere at sometime. Likely somewhere at all times to allow builds without human intervention. – Chris Marisic Mar 18 '15 at 20:26
  • Who is they? MS security recommends the approach I've documented. On private disk is better than public source. Read my Best practices for deploying passwords and other sensitive data to ASP.NET and Azure Websites http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure which has been vetted by the security team. Consider updating your answer which leaves leakage via GIT wide open. – RickAndMSFT Mar 20 '15 at 05:00
  • On my Azure build server, I use http://www.powershellcookbook.com/recipe/PukO/securely-store-credentials-on-disk to encrypt credentials to disk - but then I only have dev/test pw's, not production pw. Please update your response as your assertion "whoever gave you the "security requirement" that you can't place the connection string in the web.config is an idiot. The web.config can never be accessed by anything" is incorrect as it omits pw leakage via everyone with access to source, leakage via GIT, etc. – RickAndMSFT Mar 20 '15 at 06:02
  • @RickAnd-MSFT absolutely not changing my answer. You're conflating two entirely separate issues. Source control containing the keys vs the web.config containing the key. No where does this question talk about keeping the keys out of source control it was purely about keeping them out of the web.config itself which is ridiculous. The accepted answer to the question merely puts them in the web.config. Methods for keeping the keys out of source control are wholly unrelated to what was **specifically asked**. – Chris Marisic Mar 20 '15 at 16:57
  • Your assertion "The web.config can never be accessed by anything other than your application or remote access to the server." misses the leakage problem - no where do you point that out. No where do you say don't check web.config into source or the alternative use a transform that is not checked in. You are calling a security best practice "idiot" because you missed the leakage problem. – RickAndMSFT Mar 21 '15 at 19:39
  • @RickAnd-MSFT once again for the thousandth time, OP never once asked about how to not check keys into source control. Maybe that's what he meant, who knows? I don't have a crystal ball. I answered the question that was asked. – Chris Marisic Mar 23 '15 at 15:43
  • That's because he, like you, didn't know that leaks passwords. Now that you know it leaks passwords and you know your assertion "the "security requirement" that you can't place the connection string in the web.config is an idiot." is incorrect, why not update your answer. You should at least include, while IIS won't serve a .config file, you can leak PW's from source.Have you read my http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure - and if so, what part of it don't you understand? – RickAndMSFT Mar 24 '15 at 17:43
  • @Chris Marisic you assert "Ultimately no matter what, the keys will exist on disk somewhere at sometime. Likely somewhere at all times to allow builds without human intervention." That's incorrect. I use http://www.powershellcookbook.com/recipe/PukO/securely-store-credentials-on-disk to store encrypted PW on disk for unattended builds. – RickAndMSFT Mar 24 '15 at 17:51
  • @RickAnd-MSFT **your assumptions** are flatly wrong. Just stop. The OP specifically declined config encryption. Your solution of using Azure, guess what? Those keys are sitting on disk in Azure somewhere (hopefully encrypted).... "to allow builds without human intervention". You're conflating unrelated things over and over and over again. No where did I say **unencrypted keys** either. No matter how you do key management a person with sufficient permissions **always has access**. Even with config encryption the person who can pull the cert out of the box can decrypt the keys. – Chris Marisic Mar 25 '15 at 14:29
5

If you are trying to edit the connection strings in your web.config at runtime take a look at WebConfigurationManager.

If you are just trying to modify the configuration at runtime to inject a connection string then you are out of luck. The ConfigurationManager object tree is meant to be a direct reflection of the configuration files, if you were able to change that the state would then be inconsistent.

I would recommend creating a simple facade class that you could use to retrieve your connection strings. This way you could have the facade return a connection string from your on the fly collection or if one doesn't exist then it could grab it from the ConfigurationManager.

class ConnectionStringProvider
{
    Dictionary<string, System.Configuration.ConnectionStringSettings> _localStrings = new Dictionary<string, System.Configuration.ConnectionStringSettings>();

    public void AddLocalConnectionString(string name, string connstring)
    {
        System.Configuration.ConnectionStringSettings cs = new System.Configuration.ConnectionStringSettings(name, connstring);
        _localStrings.Add(name, cs);
    }

    public void RemoveLocalConnectionString(string name)
    {
        _localStrings.Remove(name);
    }

    public System.Configuration.ConnectionStringSettings this[string name] {
        get 
        { 
            return _localStrings.ContainsKey(name) ? _localStrings[name] : System.Configuration.ConfigurationManager.ConnectionStrings[name]; 
        }
    }
}

Or you could always go quite a bit heavier and use something like the Enterprise Library Configuration Block.

joshperry
  • 41,167
  • 16
  • 88
  • 103
2

Haven't tried it yet, but perhaps you can alter the value of an existing connection string at runtime? For example, instead of:

ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings(params));

Maybe you could do something like:

ConfigurationManager.ConnectionStrings["myconnection"].ConnectionString = "something";

If so, you could specify the connection string "variables" in config, but set them to false or empty connection strings:

<add name="myconnection" connectionString="SET AT RUNTIME" ... />
Scott Isaacs
  • 1,168
  • 7
  • 16
1

The configuration infrastructure supports very robust encryption through the Windows DataProtection API wich uses a machine specific key to encrypt the configuration sections. This way it would not be possible to read the encrypted data anywhere but on the machine where it was encrypted.

This is the same API that is used for the Government compliant drive/folder encryption in Windows. Would this stand up to your companies security requirements?

Either manually or through your deployment automation you can execute this command to encrypt the connectionStrings section of your web.config for a specific web application.

aspnet_regiis -pe "connectionStrings" -app "/MyCoolWebApplication" -prov "DataProtectionConfigurationProvider"
joshperry
  • 41,167
  • 16
  • 88
  • 103
1

If you are using MS SQL you can configure you web server to access the SQL Server via the windows authentication, so you never have to have any passwords at all in your webconfig, or even floating around in your application memory.

Kibbee
  • 65,369
  • 27
  • 142
  • 182
-2

No, you can't modify the config file at runtime, it isn't intended for that. Maybe you could use the Enterprise Libraries Configuration to do that.

ema
  • 5,668
  • 1
  • 25
  • 31
  • –1 that's not true at all, it just causes you your site to recycle. – Chris Marisic Mar 17 '15 at 14:28
  • Ohh..come on!! Sure that you can it's an xml file, but is a very bad practice. .NET hasn't an API to modify the config files....ask yourself why. "-) – ema Mar 18 '15 at 09:38
  • incorrect again, it absolutely has APIs for modifying the config files `OpenWebConfiguration/Save` http://stackoverflow.com/a/719941/37055 – Chris Marisic Mar 18 '15 at 20:21
  • Didn't know that. The answer is quite old and anyway I think (IMHO) that is not a good practice to follow. – ema Mar 19 '15 at 10:59
  • 1
    even the accepted answer here is `OpenWebConfiguration`, ironically i didn't scroll up before linking to another question. I certainly agree with you that *everyone* **should not** do this, but can't is an absolute. Absolutes are almost always wrong in every situation in software... unless it involves Oracle but I digress – Chris Marisic Mar 19 '15 at 18:15