0

Update: I originally posted that the "in" directory was on C: . It is actually on E: . D: and E: are volumes on a RAID. I wouldn't expect that to make a difference, but if I knew what was going on, I wouldn't have had to ask the question.

I am having a problem with the ACL permissions of directories which must be controlled by both web services and local users. This is my first project that involves directory security and ACLs, so I am concerned that I am thinking about this all wrong. I am open to answers that provide a point-fix, as well as those that would suggest an overhaul of my security model.

I am working on a Windows Server 2012 R2 web service that captures data from a number of users (Nodes) and then processes it. I have per Node directories (e.g. E:\in\node1, E:\in\node2, etc.) to hold the incoming data, and then I use a C# console app that I run as a non-administrative local user (LocalUser) to move the files to a larger volume with a deeper directory structure that reflects classification done by the console app.

Initially, I would create the directories for each Node as LocalUser, but in the interests of manageability, I made a web service (POST Handler) to create the Node directories as each one is provisioned and configured.

I now have a file system in which some directories were created by LocalUser and some by DefaultAppPool via the web service. Both types of directories receive files as expected. When I run my console app as LocalUser, everything works fine for the LocalUser-created directories, but I get an UnauthorizedAccessException when I try to File.Move() from a web-created Node directory to a web-created Classification directory. When I look at the ACLs, I see that problem is that the Creator (and account with Full Control) is different than the account running the console app. Also, the ACL page says that E:\in\node2 inherited from E: , not E:\in .

The whole point of the web-provisioning was to automate the system, so I do not want to have to touch all of the new directories to add LocalUser (or a group containing LocalUser). I also want the system to work when other authenticated users attempt to run the console app (e.g. LocalUser2 who never created any directories anywhere).

It seems that the two opportunities that I would have to fix this are 1) when the web service creates the directories, or 2) when LocalUser runs the script. Unfortunately, I am concerned that neither account (DefaultAppPool, LocalUser) have the permissions to grant (in case 1)) or seize (in case 2)) Full Control of the directories in question.

Eventually, I plan to run the console app from the web services, and that would make everything run as DefaultAppPool, but during development, and as a manual maintenance operation, I would like to be able to run the console app on demand as LocalUser or LocalUser2. I was thinking it might be possible to make some sort of "shim" that impersonated DefaultAppPool while running the console app, but as far as I can tell, the only way to do such impersonation is by having the web-service do it.

In summary, how can I have a system in which web services create directories that are then controllable by users in a particular group?

verbamour
  • 945
  • 9
  • 16

2 Answers2

0

This is how I understand your question:

  • you have a web service running in the DefaultAppPool that creates directories if required and stores data in files in these directories
  • you have a console application run by local users that processes the data in the directories and stores the results on a different volume
  • you plan to have the web-service also run the console application, which means it will access the file system using the same identity as the AppPool
  • certain node directories have been created by a local user, others by the web-service
  • your console app cannot access files in node directories created by the webservice

In your question you list the example node directories *c:\in\node1*, *c:\in\node2*, etc. The directory *c:\in* would be the parent of all the node directories. Permissions are usually automatically inherited. Node directories created in *c:\in* ought to inherit permissions from *c:\in*.

Is the webservice manually setting access permissions for the node directories it creates?

If so, is this necessary? If you set the permissions for c:\in\ so that for instance IIS APPPOOL\DefaultAppPool and the Group Users have full control all directories created in c:\in\ can automatically inherit these permissions, thus freeing you from this problem. (All local users as far as I know are automatically made members of the group Users.)

If the webservice has to set the access permissions manually, how about adding the required permissions for the group Users when a node directory is newly created? This way the console app will be able to access the directory, regardless of who started it.

Does the webservice / console app require "Full Control" of each directory? The way I understand your question the permissions Modify, Read, Write and List folder contents should suffice. Maybe I'm missing something...

If you need to restrict access to certain users only you could create a new security group and only allow this group access to the node directory tree. The local users who need access can then be added to this group. The app pool identity for the webservice would need to be a member of this group as well. In this case it would probably be useful to add a new app pool that is only used for the webservice. Whether you change the identity of this app pool is a matter of choice.

roadkill
  • 436
  • 1
  • 3
  • 9
  • Thank you, you have restated the problem well. – verbamour Dec 19 '13 at 14:27
  • I will edit the question to add a little more detail. I over-simplified when I said the in directory root was c:\in, it is actually on e: . When I look at the ACLs, they are inherited from e:\ , not e:\in . That was unexpected. Once I can be sure I am looking at the latest code, I will post the snippet that makes the directories. I will also do another check of the current ACLs for the parent directory and try again to see if i can create a directory with the proper inheritance. – verbamour Dec 19 '13 at 14:34
  • You've written that volumes D: and E: are on a RAID. Are they on an external storage system that is maybe not a Windows system? I ask because the external system would then probably be responsible for the setting and inheriting of actual access permissions. The Windows server would perceive a simulation of the permissions in the way it expects. If this is the case it may be worth having a closer look at how the storage system deals with access permissions. – roadkill Dec 19 '13 at 15:07
  • It looks like the RAID is a red-herring. I was able to get my script to work by going to the parent directories in D: and E: and granting Users Modify access. I am going to do one more test to see if newly created directories inherit the Users ACL, and if so, we've got an answer! – verbamour Dec 19 '13 at 18:23
  • The newly created directory didn't work. Even though the parent folder had Modify rights, that didn't get inherited. Read/Write/Execute did, but I think I need something like FileSystemRights.DeleteSubdirectoriesAndFiles to allow the move to work. I will update the question to include those code snippets. – verbamour Dec 19 '13 at 21:57
0

OK, here's the deal:

File.Move() requires Write permission for the destination and DeleteSubdirectoriesAndFiles for the source. This is an advanced permission so you have to dig a little for it (thanks to http://www.codeproject.com/Questions/181198/File-I-O-permissions-the-C-way which references File handling with non-administrative user for the identification of the requirement).

  1. Select the parent directory in question (preferably with no subdirectories, as applying the permissions recursively can fail and require to you click 'Continue' alot).
  2. Right-click->[Menu]Properties->[Tab]Security->[Button]Advanced
  3. This brings up 'Advanced Security Settings for [directory]'
  4. Add or select the desired principal ('Users' in my case).
  5. [Button]Edit
  6. This brings up 'Permission Entry for [directory]'
  7. [Blue Text]Show advanced permissions
  8. Check the 'Delete subfolders and files' box.
  9. (verifying the Read and Write attributes you want is probably a good idea here)
  10. Click Apply and/or OK until all the windows go away.

This is then inherited by the programmatically created subdirectories, and everybody gets cake.

Thanks to @roadkill for putting me on the right track, lukeer at CodeProject.com for the first solution I found, and @Powerlord for the StackOverflow solution lukeer used.

Community
  • 1
  • 1
verbamour
  • 945
  • 9
  • 16