Don’t Disrespect the Web.Config – ELMAH

This blog series has focused on simple changes that can be made to a .NET solution’s web.config in order to enhance the development environment, enhance security, and improve troubleshooting capabilities.

You can find previous posts here:

  1. Use web.config transforms to keep track of development versus production settings
  2. Encrypt important configuration sections for security
  3. ELMAH – Error Logging Modules and Handlers

This is the 3rd and final post of the series in which we discuss ELMAH, short for Error Logging Modules and Handlers. I am definitely not the first to write about this, but it is such a useful tool that fits snuggly into the web.config that I had to include it in the series.

 

What is it and why do I care?

First, let’s explain what ELMAH is. It is an open-sourced component that can be easily added to a .NET project for the purpose of logging and notifying developers of unhandled exceptions. What is an unhandled exception? It’s an error in code that a web application cannot respond to, often resulting in a “Yellow Screen of Death.”

ELMAH does not, by itself, rid your application of a Yellow Screen of Death, a screen that causes much frustration among users of your application. Instead, it automatically logs the details of the exception, and the stack trace at the time of the exception, and it can even email the development team that something bad happened.

Using ELMAH has become the standard for any project that I work on. It’s just so darned useful for troubleshooting issues and doing great customer service.

 

Typical Workflow of a User Encountering an Error

Most of the time, users encountering an error do not immediately send an email to support. If it’s a public website, the user might get immediately discouraged and leave the site. If it’s an Intranet website, one that users must use to perform their jobs, then he or she might back up and try it again a couple of times before giving up:

  1. Attempt to perform job function
  2. Curse at screen when exception occurs
  3. Try again
  4. Complain to boss when the same failure occurs
  5. Contact support
  6. Wait
  7. Lose faith in the developers of the website, the support team, and anyone else who is guilty by association

 

Workflow when Error Notifications are Involved

With ELMAH in place, it is easy to short-circuit the workflow and keep users happy. You can begin to troubleshoot the issue before the user has even contacted the support team.

  1. User attempts to perform job function
  2. User curses at screen when exception occurs
  3. Development team member is notified that exception occurred along with details
  4. As the user attempts to try again, the development team member can reach out to the user

    Hello [username],

    I work on the support team for [name of web application]. Our system automatically notifies us when users run into an error that it does not know how to handle, and we are aware that it affects your ability to continue through the application.

    We do not yet know exactly what the problem is, but are working to find out more information and resolve the issue quickly. I will let you know as soon as this is fixed.

    In the meantime, it would help us to resolve this more quickly if you could tell me [what steps you were performing when this crashed].

    Lastly, I know it is less than ideal, but you might try to [perform your job through this work-around or alternative solution] until I get back in touch with you.

    Thank you,

    [Nathan Stuller]

    [Title]

  5. Often, by the time the user would have contacted support, the issue is already fixed

 

Being proactive makes a serious impression on users (and bosses). I’ve used this technique before to reach out to customers about exceptions that they didn’t even notice. It reduced my stress level by confirming that it was a low-priority issue and also allowed me to engage with a customer about my product.

 

How to Get Started

The first step is go to the ELMAH homepage. There you will find the 2 most important links to enable this setup:

  1. Download links to the ELMAH dll you must include in your project
  2. A sample Web.config file (on the same page)

 

The Real Steps

  1. Download the appropriate binary to your web application folder.

  1. Open the zip file. Browse into the “bin\net-2.0\Release” folder and extract the Elmah.dll into your Libs folder.
  2. In Visual Studio, we need to make a reference to this dll from your main web project.

 

  1. Next, you need to add entries into the web.config to tell your project how to use ELMAH. The website has lots of information on how to do this, but I will try to simplify it for the common example of notifying developers by email. First, you need to add this line inside the <configSections> area of the web.config:

  1. Next, add the following line under the <httpModules> section. This may need to be altered depending on which version of IIS your web server is using:

  1. Lastly, add the elmah section (usually at the end) inside the <configuration> section:

There are a host of configuration options you can set to enable ELMAH to do exactly what you want.

 

Wrapping Up

