Jorge's Quest For Knowledge!

All About Identity And Security On-Premises And In The Cloud – It's Just Like An Addiction, The More You Have, The More You Want To Have!

(2012-03-28) Managing The ‘Protect From Accidental Deletion’ Option On AD Objects Through PowerShell

Posted by Jorge on 2012-03-28

In this post I explain the “Protect From Accidental Deletion” feature that is made accessible through both “Active Directory Users And Computers” and “Active Directory Administrative Center”. Under the hood that feature in reality is implemented through a combination of ACEs on objects. If you wanted to script the addition or removal of the protection you had to screw with ACEs and that was not always a fun thing to do as it could be quite complex to achieve a simple configuration.

Let’s say you want to create and protect the OU "OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB". The OU "OU=TOPLevel,DC=ADCORP,DC=LAB" already exists and is already protected!

[1] Using ADMOD and DSACLS

Creating the OU:

  • ADMOD -sc adaou:1;OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB

Adding the protection:

  • DSACLS "OU=TOPLevel,DC=ADCORP,DC=LAB" /D "EVERYONE:DC" (DENY ACE for Everyone to DELETE CHILD with the This object only scope)
  • DSACLS "OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB" /D "EVERYONE:SDDT" (DENY ACE for Everyone to DELETE and DELETE TREE with the This object only scope)

[2] Using the Microsoft AD PowerShell CMDlets And Configuring The Correct ACEs

Creating the OU (I know I could use the CMDlet “New-ADOrganizationalUnit”…):

  • $objOU = $objParent.Create("organizationalUnit","OU=MyProtectedOU")
  • $objOU.SetInfo()

Adding the protection:

  • Import-Module ActiveDirectory
  • $sidEVERYONE = [System.Security.Principal.SecurityIdentifier]’S-1-1-0′
  • $ACLParent = Get-Acl "AD:\OU=TOPLevel,DC=ADCORP,DC=LAB"
  • $ACEParent = $sidEVERYONE,"DeleteChild","Deny"
  • $AccessRuleParent = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $ACEParent
  • $ACLParent.AddAccessRule($AccessRuleParent)
  • Set-Acl -ACLObject $ACLParent -Path "AD:\OU=TOPLevel,DC=ADCORP,DC=LAB"
  • $ACLOU = Get-Acl "AD:\OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB"
  • $ACEOU = $sidEVERYONE,"Delete,DeleteTree","Deny"
  • $AccessRuleOU = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $ACEOU
  • $ACLOU.AddAccessRule($AccessRuleOU)
  • Set-Acl -ACLObject $ACLOU -Path "AD:\OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB"

Removing the protection:

  • Import-Module ActiveDirectory
  • $sidEVERYONE = [System.Security.Principal.SecurityIdentifier]’S-1-1-0′
  • $ACLOU = Get-Acl "AD:\OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB"
  • $ACEOU = $sidEVERYONE,"Delete,DeleteTree","Deny"
  • $AccessRuleOU = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $ACEOU
  • $ACLOU.RemoveAccessRule($AccessRuleOU)
  • Set-Acl -ACLObject $ACLOU -Path "AD:\OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB"

[3] Using the Microsoft AD PowerShell CMDlets And Using The Exposed Property

Creating the OU:

  • Import-Module ActiveDirectory
  • New-ADOrganizationalUnit -Name ‘MyProtectedOU’ -Path ‘OU=TOPLevel,DC=ADCORP,DC=LAB’

REMARK: when using this CMDlet, the default behavior is to protect the created OU

Adding the protection:

  • Import-Module ActiveDirectory
  • Set-ADOrganizationalUnit "OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB" -ProtectedFromAccidentalDeletion:$true

Removing the protection:

  • Import-Module ActiveDirectory
  • Set-ADOrganizationalUnit "OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB" -ProtectedFromAccidentalDeletion:$false

[4] Using the Quest AD PowerShell CMDlets

Creating the OU:

  • Add-PSSnapin Quest.ActiveRoles.ADManagement
  • New-ADOrganizationalUnit -Name ‘MyProtectedOU’ -Path ‘OU=TOPLevel,DC=ADCORP,DC=LAB’

Adding the protection:

  • Add-PSSnapin Quest.ActiveRoles.ADManagement
  • Add-QADPermission -identity ‘OU=TOPLevel,DC=ADCORP,DC=LAB’ -Deny -Account ‘EVERYONE’ -Right ‘DeleteChild’ -ApplyTo ThisObjectOnly
  • Add-QADPermission -identity ‘OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB’ -Deny -Account ‘EVERYONE’ -Right ‘Delete,DeleteTree’ -ApplyTo ThisObjectOnly

