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 }