I hope this 3-part blog series has helped you identify simple improvements that can be made to the web.config file. ELMAH, in particular, helps me delete my clients and since it is so simple to implement, to me it is a no-brainer.

Advertisement

Don’t Disrespect the Web.Config – Encryption

As stated in an earlier post…

There are 3 things every public website should be doing with their web.config

  1. Use web.config transforms to keep track of development versus production settings
  2. Encrypt important configuration sections for security
  3. ELMAH – Error Logging Modules and Handlers

In this post, we’ll discuss how to encrypt sensitive sections of the web.config so passwords and other information cannot be easily read by those who gain access to the file.

Why is it important?

Encrypting sensitive sections of the web.config is important because they are just that, sensitive. Think about your production web.config file. It may contain all sorts of data that you would not want to be accessible. There are often passwords for SQL database connections, passwords to an SMTP server, API Keys, or critical information for whatever system is being automated. In addition, web.config files are usually treated as just another source code file. There are probably many versions in your source control system right now. That means, any developer on the team, or more accurately anyone with access to the source code, can see what information is in the web.config file.

In many cases, storing passwords in a web.config is itself unnecessary and should be avoided. However, we know it is all too easy to fall into the trap of placing them in this flexible, convenient file. Therefore, at the very least, certain sections should be encrypted so they cannot be easily read or used for evil.

Encrypting ConnectionStrings

In our example, we will encrypt two typical configuration sections: ConnectionStrings and AppSettings on a Windows 7 development machine.

Follow the below steps:

1. Open a command prompt with elevated, Administrator, privileges:

2. At the command prompt, enter:

cd “C:\Windows\Microsoft.NET\Framework\v4.0.30319”

3. Now enter the following to encrypt the ConnectionStrings section:

aspnet_regiis.exe -pef “connectionStrings” “C:\WebApplication1\WebApplication1”

In this case, C:\WebApplication1\WebApplication1 is the directory where our web.config is located.

4. Enter the following to encrypt the AppSettings section:

aspnet_regiis.exe -pef “appSettings” “C:\WebApplication1\WebApplication1”

For reference on all the command-line options of aspnet_regiis.exe, refer to this MSDN page.

Decrypting ConnectionStrings

Of course, it is possible you might need to be able to read the original, unencrypted, data at a later time. To access that information is easy. Simply perform the previous steps but use the command-line option “-pdf” to decrypt the important sections.

Deployment

Deploying your web application with encrypted web.config sections is simple, but it may not be obvious. This StackOverflow answer explains the steps best. Generally, any server or development machine that uses the same encrypted web.config data must use the same RSA key pair, which can be exported using the aspnet_regiis tool.

Before and After

There you have it. You have successfully encrypted 2 sections of your web.config file. Take a look below to observe the before and after results:

Before

<connectionStrings>

<add name=ApplicationServices connectionString=data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true
providerName=System.Data.SqlClient />

</connectionStrings>

After

<connectionStrings configProtectionProvider=RsaProtectedConfigurationProvider>

<EncryptedData Type=http://www.w3.org/2001/04/xmlenc#Element
xmlns=http://www.w3.org/2001/04/xmlenc#>

<EncryptionMethod Algorithm=http://www.w3.org/2001/04/xmlenc#tripledes-cbc />

<KeyInfo xmlns=http://www.w3.org/2000/09/xmldsig#>

<EncryptedKey xmlns=http://www.w3.org/2001/04/xmlenc#>

<EncryptionMethod Algorithm=http://www.w3.org/2001/04/xmlenc#rsa-1_5 />

<KeyInfo xmlns=http://www.w3.org/2000/09/xmldsig#>

<KeyName>Rsa Key</KeyName>

</KeyInfo>

<CipherData>

<CipherValue>fK275KFHx9RKip16DTpwxLi4AHpvCpat4S3edgsDwco9PgudsMKc1qAyh9qNt2y+90qV4QIzyZXm8j27UV5J+R5rNruMUOROLWzVt8qkRYRM3ADoiCi5BJh2SsjE0guGXFbufZDgRpPFV5bstgZSBPYNiYXQF/aOLyQjPCE8VDo=</CipherValue>

</CipherData>

</EncryptedKey>

</KeyInfo>

<CipherData>

