Who is my IIS application process identity?

Over the versions of IIS, we have changed our process model in some ways with each release.  Each of those changes required administrators to change the way they set up permissions for "code" to run properly on IIS.  It also requires application developers to be aware of these changes. 

Let's skip ASP.net for this blog post (that code has it's own process model and identity configuration), and instead focus on how IIS itself will run script-mapped code and ISAPI filters and extensions. Let's also ignore the fact that you can configure the process identity for each of these process models; let's just talk about the default's and what most folks are experiencing. 

In IIS 5.x, we had a "COM" based process model; and you basically had "In process", "out of process" and "pooled process" options for "where" you wanted your code to run and in fact that is where much of the server would run as well.  These processes would typically run as the "IWAM_{computername}" user, or they would run as LocalSystem (terrible!)  So, let's break this down further:

  • "In Process" applications - LocalSystem (in the inetinfo.exe process)
    • This was fast, but unreliable, since some bad code could take out your whole server
  • "Pooled or Out-of-Proc" applications - IWAM_{computername} (in the dllhost.exe processes)
    • This was more reliable, but slower (because of cross-process communication) 

In IIS 6.0, you could optionally run in the IIS5.0 process model (if you selected the Run WWW service in IIS 5.0 isolation mode option in the UI), or better, you can run in the new process model called a worker process model. http://technet.microsoft.com/en-us/library/cc778754(WS.10).aspx

  • If you used the IIS 5.0 Isolation mode, then we would use the IWAM_{computername} account, similar to IIS 5.x implementations. 
  • If you used worker processes, they would by default run as NetworkService; which is a built-in account.  You could select other users if you wanted, per Application Pool. 

To make this slightly more complicated, we added a group called the IIS_WPG group that was supposed to make it easy to set permissions for all "process identity" level items broadly.  NetworkService and any custom process identities were suppossed to be part of this group.  These links are super helpful in IIS 6.0 scenarios:

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/12a3d96c-65ea-4210-96ad-86a801f6a88c.mspx?mfr=true
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/3648346f-e4f5-474b-86c7-5a86e85fa1ff.mspx?mfr=true

In IIS 7.0, we retained the IIS 6.0 process model, but we made several tweaks to how you provide permissions to these processes.  You can still use the NetworkService account, but instead of the IIS_WPG group, we have the IIS_IUSRS group which is a built-in group and IIS automatically adds whatever specific user you've configured your process identity as to this group.  This article covers a lot of it in detail: http://learn.iis.net/page.aspx/140/understanding-the-built-in-user-and-group-accounts-in-iis-70/ 

In addition (although not directly affecting most customers), Windows gave us the concept of a "Service SID" so we could lock down further what our w3wp.exe process could do; this should give you a warm fuzzy feeling about the improved security of Windows Server 2008.

In IIS 7.5, everything is the same as IIS 7.0, except that the default process identity is no longer NetworkService, but is a special "user" that is created on the fly ... we call it the "AppPool identity" ... we create a user named with the name of the AppPool (so for Default App Pool, we use a DefaultAppPool user) and make it part of the built-in group IIS_IUSRS group and everything is happy.  This is not a "real" user though, some tools may have difficulty referencing this user (but I won't go into it).  We also added other optional identities for your application pools such as "Managed Service Account" which is a domain-based user that doesn't require password resets ... a nice way to keep a long-running process alive but still use a domain account without any management costs. 

Finally, when you reference "built-in" accounts, you need to reference them as BUILTIN\UserAccount instead of MACHINENAME\UserAccount.  You would have used MACHINENAME with the IUSR_{computername} that IIS 5.x (and IIS 6 in compat mode) was creating at setup time, but with IIS 6 worker process mode and forward, you'll use the BUILTIN naming convention since these accounts I've referenced are built-in and not simply local. 

Back to our original question, what part of our code runs as this "process identity" and which code runs as the "authenticated or anonymous user"?  This is not a simple answer; but in short, if you're accessing a resource on disk, then both identities will need READ access to that file.  In some cases, such as with static files, there's no "user" code involved, so IIS is impersonating the authenticated/anonymous user for most of the time (all the time that matters for this exercise).  If you have script-mapped content, you need both users to have access and expect that resources used by your scripts (ASP/asp.net/PHP) to need to allow both identities to have READ access (and write where it's needed - but be careful!).  I would have to write a very large post to talk about which code is run by which user; they are very intertwined; but we're always more conservative in our AccessCheck calls. 

Here are some example links that deal with the complexity this has caused some folks:

http://support.microsoft.com/kb/297519
http://www.dotnet-guide.com/impersonation.html
http://www.joelonsoftware.com/RandomStuff/IIS6.0startsusingIWAMacco.html
http://support.microsoft.com/kb/918041

Hope that helps, if you have questions on this, I'd love to help clarify this for you. 

Dave

No Comments