I recently had a shared hosting provider customer contact me about a problem with non-administrators deploying using Web Deploy. The specific issue he was running into was that the deployment would work if the user deployed to a sub-application (e.g. mywebsite/myapp) but not if he deployed to the root of the site (e.g. mywebsite). I want to walk through how to debug issues with Web Deploy delegation rules.
First things first – let's take some steps to make debugging easier. Read here about how to enable Web Management Service (wmsvc) tracing – you can read about IIS tracing in general here. Don't forget to restart wmsvc once you enable tracing! This will start recording all sorts of useful information every time a request comes to wmsvc.
Once the customer did that, I looked at his tracing logs
files. I generally search for the names of common Web Deploy providers, such as
createApp, setAcl and recycleApp, that require non-standard permissions. Sure
enough, I found the culprit:
<EventData>
<Data Name="ContextId">{00000000-0000-0000-517F-0080020000F6}</Data>
<Data Name="Uri">/msdeploy.axd</Data>
<Data Name="eventData">Tracing
deployment agent exception. Request ID ''. Request Timestamp: '09/23/2010 18:47:04'. Error Details:
System.UnauthorizedAccessException: Attempted to perform an unauthorized
operation.
at
System.Security.AccessControl.Win32.SetSecurityInfo(ResourceType type, String
name, SafeHandle handle, SecurityInfos securityInformation, SecurityIdentifier
owner, SecurityIdentifier group, GenericAcl sacl, GenericAcl dacl)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String
name, SafeHandle handle, AccessControlSections includeSections, Object
exceptionContext)
at
System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections, Object exceptionContext)
at
Microsoft.Web.Deployment.FileSystemSecurityEx.Persist(String path)
at
Microsoft.Web.Deployment.SetAclProvider.Add(DeploymentObject source, Boolean
whatIf)
at
Microsoft.Web.Deployment.DeploymentObject.Update(DeploymentObject source,
DeploymentSyncContext syncContext)
at
Microsoft.Web.Deployment.DeploymentSyncContext.HandleUpdate(DeploymentObject
destObject, DeploymentObject sourceObject)
at
Microsoft.Web.Deployment.DeploymentSyncContext.SyncChildrenOrder(DeploymentObject
dest, DeploymentObject source)
at
Microsoft.Web.Deployment.DeploymentSyncContext.ProcessSync(DeploymentObject
destinationObject, DeploymentObject sourceObject)
at
System.Security.AccessControl.Win32.SetSecurityInfo(ResourceType type, String
name, SafeHandle handle, SecurityInfos securityInformation, SecurityIdentifier
owner, SecurityIdentifier group, GenericAcl sacl, GenericAcl dacl)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String
name, SafeHandle handle, AccessControlSections includeSections, Object
exceptionContext)
at
System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections, Object exceptionContext)
at
Microsoft.Web.Deployment.FileSystemSecurityEx.Persist(String path)
at
Microsoft.Web.Deployment.SetAclProvider.Add(DeploymentObject source, Boolean
whatIf)
at
Microsoft.Web.Deployment.DeploymentObject.Update(DeploymentObject source,
DeploymentSyncContext syncContext)
at
Microsoft.Web.Deployment.DeploymentSyncContext.HandleUpdate(DeploymentObject
destObject, DeploymentObject sourceObject)
at
Microsoft.Web.Deployment.DeploymentSyncContext.SyncChildrenOrder(DeploymentObject
dest, DeploymentObject source)
at
Microsoft.Web.Deployment.DeploymentSyncContext.ProcessSync(DeploymentObject
destinationObject, DeploymentObject sourceObject)
at
Microsoft.Web.Deployment.DeploymentObject.SyncToInternal(DeploymentObject
destObject, DeploymentSyncOptions syncOptions, PayloadTable payloadTable,
ContentRootTable contentRootTable)
at
Microsoft.Web.Deployment.DeploymentAgent.HandleSync(DeploymentAgentWorkerRequest
workerRequest)</Data>
</EventData> at
Microsoft.Web.Deployment.DeploymentObject.SyncToInternal(DeploymentObject
destObject, DeploymentSyncOptions syncOptions, PayloadTable payloadTable,
ContentRootTable contentRootTable)
at
Microsoft.Web.Deployment.DeploymentAgent.HandleSync(DeploymentAgentWorkerRequest
workerRequest)</Data>
</EventData>
Notice that one of the lines mentions the SetAclProvider. This told me that Web Deploy was failing to set file system permissions. I then asked him for the output of icacls.exe on the folder where the website's files are stored. I saw something like this:
C:UsersAdministrator>icacls
C:hostingspacesfoobarfoobar.comwwwroot
C:hostingspacesfoobarfoobar.comwwwroot NT AUTHORITYSYSTEM:(OI)(CI)
BUILTINAdministrators:(OI)
machinesomeuser:(OI)(CI)(R)
machinesomeuser:(OI)(CI)(M)
machinesomeuser:(OI)(CI)(RX)
Successfully processed 1 files; Failed processing 0 files
From this, I can tell that the customer hasn't given the local user account (someuser) Full Control over the wwwroot directory. SetAcl is failing because Modify permissions are not enough to change the permissions on a directory, they're just enough to set permissions on child objects (such as sub-folders and files underneath the directory). Giving this user Full Control fixed the problem!
I hope this blog post helps you debug Web Deploy delegated deployments.
Bhuvanesh MohankumarPosted May 23, 2016, 1:16 PM
Good one