<CipherValue>CSdausUH7yWcY8t1sPUqiCooYreEauzi4t33gVJuWYcfhspsguTchJjwthUTMLqnulYRmCu8ZnhrVBepQo7PHO/4k5mwo3s46TsgFddvvUlyY/EDQf047LG0pocBDxL3MgIGf3b+atoG29Jg0Wnhj+M6urYG55Ko4nGp36JILQptlEn+sqCl2sQ99izykXtRWP7kC4tldO+YvBuZ7x8fyGoANwSKQFo7cH+dbydvCkRvaFQsRATdsQKGmSrXwIlkoNvxFb1CBPx0qDenyCs+vO4QyF2CZ8QB+UIJzA8EL7W/FovH5zDczjXQWTsFSmsI+vSojl9G9jSVLJFbwOpQBLIKxfximl5r</CipherValue>

</CipherData>

</EncryptedData>

</connectionStrings>

In a future blog post, we will discuss the 3rd party component ELMAH, which is vital to being notified when your users encounter exceptions in your web application.

 

Update 07/24/2012
It is possible to combine encryption with web.config transforms. I know this will work as I have done it before.

In my experience, I’ve done the following. I had to add an RSA section at the top of my web.config. For me, this went into my web.config.release as I did not encrypt my default/development web.config:

<configProtectedData defaultProvider=”MyRsaProtectedConfigurationProvider” xdt:Transform=”Insert”>
<providers>
<add name=”MyRsaProtectedConfigurationProvider”
type=”System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL”
keyContainerName=”NetFrameworkConfigurationKey_viternuscom”
useMachineContainer=”true” />
</providers>
</configProtectedData>

Also, the web.config sections need to be replaced at the section level. You cannot replace the name or connection string attributes. So, you can use something like the below configuration to replace the whole connection strings section in each environment:

<connectionStrings configProtectionProvider=”MyRsaProtectedConfigurationProvider” xdt:Transform=”Replace”>
<EncryptedData Type=”http://www.w3.org/2001/04/xmlenc#Element&#8221;
xmlns=”http://www.w3.org/2001/04/xmlenc#”&gt;
<EncryptionMethod Algorithm=”http://www.w3.org/2001/04/xmlenc#tripledes-cbc&#8221; />
<KeyInfo xmlns=”http://www.w3.org/2000/09/xmldsig#”&gt;
<EncryptedKey xmlns=”http://www.w3.org/2001/04/xmlenc#”&gt;
<EncryptionMethod Algorithm=”http://www.w3.org/2001/04/xmlenc#rsa-1_5&#8243; />
<KeyInfo xmlns=”http://www.w3.org/2000/09/xmldsig#”&gt;
<KeyName>Rsa Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>fV3NsFhZR/l0/5nvioFfjwjhhauNUTR96fQOK3QeRTW05ERDAQrFGj9MBt5Jh7Ca4rIS2JZfOfNTjTxWiEp/tjk+9LXVyPKrJYMiNlYiUmZGfV/amPsLPmRm2pOEyKwJhJLN6NyZdht/xGrf1ClDKO6CG1ViA5pK5R8Db8X9ul4=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>        <CipherValue>eFvSbAzbVUzwa9Sl8V6t43kuwAcvmaPUjboSJ/oi+MMJXyqtqXS8dKSuxBy+E0rC8tUxxIfJppZNm+CCoKf9Rm39vW2flpgcsvm8ZNMekSf4r2GWYAvLw3vYvMBcbnFRqktlaM7cXia38+3KGN8skHzxioqrBgy2QQqqPWIPrmrCS440BRlXEck6XwAO9rZOERgM6+OtlRan4EuGoB0O4acJWbp51zWxkfzqxMb600BHkYzeIYkHH8GNvWo+LSQt6o+NYW+Q7sm/lLFY5hPp3pGTOygXPehT1b/3BWZM+1dJ5sh8sBXO+t5m7/Dzqt4nvMqArmdEUvQdhYAPauC3Uj9HjDFpHkbOjVEzohIvB0kJ1Wc3uP4VvE6CRMbAsrRiSNLDlT6OpXYVrArLk9c1bBA56nFXPMxLEpN1umRcCfaQY0qxKrZi/yJ8dKD/C/5Vo7o50f10jM9eUrt3/uS71bNJk5U9N7kO42tZZGXZMui51o6MWcYxSC7VQ3KdCpy6UacBnD8MYr7EHeZ591ATQds8dzcsXY7w6Lsg1pXLK74HqXMW/xDeLtBoWJxat9y+</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>

