SID HISTORY: Fixing Exchange
Dumping my notes about fixing SID history at work. Use at your own risk. These worked for me but won't work for you without some adjustments.
Locate and repair AD user accounts with acl inheritance flag uncheck. This prevents Exchange service accounts from altering user object and breaks various admin tools.
Fix mailbox permissions. First we grant “NT AUTHORITY\SELF” full access to mailbox which is default for Exchange 2007 and newer versions. Then we delete any permissions granted to valid user but with invalid SID (via SIDhistory). Next same permissions are added back which causes Exchange to resolve correct SID and joins permissions in case user had different permissions via new SID and SIDhistory SID. Finally any ACLs with unresolvable SIDs are removed.
Fix public folder permissions. Here we delete invalid ACLs. Then we delete valid ACLs and re-create them. Many folders had permission corruption preventing Outlook and Exchange Management Console from accessing permission settings entirely without this.
Fix distribution list permissions.
Locate and repair AD user accounts with acl inheritance flag uncheck. This prevents Exchange service accounts from altering user object and breaks various admin tools.
# Download and install Quest AD PowerShell addon # http://www.quest.com/powershell/activeroles-server.aspx # Dump AD acl permission inheritance status for email enabled accounts before change Get-QADUser -SizeLimit 0 | where {$_.primarysmtpaddress -ne $null}|Select-Object SamAccountName,Name,@{n='IncludeInheritablePermissions';e={!$_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected}}| Export-Csv -Encoding unicode -NoTypeInformation adpermissions-inheritance-pre.csv # Enable AD acl permission inheritance for email enabled accounts, otherwise attempts to alter mailbox permissions will fail Get-QADUser -SizeLimit 0 | where {$_.primarysmtpaddress -ne $null -and $_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected} | Set-QADObjectSecurity -UnLockInheritance # Dump AD acl permission inheritance status for email enabled accounts after change Get-QADUser -SizeLimit 0 | where {$_.primarysmtpaddress -ne $null}|Select-Object SamAccountName,Name,@{n='IncludeInheritablePermissions';e={!$_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected}}| Export-Csv -Encoding unicode -NoTypeInformation adpermissions-inheritance-post.csv
Fix mailbox permissions. First we grant “NT AUTHORITY\SELF” full access to mailbox which is default for Exchange 2007 and newer versions. Then we delete any permissions granted to valid user but with invalid SID (via SIDhistory). Next same permissions are added back which causes Exchange to resolve correct SID and joins permissions in case user had different permissions via new SID and SIDhistory SID. Finally any ACLs with unresolvable SIDs are removed.
# Dump list of mailbox permissions including SIDs prior making any changes Get-Mailbox -ResultSize unlimited | Get-MailboxPermission | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},Deny,IsInherited,InheritanceType,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation mbpermissions-all-pre.csv # Grant everyone access to their own mailbox, this is default with Exchange 2007 and newer but still sometimes wrong for older migrated accounts Get-mailbox -resultsize unlimited | Add-ADPermission -User "NT AUTHORITY\SELF" -ExtendedRights "Send-as" | ft -autosize -wrap Get-mailbox -resultsize unlimited | Add-MailboxPermission -user "NT AUTHORITY\SELF" -Accessrights FullAccess | ft -autosize -wrap # Get list of mailbox permissions with old SIDs $fixmbperm = Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission | where {$_.IsInherited -eq $false -and $_.Deny -eq $false -and $_.user -like "MYCORP\*"} | where {$_.user.securityidentifier -notlike "S-1-5-21-1423493088-*"} # Save old permissions to file for future reference echo $fixmbperm | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation mbpermissions-fix.csv # Delete permissions WITHOUT confirmation echo $fixmbperm | %{Remove-MailboxPermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Restore permissions WITHOUT confirmation echo $fixmbperm | %{Add-MailboxPermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Cleanup variable Remove-Variable fixmbperm # Get list of mailbox permissions without matching AD account (SID only) $badmbperm = Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission | where {$_.IsInherited -eq $false -and $_.Deny -eq $false -and $_.user -like "S-1-5-21-*"} # Save old permissions to file for future reference echo $badmbperm | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation mbpermissions-bad.csv # Delete permissions WITHOUT confirmation echo $badmbperm | %{Remove-MailboxPermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Cleanup variable Remove-Variable badmbperm # Dump list of mailbox permissions including SIDs after changes Get-Mailbox -ResultSize unlimited | Get-MailboxPermission | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},Deny,IsInherited,InheritanceType,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation mbpermissions-all-post.csv
Fix public folder permissions. Here we delete invalid ACLs. Then we delete valid ACLs and re-create them. Many folders had permission corruption preventing Outlook and Exchange Management Console from accessing permission settings entirely without this.
# Dump all public folder permissions to file prior making any changes get-publicfolder "\" -recurse -resultsize unlimited| get-publicfolderclientpermission | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Sort-Object Identity,User|Export-Csv -Encoding unicode -NoTypeInformation pfpermissions-all-pre.csv # Get permissions granted for deleted accounts and accounts with mailbox deleted (disabled users) $badpfperm = get-publicfolder "\" -recurse -resultsize unlimited | get-publicfolderclientpermission | where {$_.user -like "NT User:S-1-*" -or $_.user -like "NT User:MYCORP\*"} | Sort-Object Identity,User # Store list of permissions we're about to delete in CSV file for future reference echo $badpfperm | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation pfpermissions-bad.csv # Delete outdated permissions WITHOUT confirmation echo $badpfperm | %{remove-publicfolderclientpermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Cleanup variable Remove-Variable badpfperm # Get all valid permissions granted (excluding Default and Anonymous) $okpfperm = get-publicfolder "\" -recurse -resultsize unlimited| get-publicfolderclientpermission | where {$_.user -notlike "NT User:S-1-*" -and $_.user -notlike "NT User:MYCORP\*" -and $_.user -notlike "Default" -and $_.user -notlike "Anonymous"} | Sort-Object Identity,User # Store list of permissions we're about to alter in CSV file for future reference echo $okpfperm | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -Encoding unicode -NoTypeInformation pfpermissions-ok.csv # Delete permissions WITHOUT confirmation echo $okpfperm | %{remove-publicfolderclientpermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Restore permissions WITHOUT confirmation echo $okpfperm | %{add-publicfolderclientpermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} # Cleanup variable Remove-Variable okpfperm # Dump all public folder permissions to file after making changes get-publicfolder "\" -recurse -resultsize unlimited| get-publicfolderclientpermission | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Sort-Object Identity,User|Export-Csv -Encoding unicode -NoTypeInformation pfpermissions-all-post.csv
Fix distribution list permissions.
# Dump list of distribution list permissions including SIDs prior making any changes Get-DistributionGroup -ResultSize unlimited | Get-ADPermission | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},Deny,IsInherited,InheritanceType,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}},@{Name='Extended Rights';Expression={[string]::join(', ', $_.ExtendedRights)}} | Export-Csv -Encoding unicode -NoTypeInformation dlpermissions-all-pre.csv # Get list of distribution list permissions with old SIDs $fixdlperm = Get-DistributionGroup -ResultSize Unlimited | Get-ADPermission | where {$_.IsInherited -eq $false -and $_.Deny -eq $false -and $_.user -like "MYCORP\*"} | where {$_.user.securityidentifier -notlike "S-1-5-21-1423493088-*"} # Save old permissions to file for future reference echo $fixdlperm | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}},@{Name='Extended Rights';Expression={[string]::join(', ', $_.ExtendedRights)}} | Export-Csv -Encoding unicode -NoTypeInformation dlpermissions-fix.csv # Split regular and extended access rights to different variables $fixdlpermac = echo $fixdlperm | where {$_.accessrights -ne $null -and $_.ExtendedRights -eq $null} $fixdlpermex = echo $fixdlperm | where {$_.ExtendedRights -ne $null} # Delete permissions WITHOUT confirmation # This fail due bug like feature in Remove-ADPremissions causing it to first resolve old SID to username and then trying to remove ACL using new SID... idiots. #echo $fixdlpermac | %{Remove-ADPermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} #echo $fixdlpermex | %{Remove-ADPermission -identity $_.identity -user $_.user -extendedrights $_.ExtendedRights -confirm:$false} # Restore permissions WITHOUT confirmation # Because you can't delete old SIDs this will add new ACL entries for same users with new SID leaving ghost SIDs after SID history is removed echo $fixdlpermac | %{Add-ADPermission -identity $_.identity -user $_.user -access $_.accessrights -confirm:$false} echo $fixdlpermex | %{Add-ADPermission -identity $_.identity -user $_.user -extendedrights $_.ExtendedRights -confirm:$false} # If you get access denied errors from two commands above check permissions on AD, don't be surprised if they're completely messed up due to incorrectly made old migration projects # Dump list of distribution list permissions including SIDs after making changes Get-DistributionGroup -ResultSize unlimited | Get-ADPermission | Select Identity,User,@{Name='SID';Expression={$_.user.securityidentifier}},Deny,IsInherited,InheritanceType,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}},@{Name='Extended Rights';Expression={[string]::join(', ', $_.ExtendedRights)}} | Export-Csv -Encoding unicode -NoTypeInformation dlpermissions-all-post.csv # Cleanup variable Remove-Variable fixdlperm Remove-Variable fixdlpermac Remove-Variable fixdlpermex
Comments
Post a Comment
Got something to say?!