I'm passing a UNC path to File.GetAttributes(). This works fine when running off my local, but when I move the site to the test server, I get a "Network path not found" error. I am able to navigate to the path from the test server, so I don't know why I would be getting this error. The code is very simple. This is where it errors out:
try
{
if (FileAttributes.Directory != (FileAttributes.Directory & File.GetAttributes(directory)))
directory = GetPath(directory);
}
catch...
Being able to navigate to the share from the server doesn't mean much - remember your application is running under another account, usually whatever the app pool is set to. That account normally does not have access to anything other than the resources in the local machine, because it's not a domain account.
Check what account the app pool is running under. You might have to change that to a domain account on your AD forest to be able to access things on other servers.
Most likely it is "NTLM one hop" issue - credentials of a remote user can't be passed to thrird server.
Machine 1:Browser -(credentials)-> Machine 2:ASP.Net site -(no credentials)-> Machine 3.
Solution is to access "machine 3" under known (i.e. process) account or use Kerberos.
Related
I have an ASP.NET MVC 5 app hosted in IIS 10 on Windows 2016. Our sys admins have created a Managed Service Account (MSA) that is tied to this server and has read/write permissions to a folder on the network. I need to write PDFs to that folder from the web application using the MSA.
Currently, I'm simply trying to write a simple text file to the folder:
System.IO.File.WriteAllText(#"\\SomeUncPath\Reports\test.txt", "sample text");
The above produces this error, which is to be expected,
System.UnauthorizedAccessException: Access to the path '\SomeUncPath\Reports\test.txt' is denied.
I followed this video: https://www.youtube.com/watch?v=lBv81lwZgIo to no avail. It just caused the site to generate a 503 error.
Is it possible to write the files using C# impersonation, such as described in this article? But how do you impersonate an MSA, which has a password set by the system?
I tried the following code using the SimpleImpersonation:
var cred = new UserCredentials("myDomain", "someMsa$", "");
Impersonation.RunAsUser(cred, LogonType.Batch, () =>
{
System.IO.File.WriteAllText(#"\\SomeUncPath\Reports", "sample text");
}
);
The above throws this:
System.ArgumentException: Password cannot be empty or consist solely of whitespace characters. Parameter name: password
Update 1: The server is throwing the following error into the System log:
Application pool SomePool has been disabled. Windows Process Activation Service (WAS) encountered a failure when it started a worker process to serve the application pool.
And these two warnings:
Application pool SomePool has been disabled. Windows Process Activation Service (WAS) did not create a worker process to serve the application pool because the application pool identity is invalid.
and
The identity of application pool SomePool is invalid. The user name or password that is specified for the identity may be incorrect, or the user may not have batch logon rights. If the identity is not corrected, the application pool will be disabled when the application pool receives its first request. If batch logon rights are causing the problem, the identity in the IIS configuration store must be changed after rights have been granted before Windows Process Activation Service (WAS) can retry the logon. If the identity remains invalid after the first request for the application pool is processed, the application pool will be disabled. The data field contains the error number.
I tried this and rebooted the server but the issue persists.
Update 2: If I give the app pool my credentials, the app loads without any issues. It's only on the MSA that it fails with the above error/warnings. What could be wrong with the MSA?
Update 3: The issue was how I was adding the MSA to the app pool. I needed to include my domain in the username: myDomain\someMsa$. Once I had that in, it worked like a charm!
The issue had to do with missing the domain when setting the MSA as the app pool identity. When adding it, I needed to set it as myDomain\someMsa$ instead of simply someMsa$. What's strange is how IIS didn't give an error, perhaps because the MSA account was considered both a local and domain account.
Also, in our case, we didn't need the "Log on as a batch" permission for the MSA. It worked fine without it.
Im having trouble with writing files to remote directory via network. The following code fails when I try to check if the directory exists:
if (!Directory.Exists(processingPath))
Directory.CreateDirectory(processingPath);
processingPath is composed like
processingPath = xxxObject.serverPath + "processing\\";
xxxObject.serverPath contains something like this
\\machineNetworkName\sharedFolder\
Its working properly, but when many requests are processing (running as tasks asynchronously), it stops working and failing into exception:
System.IO.IOException: The network path was not found.
Could you please help me what could be the problem and why it is failing after some time on network path???
Thanks for your solutions
I got the same error before, it was about authentication problems.
You have to be sure that you set properly the user on IIS, because it use a Default App Pool's identity which can't access to your NFS.
You can also use IIS virtual folders to set the identity.
(on IIS manager, see App Pool settings -> Identity and also virtual folders settings -> identity).
In my case, it worked better by using the Impersonation directly in the code, so I recommend you to use the VladL WrappedImpersonationContext Object: How to provide user name and password when connecting to a network share
Last thing to check, the owner of the files on your NFS server, if they were created under the root user, it might not work.
I had the same problem and solved it. The problem in my code and I see it in yours, too, is that you have the slash at the end of the network path.
Instead of processingPath = xxxObject.serverPath + "processing\\"; write: processingPath = xxxObject.serverPath + "processing";
I have developed a windows service using local system as Account. I have used
network path of file
FileInfo fi = new FileInfo(#"\\epm-server\penDocuments_LabMeds\" + Convert.ToString(dr["mrn"]) + "\\SyncedXML\\" + Convert.ToString(dr["xmlfile"]));
if (!fi.Exists)
boolFileNotFound = true;
A dynamic path of a file that is built from database.
It works fine when I run Windows Service in Debug Mode, but when I install it then fileNotExists returns TRUE always like the file doesnt exist but infact it does exist.
This is bugging me a lot now. Kindly help me why its not working. Its a server path. Its getting opened in my PC.
Thanks
Did you notice the double backslashes in front and after SyncedXML (\\SyncedXML\\)?
This is probably the cause of your error.
Additionally I'd use string.Format in such cases to reduce the inadvertently addition of unwanted characters:
var path = string.Format(#"\\epm-server\penDocuments_LabMeds\{0}\SyncedXML\{1}", dr[mrn], dr[xmlfile]);
var fi = new FileInfo(path);
Edit:
If it's permission-related, then it's very likely that your local system account (in whose context the service is running) isn't allowed to access the epm-server.
The path is accessible if you're opening it directly or if you're running the service in debug mode as this is happening in your user context (e.g. YOURDOMAIN\vickyshazad), and you're allowed to access the ressource, whereas NT AUTHORITY\SYSTEM is not.
It's usually a good practise to have a special service account for your developed windows service and grant this user only and exactly the required permissions (least privilege). Maybe ask your system administrator for a service user.
Local System (NT AUTHORITY\SYSTEM) is a highly privileged account that's not recommended to use in general (see MSDN).
Most services do not need such a high privilege level. If your service does not need these privileges, and it is not an interactive service, consider using the LocalService account or the NetworkService account.
I wanted to remove a config file from a remote machine having IP as : sj1slm612. Now the problem is i do not have full modification rights to that remote machine, so I'm using impersonation technique to do this. Normally when I'm connected to this remote machine via putty, I use 'sudo'. So my question is will the following code be able to solve my problem ? Thanks.
My Code :
AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
using (WindowsIdentity Authorized_user = new WindowsIdentity("sj1slm612\\wtsnqa", "password"))
{
using (WindowsImpersonationContext context = Authorized_user.Impersonate())
{
File.Delete(#"/apps/instances/express_13000/configuration/standalone-full.xml");
File.Delete(#"/apps/instances/query_13100/configuration/standalone-full.xml");
File.Delete(#"/apps/instances/wppapi_13200/configuration/standalone-full.xml");
File.Delete(#"/apps/instances/wppgui_13300/configuration/standalone-full.xml");
Console.WriteLine("All config files removed from sj1slm612");
Console.ReadLine();
There are 2 problems with your approach:
You are trying to impersonate a remote machine account on a local machine; this won't work. The credentials of a machine account can only be validated by that machine. In addition, that account has no rights on the local machine, so it doesn't really make sense to impersonate it. You need to impersonate a domain account. When you use a tool like putty, the credentials are sent to the remote machine and not validated by the local machine. This is why you can use a machine account of the remote machine.
You need to give proper paths for the files. Nowhere do you indicate that these files are on the remote machine. Use something like "\\machine\c$\path\to\file".
The details on what are going to work or not will depend on your network and OS, which you didn't specify, though it sounds Linux-ish. There may be a different syntax for referring to remote files that you need to use.
I have a Windows service, running using the login localhost\administrator. This service is meant to invoke another executable (MyProcess.exe), which is supposed to write some stuff to a log file. The service uses Process.Start() to create the process, like so:
var p = new Process();
p.StartInfo.FileName = processFileName;
p.StartInfo.Arguments = arg;
p.Start();
Problem is, it appears that MyProcess.exe is being denied rights to write to the log file, even though localhost\administrator unquestionably has rights to the log folder. If I run MyProcess.exe from a command line, it works perfectly.
So, is it possible that the process is being executed using a different user login?
Can you think of any other reason why MyProcess.exe is being denied rights to write the log file?
UPDATE: the log file is being written to the local machine, but using a network address, i.e. \\MyPC\LogFolder. When I change the code to refer to C:\MyFolder, everything works fine. It's obviously having a problem with the network address (even though it's local).
What sharing settings do I need to put on the folder so that the local system account can access the file?
If you are using impersonating, than it impersonates a user that can be the currrent or a specified user. if not it will run under the Local System, with the privileges of the local system.
p.StartInfo.Domain = "UserName";
p.StartInfo.Password = "Passw0rd!";
You can get the username from:
Thread.CurrentPrincipal.Identity.Name
I've worked it out.
The problem, as noted in my update, is that the process was addressing the log folder using a network share address, \\MyPC\LogFolder, and when we switched the configuration so that it wrote instead to c:\Logfolder, it worked fine.
So it seems that when you address a local folder, the localhost\Administrator account is deemed to have sufficient rights. But when you go via the network share, you need to present valid network credentials, and localhost\Administrator just doesn't cut it. If you change to use MYDOMAIN\MyUser, it works even using the network share address.