BeGreen
BeGreen

Reputation: 951

C# REST API Service access to path denied

I'm very new to Windows environment, I've struggle a lot making my c# API work on IIS. I only managed to do a GET on my Web API.

When I try to do a POST, I get this:

{"Message": "An error has occurred.",
"ExceptionMessage": "Access to the path 'C:\\Path\\To\\API' is denied.",
"ExceptionType": "System.UnauthorizedAccessException",
"StackTrace": "   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n   at System.IO.Directory.InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, Boolean checkHost)\r\n   at System.IO.Directory.InternalCreateDirectoryHelper(String path, Boolean checkHost)\r\n   at MiningAPI.Controllers.ValuesController.Post(HttpRequestMessage request) in C:\\Users\\Tavernier\\Desktop\\MiningReport\\MiningAPI\\MiningAPI\\Controllers\\ValuesController.cs:line 90\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}

Permissions on IUSRS and IIS_IUSRS are fully allowed to read files on the Web API folder. I'm on Windows 10, running IIS-10

UPDATE:

POST was working when I launched the Web API through Visual Studio. (localhost:port, now 192.168.1.30:port)

I tried to move my folder to D:, added NETWORK SERVICE to the permissions.

Upvotes: 1

Views: 4689

Answers (2)

netniV
netniV

Reputation: 2418

The user being used depends on your application pool. If no identity has been specific within the IIS Application Pool used by your application, then the default will be "IIS AppPool\<AppPool Name>" (without quotes).

see https://www.iis.net/learn/manage/configuring-security/application-pool-identities for more information.

I would recommend that any folders the app pool user needs to write to, is granted permission to explicitly. It would be unwise to allow the app pool user full write access especially to code directories, as that could lead to modification of sources if present.

Code to check permissions

Here is some code that will do a basic check for permissions. It doesn't go off and find all the user groups that the user belongs to, so wouldn't work in an extended situation. However, with application pools using the default identity, they should get either the app pool name or BUILTIN\Users

Import-Module WebAdministration

$websites = (Get-ChildItem IIS:\Sites)

foreach ($website in $websites)
{
    $appPool = (Get-Item IIS:\AppPools\$($website.applicationPool))    
    Write-Output "Found $($website.name) with $($appPool.name) in mode $($appPool.processModel.identityType)";
    $folder = [System.Environment]::ExpandEnvironmentVariables($website.physicalPath);
    if ($appPool.processModel.identityType -eq 3)
    {
        $user = $appPool.processModel.userName;
        Write-Output "Using explicit username '$user'";
    } else {
        $user = "IIS AppPool\" + $appPool.name;
        Write-Output "Using application pool name '$user'";
    }

    $permission = (Get-Acl $Folder).Access | ?{$_.IdentityReference -match $User -or $_.IdentityReference -match "BUILTIN\\Users" } | Select IdentityReference,FileSystemRights
    If ($permission){
        $permission | % {Write-Host "User $($_.IdentityReference) has '$($_.FileSystemRights)' rights on folder $folder"}
    } Else {
        Write-Host "$User Doesn't have any permission on $Folder"
    }
}

On my system this gives the following output

Found Default Web Site with DefaultAppPool in mode ApplicationPoolIdentity
Using application pool name 'IIS AppPool\DefaultAppPool'
User BUILTIN\Users has 'ReadAndExecute, Synchronize' rights on folder C:\inetpub\wwwroot
User BUILTIN\Users has '-1610612736' rights on folder C:\inetpub\wwwroot

Upvotes: 3

Andrei
Andrei

Reputation: 44620

Your WebAPI tries to access the path C:\\Path\\To\\API. It runs on behalf of IIS user that doesn't have access to it. Try to grant access to NETWORK_SERVICE user as well. Then perform iisreset from CMD just in case.

If this doesn't work, just move your project to disk D:, as disk C: is a system disk and it's typically more restrictive.

Upvotes: 1

Related Questions