I’m still working on clearing up an enormous number of public folders prior to migration to Exchange 2010 (from 2007).
The permissions structure was not well managed so I have been applying a set of standard groups (Read, Update and Change) to each PF, and at the same time removing any rights granted to Everyone and ANONYMOUS LOGON, and tidying up ACLs left over from deleted accounts.
PF permissions are difficult to fix because they are applied directly to each group. When a PF is created it inherits the rights of its parent, but after that its ACL is individually managed. You can’t just change a permission at the top and expect it to filter down.
Another thing to note about PF permissions is that they are cumulative and there is no deny. The only way to prevent someone seeing a PF is to not give them any rights in the first place.
The final point to note is that deleted accounts don’t seem to get cleared out of the ACL automatically, so by far the best practise is to use groups. Here I have previously created a set of permissions groups for each major folder tree, with their names denoted by the $pfgroupstub that is passed to the script..
To run the script I call it like so (the double-quoting is needed if there are spaces in the folder names):
./fix-pfacl.ps1 -pfroot "'/Top Folder/sub-folder'" -pfgroupstub 'PF_subfolder'
This would have the effect of setting the permissions like this:
| \Everyone | None |
| NT AUTHORITY\ANONYMOUS LOGON | None |
| MYDOMAIN\PF_subfolder_Read | Reviewer |
| MYDOMAIN\PF_subfolder_Update | Author |
| MYDOMAIN\PF_subfolder_Change | Publishing Editor |
| MYDOMAIN\PF_ALL_Read | Reviewer |
| MYDOMAIN\PF_ALL_Update | Author |
| MYDOMAIN\PF_ALL_Change | Publishing Editor |
Note: Any other explicit rights that were already applied will not be affected.
The Script
PARAM([string]$pfroot,[string]$pfgroupstub)
[string]$pfserver = 'MyServer'
[string]$read_group = $pfgroupstub + '_Read'
[string]$update_group = $pfgroupstub + '_Update'
[string]$change_group = $pfgroupstub + '_Change'
[boolean]$stdok = $false
function fixacl([string]$pfname) {
 $pfacl = get-publicfolderclientpermission -server $pfserver -identity $pfname
 write-host $pfname
 foreach ($acl in $pfacl){
   if ($acl.User.IsAnonymous -eq $true -and $acl.AccessRights[0].Permission -ne 'None'){
     remove-publicfolderclientpermission -server $pfserver -identity $pfname -user $acl.User -AccessRights $acl.AccessRights -Confirm:$false -erroraction silentlycontinue
     write-host "Removed ANONYMOUS"
   }
   if ($acl.User.IsDefault -eq $true -and $acl.AccessRights[0].Permission -ne 'None'){
     remove-publicfolderclientpermission -server $pfserver -identity $pfname -user $acl.User -AccessRights $acl.AccessRights -Confirm:$false -erroraction silentlycontinue
     write-host "Removed Everyone"
   }
   if (($acl.User.ExchangeAddressBookDisplayName -ne $null) -and ($acl.User.ExchangeAddressBookDisplayName.StartsWith('NT User:S-1-5'))){
     remove-publicfolderclientpermission -server $pfserver -identity $pfname -user $acl.User -AccessRights $acl.AccessRights -Confirm:$false -erroraction silentlycontinue
     write-host "Removed deleted"
   }
   if (($acl.User.ExchangeAddressBookDisplayName -ne $null) -and ($acl.User.ExchangeAddressBookDisplayName.Contains($pfgroupstub))){
     $stdok = $true
   }
 }
 if ($stdok -eq $false){
   write-host "Adding default groups"
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user $read_group -AccessRights Reviewer -Confirm:$false -erroraction silentlycontinue
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user $update_group -AccessRights Author -Confirm:$false -erroraction silentlycontinue
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user $change_group -AccessRights PublishingEditor -Confirm:$false -erroraction silentlycontinue
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user 'PF_ALL_Read' -AccessRights Reviewer -Confirm:$false -erroraction silentlycontinue
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user 'PF_ALL_Update' -AccessRights Author -Confirm:$false -erroraction silentlycontinue
   add-publicfolderclientpermission -server $pfserver -identity $pfname -user 'PF_ALL_Change' -AccessRights PublishingEditor -Confirm:$false -erroraction silentlycontinue
 }
}
$getpfcmd = "get-publicfolder -identity $pfroot -server $pfserver -Recurse -resultsize unlimited"
invoke-expression $getpfcmd | foreach {
   fixacl -pfname $_.Identity
}