How to set up IIS 7 application pool identity correctly?
Asked Answered
E

2

10

Having deployed my website to IIS7.5 I found one strange behaviour: when application pool identity is left to be ApplicationPoolIdentity by default (as recommended in IIS Application Pool Identities), Ninject seems to be ignored, as I get the following error, while creating the very first controller:

System.InvalidOperationException: An error occurred when trying to create a controller of type '..MainController'. Make sure that the controller has a parameterless public constructor. ---> System.DirectoryServices.DirectoryServicesCOMException: An operations error occurred.

I tried to grant FullAccess to IIS AppPool\<MySiteAppPool> to the folder, containing the site (including all subfolders and files), but this did not change anything.

However, when I set the application pool identity to any domain account (even a simple one, without administrative privilages, as well as without any access to the folder with the site), it works normally.

Ninject is installed according to Setting up an MVC3 application tutorial through the NuGet package.

I am not sure, if it's relevant, the site is supposed to work in a domain intranet with windows authentication.

So, the only problem seems to be with the application pool identity. As far as I am eager to use the recommended way, I'd love to have the ApplicationPoolIdentity, not a domain account.

What can this be connected with? Is it possible to mix all these together?


Here is an SO thread with a similar issue: ASP.NET MVC 4 + Ninject MVC 3 = No parameterless constructor defined for this object. However no suitable answer there at all either.


As a deleted comment suggested, I tried using NetworkSerive as the identity. And it worked properly. However, I guess this is not much better, than a non-privileged domain account.


EDIT

Suddenly found another dependency: the application pool identity is used for the windows authentication on sql server, though I expected the client-side user's credentials to be used there.

Based on comments

Agree that a remote sql server can be accessed with the authenticated credentials via impersonation.


However it is still not clear what the problem is with ApplicationPoolIdentity and Ninject.

The article mentiond at the very top of this question made me suppose that this could be caused by the fact, that virtual account has no user profile. This aspect remains unclear to me, as one can still enable IIS to load the user profile with the LoadUserProfile attribute. I can't get, what is IIS going to load, if there is no profile for the virtual account?

It is said there:

IIS doesn't load the Windows user profile, but certain applications might take advantage of it anyway to store temporary data. SQL Express is an example of an application that does this. However, a user profile has to be created to store temporary data in either the profile directory or in the registry hive. The user profile for the NETWORKSERVICE account was created by the system and was always available. However, with the switch to unique Application Pool identities, no user profile is created by the system. Only the standard Application Pools (DefaultAppPool and Classic .NET AppPool) have user profiles on disk. No user profile is created if the Administrator creates a new Application Pool.

However, if you want, you can configure IIS Application Pools to load the user profile by setting the "LoadUserProfile" attribute to "true".


I found the following thread on serverfault.com:

How can I assign active directory permission to the default app pool identity

There it is also stated that app pool identity is unable to work as a network service, in particular, query the AD.

Enidenigma answered 28/3, 2013 at 8:26 Comment(10)
You granted full access to whom ?Find
@Find I granted FullAccess to IIS AppPool\<MySiteAppPool> to the folder containing the site (including all subdirectories and files)Enidenigma
Ok, do you have any thing additional showing up in the event logs ?Find
My application log gets only the exception posted above. As fr the windows logs, I failed to find anything suitable there.Enidenigma
You can leave the application pool to ApplicationPoolIdentity and then use asp impersonation to login to your database with a specific user. Look at the authentication section and you'll see it. The key is <identity impersonate="true" userName="" password="" /> in your web.config.Unhorse
@Unhorse actually I use windows authentication. Are these two types of authentication applicible at once?Enidenigma
Yes you can use windows authentication and asp.net impersonation. The authenication mechanism will mean that the end user needs to login with a windows account to view the web pages. The impersonation means that it will use the user account specified when logging in to a database for example. If you are worried about putting the password for the domain account in you web.config you can encrypt the web.config. You can also set the impersonation to use the authenticated users credentials rather than a specific users.Unhorse
Sorry couldn't type all this see msdn.microsoft.com/en-us/library/aa292118(v=vs.71).aspx for more detail on the option available with impersonation.Unhorse
Definitely I will read it. Thank you. However the original question remains unanswered. What is the problem with the ApplicationPoolIdentity and Ninject?Enidenigma
I have this same problem now and cannot get to solve it. How did you go about it? Can you share!Platonic
P
2

From the detail in the question, it sounds a lot like a permissions problem causing a COMException to be thrown, which is preventing Ninject from instantiating MainController. The exception is related to System.DirectoryServices which are the classes used to query Active Directory.

When IIS is running under the normal app pool accounts, those accounts don't have permissions to make queries against Active Directory and a COMException can be thrown. I think the actual message in the exception (can't find a parameterless constructor) is a bit of a red herring and is Ninject trying to fall back to another constructor since the normal one didn't work.

That would explain why when you change the IIS app pool to run as a domain account it suddenly works, because that account does have permission to query the domain.

