Friday, February 5, 2010

Web.config inheritance madness!

We’re slowly migrating to Server 2008/IIS 7, and we hit on a curious issue the other day. We have a marketing "subsite” that’s incredibly basic – think a handful of .html and .asp pages -  in the same domain space as our flagship asp.net application, just taking up an isolated subfolder (and I actually use a virtual directory, because there’s no good reason to physically host one project inside another project, let alone an html/asp project inside a .net 3.5 project where you have two totally disparate groups making changes). Other than in Production nobody makes a habit of hitting the marketing site. So when a break-fix for one of the few pieces of functionality it has showed up, Development wasn’t able to pull up the marketing subsite in Test. They got this instead:


Server Error in '/Child' Application.




Could not load file or assembly 'Super.Awesome.v3.3, Version=3.3.2.0, Culture=neutral, PublicKeyToken=abc123youandme' or one of its dependencies. The system cannot find the file specified.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.FileNotFoundException: Could not load file or assembly 'Super.Awesome.v3.3, Version=3.3.2.0, Culture=neutral, PublicKeyToken=abc123youandme' or one of its dependencies. The system cannot find the file specified.


The assembly that whacked us is an http module used by the parent asp.net website, referenced in the parent folder’s web.config in httpModules and system.webServer modules. IIS 7 has some great inheritance features, but they never seem to work when you want them to (MSEntLib database connection strings) and work when you don’t want them to (referenced modules).

Googling around, there are a few solutions, but the one that seems to work best is the one I didn’t like at all, initially. They want you to modify the web.config of the parent application to stop inheritance. I’d rather modify the child application to block inheritance. MS’s method seems backwards to me, more of a security risk and a hinderance than a help. If you’re on a locked down server farm (say, rented web space at a 3rd party co-location facility), anyone with physical rights above your folder can make you inherit whatever you don’t explicitly call out. They could write a http, network or file stream logger that steals logins and passwords, for instance. Securing your site via https wouldn’t help because they would be on the inside of the protection. And you wouldn’t be able to do anything about it; you wouldn’t even know what you were inheriting.

Alright, soap box time over. Here’s the simplest way to block web.config section inheritances downstream:
Insert
<location path="." inheritInChildApplications="false">

and
</location>
Around the section you want to stop child inheritance for.

I used system.web & system.webServer in this example, as that’s where extension mapping modules seem to be loaded most commonly.

<?xml version="1.0"?>
[…]
  <configuration>

    <location path="." inheritInChildApplications="false">
      <system.web>
      […]
        <httpModules>
          <add type="SuperAwesome.HttpHandlerModule, Super.Awesome.v3.3, Version=3.3.2.0, Culture=neutral, PublicKeyToken=abc123youandme" name="SuperAwesomeHttpHandlerModule" />
        </httpModules>
      </system.web>
    </location>

  […]
    <location path="." inheritInChildApplications="false">
      <system.webServer>
        <modules>
          <add type="SuperAwesome.ASPxHttpHandlerModule, Super.Awesome.v3.3, Version=3.3.2.0, Culture=neutral, PublicKeyToken=abc123youandme" name="SuperAwesomeHttpHandlerModule" />
        </modules>
      </system.webServer>

    </location>
  </configuration>

Not the way I would have handled this (to repeat, I would have had the child web.config be able to block inheritance) but it could be worse.

2 comments:

  1. I don't understand your reason for not making the child application, an application root in IIS7. That would prevent the inheritence at the child level. Are there elements that you want to fall through to the child application? If your goal is to block inheritence from the parent, at the child, the solution to that is to make the child application an application as opposed to a virtual directory.

    Or, since this is a web module that you want to prevent in the child application, you could block the specific module, by using a remove tag inside to remove modules that were previously added by a parent applicaton.

    ReplyDelete
  2. Sorry I haven't replied - I have been trying to find the time to re-setup the original circumstances and (re)try what you're suggesting. I believe I did try separate application pools and it _still_ inherited the parent (folder's) web.config.

    My point about the remove tag is if you don't know about the module, how can you remove it?

    ReplyDelete