Access network share from IIS hosted WCF web service - wcf

I have a C# WCF web service hosted by IIS7 running on Windows Server 2008 R2. My web service needs to access a network share and so during Application_Start I execute the following:
NETRESOURE nr = new NETRESOURCE();
nr.dwScope = RESOURCETYPE_DISK;
nr.lpRemoteName = string.Format(#"\\{0}\{1}", MyServer, MyShareName);
nr.lpLocalName = #"X:";
string UserName = MyWebSvcLoginName;
string Password = MyWebSvcPassword;
uint result = WNetAddConnection2(ref nr, Password, UserName, CONNECT_UPDATE_PROFILE);
This has been working fine for 3 months. All of the threads in the web service process had access to the mapped drive. Now, all of a sudden, only the thread that called WNetAddConnection2 has the drive mapped. I am not aware of anything that changed in the server configuration. Are there any options that would prevent other threads in the process from seeing the mapped drive?

You need to look for the difference between what works and what does not. Things to check are:
Does the one that works running in a different application pool with a different identity. Has the identity that does not work lost some rights?
Does the one that works use a different user name and password to access the share. Has the passord of the user that does not work expired?
Do all map to the same drive letter? Is the drive being used for another share?

Related

Host .net core app with iis give a database access error

I have a .Net Core 2.0 application that I host in IIS 7.
With IIS Express the application works fine and I'm able to connect to the database successfully. With IIS I get this error:
Cannot open database "Books" requested by the login. The login failed. Login failed for user 'DOMAINNAME\PCNAME$'.
My connectionString in appsettings.production.json file looks like this :
"ConnectionStrings": {
"BooksDatabase": "Server=PCNAME\\SQLEXPRESS;Database=Books;user id=iisAccess;password=iisPassword;Trusted_Connection=True;ConnectRetryCount=0;MultipleActiveResultSets=true"
};
What am I doing wrong and why does it say that the "login failed for 'DOMAINNAME\PCNAME$'" when I put the credentials user id=iisAccess;password=iisPassword; in my JSON file?
You are asking for Windows Authentication:
Trusted_Connection=True
Remove this part of the connection string and give it another try.
The reason for the error goes along these lines:
IISExpress runs as a normal process in your logon session. So it runs with your Windows Credentials. When your app is running inside IISExpress it is actually running under your credential, and when you connect to the database using Windows Authentication, is your login that SQL Server will receive.
The full IIS on the other hand runs as a service under a different session and a different user account. There are the application pools that also play a part and run under yet another account. But the main thing is that those default IIS accounts are local accounts, so they have no "visibility" to another computers. Hence when your app tries to connect to SQL Server, SQL "sees" the machine account, which goes by the name DOMAIN\MACHINE$.
Most likely, ASPNETCORE_ENVIRONMENT is not set correctly on the server (i.e. either not set at all or not set to Production).
On your server, edit the system environment variables and add one (if it doesn't already exist) with the name ASPNETCORE_ENVIRONMENT and the value Production. Also, edit the advanced settings of your app pool in IIS for the application and ensure that the key Load User Profile is set to True.

Azure Remote app: How do I evaluate the user that is running my application?

I have a simple VB.net console application that displays the current user, waits for key input, and then exits. It uses the following call to display the information:
System.Security.Principal.WindowsIdentity.GetCurrent.Name.ToString()
If I create a remote app hosting this application, and create an azure user that has rights to run the remote app such as;
thisisa#test.onmicrosoft.com
When this user connects to the remote app the output of the line of code above would look something like;
YLSDAAYU0007\thisisa_000
Is there anyway of reading the user running the remoteapp at the time? in this case, I am looking to obtain thisisa#test.onmicrosoft.com ?
Catalin from the RemoteApp team here. You have stumbled across one of our implementation details here :)
Windows does not allow automatic login with Azure Active Directory (AAD) users: they only allow users that have Microsoft Accounts or domain accounts in case the collection is domain joined. We are working around this limitation by creating a local user on the VM and logging in with that user instead of the AAD user.
If you have any more questions about this, feel free to contact me: catalda @ microsoft com

Which account is used to authenticate ASP.net to SQL when using a trusted connection?

I'm just in the process of trying to properly configure asp.net 4.5 on our IIS servers.
I have been able to navigate and launch an ASPX page that contains no data conenctions sucessfully so I know that the application pool authentication to the local directories is working as it should.
Now though I have a seperate SQL server that is connected to the domain and have a connection string stored in the code that connects the ASPX page to the server using a trusted connection. When running in visual studio debug mode, the connection works fine - but at that point I assume it is using my login credentials.
My question is, when a user calls the aspx page via the browser when hosted on the new IIS7 server, which account is used to call the SQL server when using a trusted connection? - Is it the end users or is it a local account from the IIS server?
When I call a page with data connections embedded I get the error: Login failed for user ADMIN\PCNAME$ ... which is an indication that this is the account that it is using. However this account doesn't exist on the domain that I'm aware of. - Or does it ?!
Thanks in advance,
It will use the account that ASP.NET is running under, as you've worked out. What you usually should do is create a Domain Account (with the right privileges) and run your ASP.NET AppPool under that account. Then a Trusted Connection will use that account for connecting to the database, and as long as you've given it access (which as a Domain Account you can do) it should all work.
Added:
After some back and forth on comments, lets go back to the start: set the new AppPool to run with the domain users account, and recycle the AppPoolo. What is it that says the password is wrong? If it's IIS trying to start the AppPool, then it is extremeny likely that the Password you gave the AppPool IS wrong, or else that the password is set to change on first logon.
If its not IIS, but opening a Database connection, are you sure that the database allows this Domain Account access to the database and the tables within it it will need? What roles have you assigned to this account? Also, what SQL statement is it trying to execute (if it's got far enough to try and execute a statement at all)?
I suggest you put any response in you original question - comments get to be a drag if there are too many of them.

Granting write permissions to a networked UNC folder for ASP.NET under IIS 7.5 and Windows Server 2008 R2

BLUF
Our application is attempting to write a file to a UNC folder using an ASP.NET web service running under .NET 4.5, IIS 7.5, and Windows Server 2008 R2. However, any attempt to write the file to the desired location results in an access denied exception.
The task seems simple however me and my team have been troubleshooting this for a while now and we are stumped as to what may be causing the error. Below are the details of our setup and what we have tried and found so far. Names have been changed to protect the innocent.
Environment Setup
The web server, mywebserver, has a website named My.Site.Com with a corresponding application pool named My.Site.Com. The application pool is configured as shown below.
.NET Framework Version : v4.0
Enable 32-bit Applications : False
Managed Pipeline Mode : Integrated
Name : My.Site.Com
Identity : ApplicationPoolIdentity
Load User Profile : False
The UNC path we are attempting to write to is \myotherserver\mydirectories\output where mydirectories is the actual share. On this share a domain group named mygroup-www has been granted full permissions to the share and all subfolders. The machine account (i.e., mywebserver) is a member of this mygroup-www group.
NOTE: For the moment, this UNC path actually lives on the same
machine, mywebserver. However, this will eventually be moved to a machine other
than mywebserver in our test environment and in the production environment
when that it is ready. Currently, I only have the one test environment to troubleshoot with.
The error can be replicated by executing the following code.
[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string ExportReport(int reportId)
{
try
{
string output = ConfigHelper.OutputPath + "test.html"; // UNC path
string url = ConfigHelper.VirtualPath + "test.html";
string[] lines = { "Hello", "World!" };
File.WriteAllLines(output, lines); // Access Denied!
return url;
}
catch (System.Exception ex)
{
Logger.ErrorException("Error exporting report", ex);
throw;
}
}
Troubleshooting
Failed Attempts
We tried various combinations of group/user permissions on the folders (listed below). When running these tests we also ran Process Monitor. For each configuration we saw the same result. The w3wp.exe process attempted to create the file in the desired location but reported a result of ACCESS DENIED. The user of each configuration was IIS APPPOOL\My.Site.Com as expected.
Granting mydomain\mymachine$ full permissions to \myotherserver\mydirectories
Granting mydomain\mymachine$ full permissions to \myotherserver\mydirectories\output
NOTE: I have also tried modifying the code so that it would read a
simple file from \myotherserver\mydirectories\output. When
attempting to read the file, the process fails with an ACCESS DENIED
message as it did when writing the file.
Successful Attempts
We also tried several configurations that worked.
Grant the local IIS APPPOOL\My.Site.Com permissions
The first configuration to work was to grant the IIS APPPOOL\My.Site.Com full permissions to \myotherserver\mydirectories The file was successfully written however the process's user was quite unexpectedly a domain account that was set up for a web application on the same machine in another website. This remains very confusing but worked as the 'other' account also has write permissions to the share.
This won't work in production as we cannot use local accounts to grant access to networked resources but is an interesting data point nonetheless.
Change the App Pool Identity to Domain User
The second configuration that worked was to change the My.Site.Com application pool's identify to domain account that had full permissions to \myotherserver\mydirectories. This was a 'vanilla' domain account that was manually created by us. We did not capture what the user of the process was but that may be another useful data point.
This option may be possible, however it breaks away from best practices with IIS 7.5 and may not be allowed in our production environment due to fairly stringent IT policies.
Run the Site On My Development Machine
The third test was to run the site locally on my development machine, mydevmachine. My local IIS configuration is identical to mywebserver with the exception that I am running Windows 7 instead of Windows Server 2008. I granted full permissions for mydomain\mydevmachine to the \myotherserver\mydirectories and ran the application. The file was successfully written. According to Process Monitor the user for the process was correctly set to IIS APPPOOL\My.Site.Com.
Conclusion
We would like to enable write access as designed using the machine account of mywebserver. We have read ApplicationPoolIdentity user cannot modify files in shared folder in Windows Server 2008 and Permissions for Shared Folder for IIS 7 Application Pool Identity Across Domain and Application Pool Identities.
According to this information we should be able use the machine account to grant read and write access to networked resources such as the UNC path. In fact, I can do this in the desired manner when running the web site from my development machine.
There are a couple thoughts that come to mind. Perhaps there is something wrong with the machine account of the test web server. Or perhaps that 'other' software is interfering with the process somehow.
Any thoughts as to what may be causing this issue? What else should we do to troubleshoot?
Reboot your 'mywebserver'.
Marvel at the now mysteriously functional ApplicationPoolIdentity.
Install MS HotFix KB2545850 and learn the details about this bug in KB2672809 which also shows the steps to reproduce and demonstrate this apparently random problem. Direct download link here.
Speculate why Microsoft has not managed to release a normal windows update for this in the 3 years since that hotfix was published. While people still continue running into it and pulling their hair out because of this obscure problem.
Learn about the other folks who have shared and enjoyed this gift from MS that still continues to keep on giving:
IIS application using application pool identity loses primary token?
DirectoryServicesCOMException 80072020 From IIS 7.5 Site Running Under ApplicationPoolIdentity
ApplicationPoolIdentity cannot access network resources
ApplicationPoolIdentity IIS 7.5 to SQL Server 2008 R2 not working
Windows Authentication Failed when using application pool identity
IIS 7.5 stops using machine account to connect to network resource when using AppPoolIdentity
Your Windows 7 dev machine probably worked fine because it reboots more often than the server. Congrats on your very well written and thorough bug report. I rarely see that here.
I had similar problem accessing a network share using AppPoolIdentity in an ASP.NET application (access denied).
Using NetworkService account or other domain account worked but these were not the best solution.
I performed almost all the tests you did but finally found something that worked.
I figured out that the Network Service account was not used when accessing the shares, just like you did (i expected domain\machine$ account)
This worked for us:
On your IIS web site, go to Authentication and change the Anonymous Authentication item to "Application Pool Identity". It's by default set to "IUSR". This solved our problem.
Also maybe activating ASP.NET impersonation (still in Authentication menu) may help.
Thibault
I have faced same issue, I resolved by creating one domain account for each environemt (QA, STAGE, PRODUCTION). In Application pool identity I have set custom account and I used domain user for respective account. Now It gives me the ability to write and read the files from UNC Path.

Permissions issues with SQL 2008, Report Builder 2.0

So here's a bit of context for the horror story:
Win 2003 SP2 64bit running on a VM exposed to outside world for web access.
SQL Server 2008 Std SP2 64bit with Reporting Services (RS) installed for native mode (i.e. not sharepoint mode).
IIS 6 .NET 3.5 web site app written to use the web services from RS. The site has been set to use Windows Authentication and nothing else.
To save writting custom authentication since I don't need it for this demo I have set-up a local account in Win 2003, i.e. servername\myDemoUser, effectively allow fake Windows Authentication.
Default.aspx lists folders on RS and the reports from each folder. It also has a link to the Report Builder 2 on the server.
The rsreportserver.config has been changed so that the only <AuthenticationType> is <RSWindowsNTLM> since <RSWindowsNegoiate> can't work since it's across the internet and users will not be on the same network (hence the local account myDemoUser).
The web site app has url of the form: http://mysite.mydomain.co.uk/ and the link on it to the Report Builder is of the form: http://mysite.mydomain.co.uk/services/reportbuilder/reportbuilder_2_0_0_0.application, in this case RS has been configured so the Web services virtual directory is "services".
The web.config for the website app has been set to <identity impersonate="true /> for <locations> for the ASPX pages that access the RS webservice. I even added a <location path="services/reportbuilder"> with the same thing and also to allow anonymous users.
So after all the above I go to the site from a machine that isn't on the network, I get prompted by IE8 for username/password and I enter servername\myDemoUser and the correct password. The homepage is displayed and correctly shows the list of folders and reports from RS. HOWEVER if I click the RS report builder link I get the pop window saying it's doing it's clickonce verfication stuff but after a couple of seconds it shows simple message box saying there was an authentication error. The details button then shows a text file with a bunch of stacktrace stuff in which eventually says that the server returned 401 while accessing the .application file mentioned above.
I turned on failure auditing for logins on the Win 2003 VM and I can see that when the clickonce fails it is trying to use the local machine account I logged into on the external (to my network) machine instead of the credentials I entered into the browser on that machine when testing it.
Much Googling and granting of permissions to Network service, everyone etc... on various folders involved later nothing the Report Builder bit just won't install via clickonce due to permissions or the incorrect use there of.
I'm looking into maybe changing something in the RS to try and grant permissions to the report builder to anonymous but at this point I'm pretty pessimistic that I'll actually find anything. The annoying thing about this is that this a test that doesn't represent the final thing (we'll be using custom authentication in RS) but unfortunately I have to do it, 8(.
Any ideas would be most appreciated.
It turns out that when using fake Windows authentication in this way when the machine you are accessing the site from a machine where you have not logged into the domain then clickOnce won't work because it won't pass the details you enter into the browser as found.
So the solution is to:
1) Log into a (any) domain on the machine that is going to access the clickonce link on your site.
2) In Control Panel go to User Accounts (XP)/Store Users and Passwords (Win 2003), and manage the network passwords for a user (XP) and add in the URL, username and password.
Whenever clickonce fires up for this URL it will pass the username/password specified as opposed to the local machine account.
Either of the above will solve this problem.