It's not clear from the question whether or not you are using System.DirectoryServices yourself or whether Ninject/IIS/ASP is using them. If you are using them yourself though, make sure none of the constructors in your AD classes can throw exceptions (catch them and log them or something) which will prevent your app from crashing on start-up. You'll probably find out what I said above about permissions.

If you need IIS to run as the normal app pool account (which is a good idea) but still query AD as a domain user then you can specify the credentials to DirectoryEntry and use a DirectorySearcher to do the AD search. If you're on .Net 4 or higher then I'd recommend using the new System.DirectoryServices.AccountManagement classes instead (which also allow you to specify credentials).

With that method, you won't need any impersonation for AD queries and your app pool can still run as the normal app pool accounts.

Parasitism answered 5/4, 2013 at 15:13 Comment(4)
That's not strictly true. Network service is low privilege account that can access network resources. When it does so it does as the machines domain account. So if you were to access AD & the machine was called domain\webserver it would be using the credentials domain\webserver$. these credentials may have less privileges than you need however.Cardew
@Simon I've updated my answer to clarify that impersonation is not necessary for an AD lookup and removed references to the NetworkService account. This was potentially misleading because of the difference between the usual IIS app pool accounts (e.g. ASP.Net v4.0) and NetworkService account which, as you say, are slightly different.Parasitism
@AdamRodger I think you've pointed me into the right direction, as I indeed access AD and this must be the reason why running under virtual account is failing. I'll check it all as soon as possible.Enidenigma
@AdamRodger Discussing the same problem, I guess: How can I assign active directory permission to the default app pool identityEnidenigma
C
9

iispool\appPoolName account are called virtual accounts & were added to Windows 2008. The idea goes that they aren't really accounts in the true sense. What they allow is enhanced security between processes using the base account.

Many services on your machine use networkService, a built in account with network access. Because of this, if an attacker were to exploit one of those services, any other process running under the same account would be accessible. Virtual accounts, such as those used by IIS prevent this by appearing as different accounts, whilst still being the same account - your asp.net app is still technically running as networkservice & granting this account access to things shoudl still work. This also means if you need to access network resources, the iispool accounts would do so as networkservice does & use the machines domain account.

If you are accessing a remote sql server, this is the account you should add to allow access from your web server. I wouldn't advise using impersonation, unless you really really need to see who the user is on the SQL server. Your app security is simpler if you leave it off.

as to why your injections aren't working, it could be any of your dependencies failing. if controllerA is injected with ClassB which in turn is injected with ClassC & that class fails to have ClassD injected, then the whole chain fails. I've had that happen & it took a while to realise it was something so removed from what I was looking at.

Cardew answered 6/4, 2013 at 0:4 Comment(0)
P
2

From the detail in the question, it sounds a lot like a permissions problem causing a COMException to be thrown, which is preventing Ninject from instantiating MainController. The exception is related to System.DirectoryServices which are the classes used to query Active Directory.

When IIS is running under the normal app pool accounts, those accounts don't have permissions to make queries against Active Directory and a COMException can be thrown. I think the actual message in the exception (can't find a parameterless constructor) is a bit of a red herring and is Ninject trying to fall back to another constructor since the normal one didn't work.

That would explain why when you change the IIS app pool to run as a domain account it suddenly works, because that account does have permission to query the domain.

It's not clear from the question whether or not you are using System.DirectoryServices yourself or whether Ninject/IIS/ASP is using them. If you are using them yourself though, make sure none of the constructors in your AD classes can throw exceptions (catch them and log them or something) which will prevent your app from crashing on start-up. You'll probably find out what I said above about permissions.

If you need IIS to run as the normal app pool account (which is a good idea) but still query AD as a domain user then you can specify the credentials to DirectoryEntry and use a DirectorySearcher to do the AD search. If you're on .Net 4 or higher then I'd recommend using the new System.DirectoryServices.AccountManagement classes instead (which also allow you to specify credentials).

With that method, you won't need any impersonation for AD queries and your app pool can still run as the normal app pool accounts.

Parasitism answered 5/4, 2013 at 15:13 Comment(4)
That's not strictly true. Network service is low privilege account that can access network resources. When it does so it does as the machines domain account. So if you were to access AD & the machine was called domain\webserver it would be using the credentials domain\webserver$. these credentials may have less privileges than you need however.Cardew
@Simon I've updated my answer to clarify that impersonation is not necessary for an AD lookup and removed references to the NetworkService account. This was potentially misleading because of the difference between the usual IIS app pool accounts (e.g. ASP.Net v4.0) and NetworkService account which, as you say, are slightly different.Parasitism
@AdamRodger I think you've pointed me into the right direction, as I indeed access AD and this must be the reason why running under virtual account is failing. I'll check it all as soon as possible.Enidenigma
@AdamRodger Discussing the same problem, I guess: How can I assign active directory permission to the default app pool identityEnidenigma

© 2022 - 2024 — McMap. All rights reserved.