How to Protect Organizational Units (OUs) from Accidental Deletion created on Windows Server 2003 or Windows 2000 Server Domain Controllers

 

When you create an OU in a Domain using Active Directory Users and Computers (ADUC) on Windows Server 2008 Domain Controller, by default, the “Protect container from accidental deletion” box is checked

 

This feature in Windows Server 2008 adds “Everyone” group to the Security DACL on the OU with Deny ACE to both Delete and Delete Subtree permissions; it also sets a Deny ACE the parent OU for  Everyone “ group to Delete All Child Objects. This is an enhancement in the ADUC Console and by default all OUs created on Windows Server 2008 Domain Controllers are protected from Accidental Deletion.

Note: To see the Security tab on an object, enable Advanced Features in ADUC

On an OU which was created with “Protect container from accidental deletion” box checked, to see the Deny ACEs; right click and select Properties, click on Security tab, click on Advanced button, and click Edit to see the granular permissions, you find that the Everyone group has Deny on Delete and Delete Subtree.

 

Creating a Script to Protect all Organizational Units Similar to Windows Server 2008 ADUC

To protect all Organizational Units in ADUC from accidental deletion, whether they were created on Windows Server 2003 or Windows 2000 Server Domain Controllers, or even re-apply the same permissions to OUs created on Windows Server 2008 Domain Controllers, the script can be used.

 

Note:

It is also possible to achieve the same result by using dsquery and dsacls in one command line

For /F “tokens=*” %i in (‘dsquery ou –limit 0’) do dsacls %i /D “everyone”:”SDDT;;”

DsQuery gets all the OUs in the domain. DsAcls sets deny everyone on the found OUs for “Single Delete” (SD) and “Delete Tree” (DT)

The script has been tested on the following Microsoft Operating Systems:

Windows 7, Windows Vista, Windows XP

Windows Server 2008, Windows Server 2003, Windows 2000 Server

 

 

Understanding the Script:

Using Scripts to Manage Active Directory Security

http://www.microsoft.com/technet/scriptcenter/topics/security/exrights.mspx

 

Using Scripts to Delegate Control of Active Directory

http://www.microsoft.com/technet/scriptcenter/topics/security/propset.mspx

 

Extended Rights Reference

http://www.microsoft.com/technet/scriptcenter/topics/security/allrights.mspx

 

APPLIES TO

·         Microsoft Windows Server 2008

·         Microsoft Windows Server 2003

·         Microsoft Windows 2000 Server

 

Visual Basic
Edit|Remove
strDomName = "LDAP://dc=contoso,dc=com"

Const ADS_FLAG_OBJECT_TYPE_PRESENT = &H1
Const ADS_DOMAIN_FLAG_OBJECT_TYPE_PRESENT = &H2
Const ADS_ACEFLAG_DONOT_INHERIT_ACE = &H10040
Const ADS_RIGHT_DS_DENY_DELETE_SUBTREE = &H1
Const ADS_RIGHT_DS_DENY_DELETE = &H1
Const ACTRL_DS_DELETE_TREE = &H10042
Const ACTRL_DOMAIN_DS_DELETE_TREE = &H2
Const ADS_SCOPE_SUBTREE = 2

        Set objConnection = CreateObject("ADODB.Connection")
        Set objCommand =   CreateObject("ADODB.Command")
        objConnection.Provider = "ADsDSOObject"
        objConnection.Open "Active Directory Provider"
        Set objCommand.ActiveConnection = objConnection

        objCommand.Properties("Page Size") = 1000
        objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

        objCommand.CommandText = _
            "SELECT Name, ADsPath, distinguishedName FROM " & "'" & strDomName & "'" & _
                " WHERE objectCategory='organizationalUnit' ORDER BY Name"  
        Set objRecordSet = objCommand.Execute

                objRecordSet.MoveFirst
        Do Until objRecordSet.EOF
                strOuDN = objRecordSet.Fields("distinguishedName").Value
                strLDAPOU = "LDAP://" & strOuDN
                Set objSdUtil = GetObject(strLDAPOU)
                Set objSD = objSdUtil.Get("ntSecurityDescriptor")
                Set objDACL = objSD.DiscretionaryACL
                Set objAce = CreateObject("AccessControlEntry")

               objAce.Trustee = "Everyone"
               objAce.AceFlags = ADS_ACEFLAG_DONOT_INHERIT_ACE
               objAce.AceType = ADS_RIGHT_DS_DENY_DELETE
               objAce.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT
               objAce.AccessMask = ACTRL_DS_DELETE_TREE
               objDacl.AddAce objAce
               objSD.DiscretionaryAcl = objDacl
               objSDUtil.Put "ntSecurityDescriptor", Array(objSD)
               objSDUtil.SetInfo
  
               objRecordSet.MoveNext
        Loop

'Set DENY DELETE ALL CHILD OBJECTS on DOMAIN
Set objSdUtil = GetObject(strDomName)
            Set objSD = objSdUtil.Get("ntSecurityDescriptor")
            Set objDACL = objSD.DiscretionaryACL

 Set objAce = CreateObject("AccessControlEntry")

    objAce.Trustee = "Everyone"
    objAce.AceFlags = ADS_ACEFLAG_DONOT_INHERIT_ACE
    objAce.AceType = ADS_RIGHT_DS_DENY_DELETE
    objAce.Flags = ADS_DOMAIN_FLAG_OBJECT_TYPE_PRESENT
    objAce.AccessMask = ACTRL_DOMAIN_DS_DELETE_TREE
    objDacl.AddAce objAce
    objSD.DiscretionaryAcl = objDacl

   objSDUtil.Put "ntSecurityDescriptor", Array(objSD)
   objSDUtil.SetInfo

wscript.echo "Script Finished"