I hope this helps.

Don’t Disrespect the Web.Config – Transformations

No matter how large of a project you are building nor how many lines of code you maintain, the most important file in your whole solution is likely the web.config file. It potentially contains connection strings, API keys, passwords, etc. If any of this information is incorrect you will likely see many problems in your application. Likewise, if a hacker were able to examine this file, it could mean disaster for your network. It is for these reasons that the web.config file must be treated with the utmost respect.

There are 3 things every public website should be doing with their web.config

  1. Use web.config transforms to keep track of development versus production settings
  2. Encrypt important configuration sections for security
  3. ELMAH – Error Logging Modules and Handlers

Each of the above topics will be covered in a separate post. As for today, we’ll discuss #1. Visual Studio 2010 introduced web.config transforms, which make it dead simple to maintain configuration information for multiple deployment environments.

The scenario:

Imagine the not-so-rare network setup of a website that is deployed on a production server, a test server, and is run locally by developers. In the old days, it was difficult to keep track of all the different environment-specific configuration options. Maybe you set the web.config correctly once for each environment and just never overrode it during a new publish. Maybe you created your own configuration text files that were dynamically linked into the application. Either way you had to spend extra time to solve this seemingly simple problem.

Thank goodness for modern IDEs.

Now it’s extremely easy to setup multiple configuration files in your Visual Studio solution, with these additional benefits:

  • Easy integration into source control
  • Each separate web.config file is tied to a Visual Studio build configuration
  • Easier integration into automated builds and deployments

Since the web.config transformation technology has been around for about 2 years now, I’ll try and introduce a new spin on it by demoing this with the Visual Studio 11 Beta.

How to set it up:

  1. Open your project in Visual Studio 11 Beta. Note: new projects in Visual Studio 2010 and 11 already have multiple config transformation files.
  2. Open the Build menu and navigate to the Build Configuration manager.
  3. Click the Active solution configuration drop down list and select New.
  4. Enter information for your test environmentbuild configurations
  5. Right click on the web.config file and select Add Config Transform. Note: If this option is not available, see this link.web.config transforms
  6. You will now see a web.config for each environment you support (Debug representing the developer’s local environment, Test representing Test, and Release representing production).

    config transform

  7. Next, we introduce the environment specific settings for your web.config files
    1. My web.config files typically have environment-specific information in the appSettings and ConnectionString sections:

    <appSettings>
            <add key=apiKey value=“83ABC029538FED091ACDD”/>
    </appSettings>
    <connectionStrings>

    <add name=DBConnectionString connectionString=Data Source=DBServer;Initial Catalog=DatabaseName;Persist Security Info=True;User ID=userName;Password=password providerName=System.Data.SqlClient/>

    </connectionStrings>

    1. Since the above is configured for my development environment, I usually leave my web.Debug.config blank
    2. In the Web.Test.config and the Web.Release.config I replace my appSettings and connectionStrings sections with environment specific values (see this website for detailed information on syntax)

    <configuration xmlns:xdt=http://schemas.microsoft.com/XML-Document-Transform>

    <appSettings xdt:Transform=Replace>
            <add key=apiKey value=B153439AB3DE8FF9CA9D0/>

    </appSettings>
    <connectionStrings xdt:Transform=Replace>

    <add
    name=DBConnectionString
    connectionString=Data Source=ProdDBServer;Initial Catalog=ProdDatabaseName;Persist Security Info=True;User ID=userName;Password=password
    providerName=System.Data.SqlClient/>

        </connectionStrings>

  8. Now just choose the build configuration and publish a project. It will automatically merge the correct web.config values based on the selected build configuration.

    asp.net publish

 

Beautiful. Your app has been deployed with the appropriate environment-specific web.config settings. In the next post, we will discuss how to encrypt secure information that is stored in the web.config file.