Link to home
Start Free TrialLog in
Avatar of amyassein
amyassein

asked on

How to assign NTFS permissions to group on several repeated folders hierarchy?

Hi all,

I know this will sound complicated to some of  you but i'll try my best to deliver my request in an easy method. Now, there is file server running windows server 2008 and this server is running different shares for different departments. In brief, i am working on one of the shares called "BSD" and the folder hierarchy looks like the following:

BSD (Share)
       -------  Contracts
                  -------  01 Agreements
                               --------  101-200
                               --------  201-300
                                            .............
                               --------  901-1000

Under every agreement, there are folders like the following;

101-200
    -------  POST-Contract
    -------  PRE-Contract

201-300
      ------- POST-Contract
      ------- PRE-Contract.

....... etc.

Now, i need to apply certain AD groups for every Post Contract and Pre Contract on every agreement. By doing this thing manually, it will really be a boring job and i think i will get myself killed someday cuz of this manual job :). However, i need a script or tool to help me to complete this job automatically by just double clicking the script.

I thought about using the Subinacl tool but actually if you look at it , you will find that you need to build a subinacl line for each group in each folder which means the task is still manual because if you calculate the time of building the subinacl batch file and the time of doing the task manually , they will be the same time. :(

VBScript will be fine in this job if you tell the script to look at a repeated folders name (such as Post Cont and Pre Cont) under each agreement and assign those groups to each of them, it will be great.

Note: 101-200
          201-300
         ...etc
these are called agreements folders to not to confuse you.

Appreciate your fast response relally on this one.

Thanks

Avatar of amyassein
amyassein

ASKER

Sorry i forgot to mention the other complicated side of this task regarding the assigning permissions.

Actually, when the script assigns permissions to groups, i need it to replace any existing objects in the folder's ACL by the groups that i mention in the script. Also, i need it to clear the inheritance of the folder after replacing the existing ACL and to propagate the permissions to subfolders as well.

For example,

When i right click the Post-Contract folder and hit security, there will be users and groups exists, i need to clear them and replace them with the groups that i mention in the script and also to clear inheritance of that folder as well as propagate those new groups to subfolders.

If i really can give this request 800 points to you, i would do that but actually this is the experts exchange limitation :)

Thanks a lot
Dear amyassein,

did you check out icacls http://technet.microsoft.com/en-us/library/cc753525(WS.10).aspx ?

You're runing Windows Server 2008 - icacls may be the solution for you.

Kind regards,
Soren
Dear amyassein,

Forgot - if you have PowerShell feature added on your Windows Server 2008, you can also do the above using the set-acl CmdLet:
http://technet.microsoft.com/en-us/library/dd315261.aspx

Kind regards,
Soren
slemmesmi, thanks for your nice response but let me clarify thing.

Subinacl, ICACLS,XCACLS and Set Acl PS command are still manual methods. In other words, you have to write a command line for each repeated folder under each agreement and compine them in a single batch file or execute them seprarately. As i mentioned, the time of doing this is the same time for doing the task manually using Windows GUI.

VBScript , however, is a code with many facilities (such as If Else, Looping, ...etc) so it can look under each agreement folder and search for repeated folders such as Post and Pre Contract folders in a dynamic way. By the way, i am not a scripting geek but i have only the basics that's why i can't create complicated scripts and ask for help here.

Thanks

I request a BIG attention to this question please.
Avatar of Chris Dent

> it will really be a boring job and i think i will get myself killed someday cuz of this manual job :)

heh I know exactly what you mean :)

Would you go with PowerShell for this? You're right that it can be done in VbScript but it's a hell of a lot easier in PowerShell.

Chris
Chris,

Can you shed some light and help me how to do this using PS ? .... As you know, i am not a PS/VBS scripting geek like you :)

I'd appreciate if you can write some PS code to do this job.

Thanks
A.Y.
I found a solution using PS but still need manual attention :-(

What i did is, i piped a security ACL of an existing Post-Contract folder to every post contract under every agreement. See below:

PS C:\>get-acl -path "\\server01\bsd\contracts\01 Agremments\201-300\201 folder\post-contract" | set-acl -path "\\server01\bsd\contracts\01 Agremments\201-300\202 folder\post-contract"

Then, i use the UP arrow again to recall the previous command and modify the new folder to "203 folder" till "300 folder"

I am dying here :) lol

Chris, Any update ?

Oh, sorry, I didn't mean to leave you hanging.

> What i did is, i piped a security ACL of an existing Post-Contract folder to every post contract under every agreement.

Is this what you need to maintain? Apply a template ACL to every instance of Post-something?