Removing the protection:

  • Add-PSSnapin Quest.ActiveRoles.ADManagement
  • Get-QADPermission -identity ‘OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB’ -Deny -Account ‘EVERYONE’ -Right ‘Delete,DeleteTree’ -ApplyTo ThisObjectOnly | Remove-QADPermission

[5] Adjusting the default security descriptor for OUs

When you create any object, that object will receive the default explicit permissions as configured in the AD schema. So, by adjusting the default explicit permissions (a.k.a. the default Security Descriptor) for the organizationalUnit objectClass any newly created organizational unit from that point on will receive the new default security descriptor. The change to the default security descriptor can be undone if you desire so! However, just making the change is not enough as the schema is cached for performance reasons. Therefore any changes to the AD schema will be refreshed into the cache within five minutes after the change has been committed into the database. If you cannot wait and you want to reload the schema right away you can follow either of the following procedures:

  1. Start the Active Directory Schema MMC, right-click “Active Directory Schema” and then click “Reload the Schema”
  2. Add the “schemaUpdateNow” operational attribute to rootDSE with a value of 1

For more detailed information about the schema please see: How the Active Directory Schema Works

To adjust the default security descriptor for the organizationalUnit objectClass perform the following steps:

  1. Open ADSIEDIT.MSC and connect to the SCHEMA naming context
  2. Find the object “CN=Organizatinal-Unit” and adjust the value of the “defaultSecurityDescriptor” property
    1. From the default value:
      1. D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(OA;;CCDC;bf967a86-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967aba-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967a9c-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967aa8-0de6-11d0-a285-00aa003049e2;;PO)(A;;RPLCLORC;;;AU)(A;;LCRPLORC;;;ED)(OA;;CCDC;4828CC14-1437-45bc-9B07-AD6F015E5F28;;AO)
    2. To the custom value (difference with the default has been highlighted in red):
      1. D:(D;;DCDTSD;;;WD)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(OA;;CCDC;bf967a86-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967aba-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967a9c-0de6-11d0-a285-00aa003049e2;;AO)(OA;;CCDC;bf967aa8-0de6-11d0-a285-00aa003049e2;;PO)(A;;RPLCLORC;;;AU)(A;;LCRPLORC;;;ED)(OA;;CCDC;4828CC14-1437-45bc-9B07-AD6F015E5F28;;AO)


Figure 1: Adjusting The Default Security Descriptor Of The ObjectClass OrganizationalUnit

REMARK: During my testing with Windows Server “8” Beta, I discovered that there is a difference in behavior between ADUC and ADAC if you select to NOT protect the if the above custom configuration for the default security descriptor is in place. In ADAC, after the new object has been created/instantiated it will in addition remove the protection as expected. However, in ADUC it will not be removed as requested. I’m not sure if Microsoft will change this unexpected behavior for ADUC in the official release of Windows Server “8”. Just be aware of this!

* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
############### Jorge’s Quest For Knowledge #############
######### ########


5 Responses to “(2012-03-28) Managing The ‘Protect From Accidental Deletion’ Option On AD Objects Through PowerShell”

  1. Steven said

    Hi Jorge

    Great post and forgive me for my simple question. But if i want to protect all OU’s in my domain whats the simplest way to recurse this command?

    •Set-ADOrganizationalUnit “OU=MyProtectedOU,OU=TOPLevel,DC=ADCORP,DC=LAB” -ProtectedFromAccidentalDeletion:$true

    Many Thanks

    • Jorge said

      that would something like:
      Import-Module ActiveDirectory
      $domainNC = (Get-ADDomain)[“DistinguishedName”]
      Get-ADOrganizationalUnit -SearchBase $($domainNC) -Filter ‘*’ -Properties ProtectedFromAccidentalDeletion | ?{$_.ProtectedFromAccidentalDeletion -eq $false} | %{Set-ADOrganizationalUnit $_ -ProtectedFromAccidentalDeletion:$true}

      The last line gets all OUs, filters the list for OUs NOT protected and for those it protect them

      Have fun! (test first in test environment!)

      • Steven said

        Jorge what can i say! Fantastic worked a treat.

        Thankyou so much for spending the time to help me out

  2. […] it looks like Jorge de Almeida Pinto blogged about scripting this using PowerShell:… 43.692800 6.845744 Like this:LikeBe the first to like this post. Tags: OU Comments RSS […]

  3. […] read Jorge’s blog posting on management of the “Protect from Accidental Deletion” feature (…) He describes the different methods and possibilities to set and unset it using different available […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: