Impersonation exception invoking DirectoryEntry.Invoke method - iis

I have a frustrating problem trying to use the System.DirectoryServices.DirectoryEntry.Invoke() method to recycle app pools on a remote IIS server.
The basic context is two client machines and an IIS 7.0 server machine (Windows 2008 Server), myServer, all in the same Windows domain. I want to run code on the client machines to
recycle an AppPool on the IIS server.
Here's the relevant code snippet:
DirectoryEntry directoryEntry = new DirectoryEntry("IIS://myServer/W3SVC/AppPools/SomeAppPool", domainUserid, password, AuthenticationTypes.Secure);
directoryEntry.Invoke("Recycle", null);
From one client machine, the code runs successfully, but on the other client machine, the code throws an exception relating to impersonation (see below).
I'm logged in as the same domain user on both client machines, and use the same domain user information in the code.
I've checked the server-side Event Viewer and other logs to see if there's some obvious difference in how the request is processed on the server, and done a significant amount of googling without success.
Can anyone give a clue as to what to look for or what diagnostics I can run (on either the client machines or on the server machine) to determine why this is happening?
Thanks for any help! Martin
2011-08-10 22:35:39,478 [10] WARN - ActionRestartIIS: Exception restarting IIS System.Reflection.TargetInvocationException: Exception has been
thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException (0x80070542): Either a required impersonation level was not provided,
or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)
--- End of inner exception stack trace ---
at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)

In that fine tradition of answering one's own questions, here's what I learnt. I modified my code to use System.Management classes and these seem to work better across domains. Sample code below:
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Authority = "ntlmdomain:" + this.domain;
connectionOptions.Username = this.username;
connectionOptions.Password = this.password;
connectionOptions.EnablePrivileges = true;
connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
ManagementScope managementScope = new ManagementScope(#"\" + this.iisserver + #"\root\microsoftiisv2", connectionOptions);
managementScope.Connect();
ManagementObject appPool = new ManagementObject(managementScope, new ManagementPath("IISApplicationPool.Name='W3SVC/AppPools/" + apppool + "'"), null);
appPool.InvokeMethod("Recycle", null, null);

Related

403 when calling API from Azure App Service

I have a strange problem. I have a .NET Core App which works fine on local machine and passes unit tests.
Inside the app it basically calls our platform web service:
using( WebClient client = new WebClient() )
{
NetworkCredential creds = new NetworkCredential(_userName, _password);
CredentialCache credCache = new CredentialCache();
credCache.Add(new System.Uri(_baseUrl), "Basic", creds);
client.Credentials = credCache;
var url = _baseUrl + "/api/v1/Pricing/Rates";
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var request = JsonConvert.SerializeObject(data);
System.Console.Out.WriteLine(request);
var response = client.UploadString(url, request);
var responseObject = JObject.Parse(response);
var products = responseObject["PricingProducts"].Children();
var result = new Dictionary<string, double>();
foreach( var product in products )
{
result.Add(product.Value<string>("LoanProgramName"),
product.Value<double>("Rate"));
}
return result;
}
When I execute this on local machine using dotnet run, everything works fine. Unit tests work great too. The logs on the App Service don't tell me much except that I am getting a 403 from the platform web service.
ers.RatesController.Get (AlexaRates) with arguments ((null)) - ModelState is Valid
2018-02-24 06:37:44.418 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Executed action AlexaRates.Controllers.RatesController.Get (AlexaRates) in 201.3483ms
2018-02-24 06:37:44.447 +00:00 [Error] Microsoft.AspNetCore.Server.Kestrel: Connection id "0HLBRA4B41EO8", Request id "0HLBRA4B41EO8:00000002": An unhandled exception was thrown by the application.
System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at System.Net.WebClient.GetWebResponse(WebRequest request)
at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream)
at System.Net.WebClient.UploadBits(WebRequest request, Stream readStream, Byte[] buffer, Int32 chunkSize, Byte[] header, Byte[] footer)
at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
at System.Net.WebClient.UploadString(Uri address, String method, String data)
at Rates.RetrieveLatest() in D:\home\site\repository\AlexaRates\Rates.cs:line 50
at AlexaRates.Controllers.RatesController.Get() in D:\home\site\repository\AlexaRates\Controllers\RatesController.cs:line 22
at lambda_method(Closure , Object , Object[] )
at Microsoft.Exten
Has anyone experienced anything similar? I see a bunch 403 posts, but they are mostly about people calling a REST API hosted on the service not calling out.
The 403 forbidden error usually means the server understood the request but refuses to authorize it.
According to your error message, it seems that the error happens in Rates class and RatesController class, which you haven’t showed for us. You could set a break point to check the code in these classes by using remote debugging.
You say the project is working fine locally, but get error in Azure, so please make sure you have published all your projects and data sources to Azure. Check whether the ‘_baseUrl ‘ is from Azure. And make sure you have started the Azure App Service.
There may be other causes of 403 forbidden error. Such as page cache and logging in of cookie. You could refer to this article to learn how to fix the 403 Forbidden Error.
Cause of 403 Forbidden Errors
403 errors are almost always caused by issues where you're trying to access something that you don't have access to.
My fix was that I realized that our infrastructure guys added a IP restriction on the azure app. That is why the app was bouncing back with a 403.
I removed the IP restrictions on the "Networking" -> "Access Restrictions" page.
After trying to add headers and doing various other things the end result was the same - I was getting a 403 error on calling out to a web service.
The solution was to convert from a Web App to a VM and deploy the application there using the old school setup. The application worked there.

Get remote application pool state using Microsoft.Web.Administration

I'm trying to get the state of an IIS 7.5 application pool using Microsoft.Web.Administration API, but get an exception:
System.Runtime.InteropServices.COMException was unhandled
ErrorCode=-2147020584
HResult=-2147020584
Message=The object identifier does not represent a valid object. (Exception from HRESULT: 0x800710D8)
Source=Microsoft.Web.Administration
I connect to a remote machine in a different domain using the following code:
string appHostConfigFile = "\\\\" + serverName + "\\c$\\windows\\system32\\inetsrv\\config\\applicationHost.config";
UNCAccess unc = new UNCAccess(#"\\" + serverName + "\\c$\\windows\\system32\\inetsrv\\config", <USER_NAME>, <DOMAIN>, <PASSWORD>);
server = new ServerManager(appHostConfigFile);
and then try to iterate through all application pools:
ApplicationPoolCollection applicationPools = server.ApplicationPools;
foreach (ApplicationPool pool in applicationPools)
{
Console.WriteLine(“Name: ” + pool.Name + “ State: “ + pool. State);
}
Now, the strange thing is that I do get the Name property correctly (and many other properties too) but the State property thoughts an exception.
Only when I tried connecting to the local machine (127.0.0.1), everything worked as expected.
So, can anyone tell me what I’ve been missing here? Is there any other way to connect to a remote IIS server on a machine outside of mine domain?
Thanks a lot!
I have successfully used Windows Impersonation to access a remote IIS instance using ServerManager.
using (ServerManager serverManager = new ServerManager($#"\\{computerName}\c$\windows\system32\inetsrv\config\applicationHost.config"))
{
ApplicationPoolCollection appPools = serverManager.ApplicationPools
}
This works with IIS 8 and IIS 7.5. I have not tested with other versions. I am using SimpleImpersonation (available via Nuget).

IIS Application pool identity

I am attempting to obtain a data feed from yahoo finance. I am doing this with the following code:
System.Net.WebRequest request = System.Net.WebRequest.Create(http://download.finance.yahoo.com/download/quotes.csv?format=sl&ext=.csv&symbols=^ftse,^ftmc,^ftas,^ftt1x,^dJA);
request.UseDefaultCredentials = true;
// set properties of the request
using (System.Net.WebResponse response = request.GetResponse())
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
I have placed this code into a console application and, using Console.WriteLine on the output I receive the information I require. I have used the 'Run as..' command to execute this using a specific domain account.
When I use this code from within a Page load I receive the following error message "No connection could be made because the target machine actively refused it 76.13.114.90:80".
This seems to suggest that the call is reaching yahoo (is this true?) and that there is something missing.
This would suggest there is an identity difference in the calls between the console application and application pool.
Environment is: Windows Server 2003, IIS 6.0, .net 4.0
"Target machine actively refused it" indicates that the TCP connection itself is not succeeding. This could be due to the fact that the Proxy settings when run under IIS are not the same as those that apply when you run in the console.
You can fix this by setting a WebProxy on your request, that points to the proxy server being used in the environment.
Yes, an active refusal is indication that the target machine is receiving the request and the information in the headers is either incorrect or insufficient to process the request. It is entirely possible that if you had to run this call using a "run as" command in console that the application pool's identity user does not have the appropriate permission or username. You can attempt to change the identity user to this specific domain account to see if that alleviates the problem, but you may have to isolate this particular function into its own application pool in order to protect the rest of the website from having this specification.

An unhandled access exception has occurred, msmq, Sharepoint error

I have an issue that is occurring after my server reboots. I have some features in SharePoint, for doing various things. One thing they do is add items into a couple of different MSMQ queues. Immediately after a server reboot, if I try to log in to SharePoint and I go to a custom page of mine, and click on a button within that page (which would then create the msmq item) I get taken to a page that displays the following:
The website declined to show this webpage
This error (HTTP 403 Forbidden) means that Internet Explorer was able to connect to the website, but it does not have permission to view the webpage
If I dig in to the Event Logs I find the following errors in Application:
Event ID: 1314
An unhandled access exception has occurred
AND in the Security event logs:
3 of these:
Event ID: 560
Object Open:
Object Server: SC Manager
Object Type: SERVICE OBJECT
Object Name: MSDTC
....
Accesses: Query status of service
Event ID: 560
Object Open:
Object Server: SC Manager
Object Type: SC_MANAGER OBJECT
Object Name: ServicesActive
...
Image File Name: C:\WINDOWS\system32\services.exe
...
Accesses: Connect to service controller
Query service database lock state
Event ID: 560
Object Open:
Object Server: SC Manager
Object Type: SERVICE OBJECT
Object Name: MSDTC
...
Image File Name: C:\WINDOWS\system32\services.exe
...
Accesses: Query service configuration information
ALSO, if I dig in to the SharePoint logs, I find the following errors:
Application error when access /my/site/url/MyPage.aspx, Error=Access
is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Server stack trace: at
System.Transactions.Oletx.IDtcProxyShimFactory.ConnectToProxy(String
nodeName, Guid resourceManagerIdentifier, IntPtr managedIdentifier,
Boolean& nodeNameMatches, UInt32& whereaboutsSize, CoTaskMemHandle&
whereaboutsBuffer, IResourceManagerShim& resourceManagerShim) at
System.Transactions.Oletx.DtcTransactionManager.Initialize() at
System.Transactions.Oletx.DtcTransactionManager.get_ProxyShimFactory()
at
System.Transactions.Oletx.OletxTransactionManager.CreateTransaction(TransactionOptions
properties) at
System.Transactions.TransactionStatePromoted.EnterState(InternalTransaction
tx) ...
...at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
at System.Transactions.Transaction.Promote() at
System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction
transaction) at
System.Transactions.TransactionInterop.GetDtcTransaction(Transaction
transaction) at
System.ServiceModel.Channels.MsmqQueue.GetNativeTransaction(MsmqTransactionMode
transactionMode) at
System.ServiceModel.Channels.MsmqQueue.SendDtcTransacted(NativeMsmqMessage
message, MsmqTransactionMode transactionMode) at
System.ServiceModel.Channels.MsmqQueue.Send(NativeMsmqMessage message,
MsmqTransactionMode transactionMode) at
System.ServiceModel.MsmqIntegration.MsmqIntegrationOutputChannel.OnSend(Message
message, TimeSpan timeout) at System.ServiceModel.Chann...
I have two VMs, one for the web (sharepoint) machine, and one of the DB machine (where all the content dbs etc are stored). The DB server is a primary domain controller, and both machines are part of the same domain. I've created a domain user to use for the SharePoint application pool.
Strangely, it is possible to make the errors go away by going to a different part of my application and running that code (which also adds an entry into the msmq). Once that is done, then all of the rest of the application works as normal.
Any help would be incredibly appreciated.
Note: I noticed that the error had something to do with the anonymous user (IUSR...) in IIS for the SharePoint site. I changed that user to be a domain administrator user, and the error no longer happens. So, it's something to do with the permissions of the IUSR.. user, but I don't know what...
O M G
Ok, so I tried something, it was a LONG shot, but I was at my wits end.
I wrapped all of the code that was talking to the MSMQ (adding items to the queue) in the run with elevated privelages thang, and it worked!!!!
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//MSMQCode here
});
Now, I can reboot the server, and do the stuff that was erroring before, and it works fine!
Consider running warm up scripts upon server reboot.
http://blogs.msdn.com/joelo/archive/2006/08/13/697044.aspx
Give everyone read permission to the bin directory under inetpub\wss etc..

MOSS 2007 site in a farm type initializer exception

We have some solution that we built against a MOSS farm one of which includes a timer job. This job has been working just fine for months. Recently the administrator enlisted another server into the farm, and our timer job automatically started running on this new machine. As soon as this switch happened our timer job started yielding the error below (found this in the SP logs).
At first I thought it was a rights issue, but the timer service on the machine where it worked before and the new one are running under the same domain account. It seems to be failing while looping the site list in a site collection, on just one of the sites/webs (code snippet below). I know that this domain account has access to this because it works on the other box under same account. Does anyone have any ideas on why this cryptic error is occurring? Or if any special procedure needs to be done on this new machine to ensure it has proper ACL's for all databases in the MOSS farm?
Code:
public static void Main(string[] args)
{
SPSecurity.RunWithElevatedPrivileges(delegate() { setInputParameters(); });
}
private static void setInputParameters()
{
SPFarm farm = SPFarm.Local;
SPWebService service = farm.Services.GetValue<SPWebService>("");
foreach (SPWebApplication webApp in service.WebApplications)
{
foreach (SPSite siteCollection in webApp.Sites)
{
using(siteCollection)
{
siteCollection.CatchAccessDeniedException = false;
try
{
/* Here is the line that it fails on */
foreach (SPWeb web in siteCollection.AllWebs)
Exception:
The Execute method of job definition LMSDataImport (ID 4b37b285-ef8a-407c-8652-391639449790) threw an exception.
More information is included below.
The type initializer for 'Microsoft.SharePoint.Administration.SPPersistedObjectCollection`1' threw an exception.
Exception stack trace:
at Microsoft.SharePoint.Administration.SPPersistedObjectCollection`1.get_BackingList()
at Microsoft.SharePoint.Administration.SPPersistedObjectCollection`1.GetEnumerator()
at Microsoft.SharePoint.Administration.SPAlternateUrlCollectionManager.LookupAlternateUrl(Uri canonicalRequestUri)
at Microsoft.SharePoint.Administration.SPAlternateUrl.LookupCore(Uri uri, SPFarm farm)
at Microsoft.SharePoint.Administration.SPWebApplication.Lookup(SPFarm farm, Uri requestUri, Boolean fallbackToHttpContext, SPAlternateUrl& alternateUrl, SiteMapInfo& hostHeaderSiteInfo, Boolean& lookupRequiredContext)
at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite, SPUserToken userToken)
at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite)
at Microsoft.SharePoint.Administration.SPSiteCollection.get_Item(String strSiteName)
at Microsoft.SharePoint.Administration.SPSiteCollection.get_Item(Int32 index)
at Microsoft.SharePoint.Administration.SPSiteCollection.ItemAtIndex(Int32 iIndex)
at Microsoft.SharePoint.SPBaseCollection.SPEnumerator.System.Collections.IEnumerator.get_Current()
at LMSDataImporter.setInputParameters()
at Microsoft.SharePoint.SPSecurity.CodeToRunElevatedWrapper(Object state)
at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.<RunWithElevatedPrivileges>b__2()
at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)
at Axian.AxianCalendar.LMSDataImporter.Main(String[] args)
at Microsoft.SharePoint.Administration.SPTimerJobInvoke.Invoke(TimerJobExecuteData& data, Int32& result)
Check the DLLs for SharePoint, do all exists and all are the same version? Try putting a catch for the TypeInitializationException, and see what is wrong inside that exception.
It's not a solution, but as a workaround in the interim, I think my suggestion to one of your other questions here:
How do you instruct a SharePoint Farm to run a Timer Job on a specific server?
will keep you running while you investigate further.
Check the NLB (Network Load Balancing) configuration. Most of the time SharePoint and applications integrated to it fails when NLB changes its state. There is a patch available to solve this problem. Just a suggestion. Not sure if this is the reason. But I have faced a similar issue and the root cause was an NLB bug
A Type init exception just means an exception occurred in the .ctor of the class (as you probably know). The real exception should be in the InnerException property - can you get your hands on this? Likely it's stemming from the database alright, from Microsoft.SharePoint.Administration.SPPersistedChildCollection InitializeFromDatabse method.
Can you look into the sharepoint logs (on that errant server) for information about the database error, it will be there. Reading logs are a pain, but not if you install the ULS Log Viewer feature from http://www.codeplex.com/features
Since the stacktrace has SPAlternateUrl tinkering furhter up the stack, perhaps your zones are misconfigured (and do not include a mapping for this new server's machine name) - granted, it shouldn't fail this bad, but what can you do.
You can filter the ULS logs by source.
-Oisin

Resources