Chris
Hi Chris,

No i meant that i set a permission in one Post-contract folder under one of the agreements and instead of doing this manually on every Post-Contract, i am simply copying the permissions from that folder to the other Post-Contract folders by using Pipe. However, the procedure still manual which means i need everytime to hit the UP arrow to recall the previous command and change the path to the other Post-Contract folders.

If possible, i need a help to write a code (PS or VBS whatever) to look for these Post-Something folders and to see permission on them.

Thanks

That should be quite easy :)

This will find Post- folders:


Get-ChildItem -Filter "Post-*" -Recurse | ?{ $_.PsIsContainer }


So what we need to do is:


# Load the template ACL
$Acl = Get-Acl "\\server01\bsd\contracts\01 Agremments\201-300\201 folder\post-contract"
# Find Post folders
Get-ChildItem -Filter "Post-*" -Recurse | ?{ $_.PsIsContainer } | %{
  # Apply the ACL
  Set-Acl $_.FullName -AclObject $Acl
}


Of course I'm sure you'll want to test that quite carefully :)

Chris
I meant to set permissions on them not see permissions on them :)
Sorry

heh I had to go back and look, some kind of auto-correct running in my head I'd read it as Set :)

Chris
Chris,

I saved the above code in a .ps1 file the i run the below command:

c:\my scripts>.\bsd
c:\my scripts>

However, nothing happened when it finished and no errors shown.

Thanks
And also to mention, i replaced the server01 by the actual server name in the UNC path and i am sure the path is correct.
Ok ... what i understood from this code is, it will get the current ACL in the "201 folder\post-contract" folder. However, i couldn't understand it will paste this ACL where ? ...
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oh my God Chris !! How did you do that ? .... You a real GEEEk !! hehe

It works extremely fine now but i have couple of questions:

1- Is this will going apply the permissions recursively to all subfolders and files to the destination Post-Contract folders in each agreement ?

2- If i want to work also on Pre-Contract folders, do i just need to replace the "Post-*" by "Pre-*" in the command?

Note: i said destination because now the command got a source and destination, source that get the ACL from and destination to apply that ACL to. :)))))

Cheers

> You a real GEEEk !! hehe

Yes, yes I am :) Scripting is just little logic puzzles, keeps me from being bored :)

1. No, it sets the template and relies on you having Inheritance set.

2. Yes :)

Chris
Ok i need now one small thing ...

Can we make the code to just replace any existing ACEs with the ACEs that is being copied? ... In other words, i want all the subfolders/files under Post-Contract to be replaced by the ACEs from source.

Thanks Man , appreciate it.

Hmm you can, but that means you lose inheritance, and that in turn makes permissions very high maintenance. Are you really sure you want that?

It would be better, in my opinion, to disable inheritance on Pre / Post (in the template), then rely on inheritance for everything beneath those folders.

Chris
Good Point ! but no worries because this actually an access restriction project requested by some department which means that the same groups will access all the Post and Pre contracts folders and their subfolders which also means nobody else will be granted access to those folders.

The problem now is when you view the security of one of the subfolder under Post-contract or Pre-contract , you will notice that there are still other groups which inherited from the top parent (shared folder) and i don't want them there. I want only those groups that are copied from source.

Also, if i need in the future to turn on inheritance to one of the subfolders, Xcacls is the right tool for this job. :))))

Ah in that case you need to disable inheritance on your template. If you're doing that in code it means setting AccessRuleProtection.

e.g.

$TemplateAcl = Get-Acl $TemplateFolder
$TemplateAcl.SetAccessRuleProtection($True, $False)

The second argument tells it to remove existing entries when turning off rule protection.

You should only need to do that once in your template acl, not on everything else.

Chris
Chris, as you know, i am not a Geek like you :)) so can you re-write the code and include those 2 new lines in it?

Thx

Well you don't really need to because you only have to disable inheritance there once you see :)

Chris
Chris, Sorry maybe i mis-described my request.

Instead of turning off Inheritance, can we simply turn on the "Replace all existing inheritable permissions on all descendants with inhetitable permissions in this object" on every Post-contract and Pre-Contract folder? .... By this way, the code will not only apply permissions copied from source but will also take these permissions and override all the subfolders permissions.

You know what i mean ? :)

I do :)

Lets see how this gets on for that then.

Chris
<#
  .Synopsis
    A short script to update permissions.
  .Description
    This script takes a template ACL and applies that to any folders it finds
    in a directory structure.

    This script also supports Verbose and WhatIf parameters.
  .Parameter Path
    The folder structure to search.
  .Parameter Filter
    A filter string used when searching for folders.
  .Parameter TemplatePath
    The path used to read a template access control list.
