26 March 2008

Put simply: Encrypting ASP.Net Web.config Connection Strings

I want to take the time to quickly explain what I have learned about ASP.Net / web.config element encryption. In this case, I wanted to deploy a web application to 4 servers and individually encrypt the connection strings for each application.

The problem was that while it worked well on the first server, the second server either refused to encrypt the connection string or the application would throw an error and crash before delivering the page.

Prepare the Application Server

Grant web access to the application folder so that the encryption engine can get access to the file. To do that, go onto the web server and find the physical directory where the application resides.

Right-click on the folder and choose Properties. Choose the radio option 'Share this folder'. The Edit Alias form will appear. Leave the default values (Access Permissions: Read & Application permissions: Scripts). Push ok and apply to save the settings.

Prepare the Connection String

The next step is to create your web.config and add connection information.

Connection String Example

<connectionStrings>
<remove name="LocalSqlServer" />
<add name="Cn_Name" connectionString="Data Source=Server_Name;Initial Catalog=Database_Name;User Id=User_Id;Password=Password;" />
</connectionStrings>

Add configProtectedData Element

The connectionStrings element is a descendant of the configuration element. In the configuration element, you will need to add the configProtectedData / providers / add elements and make a reference the System.Configuration.RsaProtectedConfiugrationProvider. Be sure that the PublicKeyToken is accurate. You can match it to the token in the Assembly directory.

The compiler (in Visual Studio 2005 at least) does not recognize the keyContainerName or useMachineContainer elements. They get underlined by VS, but the errors are ignored. Don't be a purist - just add them.

ConfigProtectedData Example

<configProtectedData>
<providers>
<add name="Name_of_Provider"
type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="Name_of_key"
useMachineContainer="true" />
</providers>
</configProtectedData>

You may see some documentation saying to add a xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0 attribute to the configuration element. In my experience, this just complicates the final encryption process, so I do not recommend it. On the other hand, it removes the compiler issues noted above. But you are on your own for figuring out the final command line arguments, because you will have to reference the namespace in your commands - something I don't have time to think about or figure out.

Find Out the ASP / IIS Service Account

You then need to find out which service account IIS is running under. I did this by turning impersonation off and then creating a simple ASPX page to find the identity. Execute that page and record the value returned on the page.

ASP Code to find IIS Service Account
<%@ Page Language="C#" %>
<% Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name); %>

Again - if you have impersonation set to true in your web.config, turn it off, otherwise it will just return the impersonated account, which won't help you when executing the encryption command lines.

The Encryption Command Lines

Once you have performed all these steps, you are ready to create your batch file to encrypt the connectionStrings section of the web.config. Just copy these lines into

C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pc "Name_of_key" -exp
C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pa "Name_of_key" "[ASP Identity]"
C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pe "connectionStrings" -app "/Application_Name" -prov "Name_Of_Provider"

Where:

  • Name_of_key is from the web.config above.
  • ASP Identity is returned from the sample ASPX page. In my case it was "NT AUTHORITY\NETWORK SERVICE"
  • Application_Name is the name of the ASP.Net application where the web.config resides.
  • Name_Of_Provider is the provider name from the web.config above.

References: