Wednesday, September 26, 2007

Encrypting web.config using asp.net 2.0 on Server 2003

Okay,

This is one that has caused me lots of angst, and while there were a number of items that seemed to key in on various concepts that seemed to help, I continued to have problems.

Let me explain the problem as I experienced it first.

I set up the web site on a windows server 2003 OS. We don't like to put the root web into the c:\inetpub directory, so we set the directory of the root web to a different drive and location on the server. The web site was up and running, and everything was working fine, so I decided it was time to apply encryption to the web.config file.

All my research (and experience on my local PC) showed me that I could encrypt the string using the following command


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pe "connectionStrings"


So, I ran this on the server, and got the "success" feedback that I craved so much.

I ran the web, and nothing happened. Eventually my browser timed out and told me something was wrong, I looked at the application logs, and got an error like the following (# characters used to mask irrelevant or private data):



Event Type: Warning
Event Source: ASP.NET 2.0.50727.0
Event Category: Web Event
Event ID: 1310
Date: #########
Time: #########
User: N/A
Computer: #########
Description:
Event code: 3008
Event message: A configuration error has occurred.
Event time: #########
Event time (UTC): #############
Event ID: 9dc3f709f3e74c61a16c4a29f3883def
Event sequence: 13
Event occurrence: 6
Event detail code: 0

Application information:
Application domain: /LM/W3SVC/782218475/Root-2-128352878489375000
Trust level: Full
Application Virtual Path: /
Application Path: ##############
Machine name: #############

Process information:
Process ID: 2948
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE

Exception information:
Exception type: ConfigurationErrorsException
Exception message: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened. (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Config\web.config line 75)

Request information:
Request URL: #############
Request path: ################
User host address: ############
User:
Is authenticated: False
Authentication Type:
Thread account name: NT AUTHORITY\NETWORK SERVICE

Thread information:
Thread ID: 1
Thread account name: NT AUTHORITY\NETWORK SERVICE
Is impersonating: False
Stack trace: at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)
at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey, Boolean getLkg, Boolean checkPermission)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Web.Configuration.RuntimeConfig.GetSectionObject(String sectionName)
at System.Web.Configuration.RuntimeConfig.GetSection(String sectionName, Type type, ResultsIndex index)
at System.Web.Configuration.RuntimeConfig.get_RoleManager()
at System.Web.Security.Roles.get_Enabled()
at System.Web.Security.RoleManagerModule.Init(HttpApplication app)
at System.Web.HttpApplication.InitModulesCommon()
at System.Web.HttpApplication.InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
at System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context)
at System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context)
at System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)


Custom event details:

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.




I decided to check the web.config file too, and strangely enough, it wasn't even encrypted, so that was even more confusing (Up until now, I still haven't been able to discover exactly what WAS encrypted, but it wasn't the web.config of the default app, nor was it the web.config in the 2.0 framework directory -- even though there is no connectionStrings section in that web.config, I know it did not encrypt, since I was encrypting other sections too that also happened to be in that web.config and which were not encrypted).

I decided to unencrypt using:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pd "connectionStrings"


and the web site seemed to start working again, at least, but the sections were obviously still not encrypted.

Needless to say, I was confused, but determined to figure this out.

I tried the encryption again attempting to be more specific and used this


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pe "connectionStrings" -app "/"


but got the same results

After some research, I found that I could encrypt my web.config more directly by giving a file location with code like this:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef "connectionStrings" "d:\SomeWebRoot\SomeWebApp"


Again, I got the "success" message I wanted to see. This time I checked my web.config right away. Yes! Now it was encrypted. I checked the web site, and again, it just hung there. I looked at the logs and got essentially the same error as before.

I was stumped again.

I looked around a bit and found this post:

http://www.codeproject.com/aspnet/WebFarmConnStringsNet20.asp

It helped give me some ideas. I thought, what if I go ahead and create my own key container. Maybe that will work better, so I tried that.

First I added this to my web.config file:




<configprotecteddata>
<providers>
<add name="EncryptionKey" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL" keycontainername="SomeWebEncryptionKey">
</add>
</providers>
</configprotecteddata>




Then I created the key container using :

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pc "SomeWebEncryptionKey" -exp


Then I noticed something else I didn't realize before when I added the last step for this:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pa "SomeWebEncryptionKey" "ASPNET"


This is when I realized I might need to give some sort of special access to the ASPNET account to the key. Since I was already doing it here, I decided to just go with this new key and continue the process, so I encrypted the web config using the new key. I tried:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pe "connectionStrings"


Doh!, same problem as before. It says it's encrypting, but it's not. I checked out the web site and it was hanging again (by the way, I had decrypted the last test prior to all of this).

So I figured out how to use the key with the specific file again.

Here's how to do it:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef "connectionStrings" "d:\SomeWebRoot\SomeWebApp" -prov "SomeWebEncryptionKey"


Okay, this succeeded in encrypting my web.config, but alas, I'm still having the same issues with the web site hanging and the error.

So I decrypt and keep researching.

Finally I come across this entry, which was somewhat helpful in understanding what was going on:

http://blogs.msdn.com/mosharaf/archive/2005/11/17/protectedConfiguration.aspx

This is when I learned how to apply the rights to the default RSA encryption key:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pa "NetFrameworkConfigurationKey" "ASPNET"


I really thought I was on to something now. I ran encryption on the web.config file using -pef again, and everything encrypted just fine again, but again, the web would hang.

Sheesh! now I'm really starting to get frustrated, but on a whim, I decided to look at the comments on the blog page and noticed one person said:


I'd just add the command for 2003:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT Authority\Network Service"
- Igor


DOH!

I had actually seen the Microsoft site for this here:

http://msdn2.microsoft.com/en-us/library/ms998283.aspx

and had run across this, and somehow I hadn't put two and two together.

The answer was in the error message and somehow I managed to miss it every time. So I ran the following line of code:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT Authority\Network Service"


Then I encrypted again and Voila! Success! the web was working again.

Hopefully this will help some poor unfortunate soul out there like myself to save a bit of time.

Here is a representation of my final batch file:


C:\Windows\Microsoft.Net\Framework\v2.0.50727\aspnet_regiis -pa "NetFrameworkConfigurationKey" "ASPNet"
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT Authority\Network Service"
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef "connectionStrings" "d:\SomeWebRoot\SomeWebApp""

5 comments:

Henry Ong said...

great post with awesome details! thank you much!

Chris Strolia-Davis said...

Thanks. I hope it helped save you some time.

Unknown said...

thank you very much! you saved my life

Chris Strolia-Davis said...

Thanks Juan. I'm glad this entry is helping people.

Unknown said...

Thanks man...I searched a lot to get this solution.