#>

[CmdLetBinding(SupportsShouldProcess = $True)]
Param(
  [Parameter(Mandatory = $True, Position = 0)]
  [ValidateScript( { Test-Path $_ } )]
  [String]$Path,
  [String]$Filter,
  [Parameter(Mandatory = $True)]
  [ValidateScript( { Test-Path $_ } )]
  [String]$TemplatePath
)

# Load the template ACL
$Acl = Get-Acl $TemplatePath

Write-Verbose "Beginning folder search from $Path"

Get-ChildItem $Path -Filter $Filter -Recurse | ?{ $_.PsIsContainer } | %{

  Write-Verbose "Modifying access control list on $($_.FullName)"

  If ($PsCmdLet.ShouldProcess($($_.FullName))) {
    # Apply the ACL
    Set-Acl $_.FullName -AclObject $Acl

    # Deal with inheritance down the tree
    Get-ChildItem $_.FullName -Recurse | %{
      $ChildAcl = $_.FullName
      # Re-enable inheritance
      $ChildAcl.SetAccessProtection($False, $False)
      # Remove any entries which have been defined here (leaving inherited entries)
      $ChildAcl.Access | 
        ?{ $_.IsInherited -eq $False } | 
        %{ $ChildAcl.RemoveAccessRuleSpecific($_) }
      # Re-apply the ACL
      Set-Acl $_.FullName -AclObject $ChildAcl
    }
  }
}

Open in new window

Ok i got the below error:

Set-Acl : Cannot bind parameter 'AclObject'. Cannot convert the "C:\test\800-9
0\POST-Contract\New Text Document.txt" value of type "System.String" to type "
ystem.Security.AccessControl.ObjectSecurity".
At C:\my scripts & tools\test_bsd.ps1:51 char:37
+       Set-Acl $_.FullName -AclObject <<<<  $ChildAcl
    + CategoryInfo          : InvalidArgument: (:) [Set-Acl], ParameterBinding
   Exception
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerSh
   ell.Commands.SetAclCommand

Ooops :)

Chris
<#
  .Synopsis
    A short script to update permissions.
  .Description
    This script takes a template ACL and applies that to any folders it finds
    in a directory structure.

    This script also supports Verbose and WhatIf parameters.
  .Parameter Path
    The folder structure to search.
  .Parameter Filter
    A filter string used when searching for folders.
  .Parameter TemplatePath
    The path used to read a template access control list.
#>

[CmdLetBinding(SupportsShouldProcess = $True)]
Param(
  [Parameter(Mandatory = $True, Position = 0)]
  [ValidateScript( { Test-Path $_ } )]
  [String]$Path,
  [String]$Filter,
  [Parameter(Mandatory = $True)]
  [ValidateScript( { Test-Path $_ } )]
  [String]$TemplatePath
)

# Load the template ACL
$Acl = Get-Acl $TemplatePath

Write-Verbose "Beginning folder search from $Path"

Get-ChildItem $Path -Filter $Filter -Recurse | ?{ $_.PsIsContainer } | %{

  Write-Verbose "Modifying access control list on $($_.FullName)"

  If ($PsCmdLet.ShouldProcess($($_.FullName))) {
    # Apply the ACL
    Set-Acl $_.FullName -AclObject $Acl

    # Deal with inheritance down the tree
    Get-ChildItem $_.FullName -Recurse | %{
      $ChildAcl = Get-Acl $_.FullName
      # Re-enable inheritance
      $ChildAcl.SetAccessProtection($False, $False)
      # Remove any entries which have been defined here (leaving inherited entries)
      $ChildAcl.Access | 
        ?{ $_.IsInherited -eq $False } | 
        %{ $ChildAcl.RemoveAccessRuleSpecific($_) }
      # Re-apply the ACL
      Set-Acl $_.FullName -AclObject $ChildAcl
    }
  }
}

Open in new window

I got this new one too : )

Method invocation failed because [System.Security.AccessControl.FileSecurity]
oesn't contain a method named 'SetAccessProtection'.
At C:\my scripts & tools\test_bsd.ps1:45 char:36
+       $ChildAcl.SetAccessProtection <<<< ($False, $False)
    + CategoryInfo          : InvalidOperation: (SetAccessProtection:String) [
   ], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Chris,

I think that's enough talking and bothering you anymore as the above script is the real final one that exactly suits my needs. I really want to thank you for your valuable efforts and if i have more than 1000 points to give you , i would do that but this is the EE points limitation. (Max 500)

Thanks Man , keep up the excellent work !

 

You're welcome :)

Chris