Skip to main content

Managed Deletion Protection on OUs, User, and Group objects with PowerShell

Below is a working PowerShell function that will help you enable/disable Deletion Protection on organizational units, user and group objects.  I included online help in this one so just dot source it or put it in a module to use it.  Once loaded, just type Get-Help Set-Deletion Protection –Full to see the entire help file and examples on how to use it.

There are actually two functions here.  The first supports the second.


<#
.SYNOPSIS

Confirms if a module is available.



.DESCRIPTION

Confirms if the provided parameter is available on

the local client.

 
 
.PARAMETER ModuleName
 
The name of the module who’s presence is being checked.
 
  
  
.EXAMPLE
  
Confirm-Module ActiveDirectory
  
   
   
Checks to see if the ActiveDirectory module is
   
present on the local machine
   
    
    
Returns True is present and False if not.
    
     
     
.OUTPUTS
     
Boolean
     
      
      
.Link
      
Get-Module
      
#>
Function Confirm-Module

{

Param ($ModuleName = $(Throw "You need to provide a module name."))



 # Place the name of the module from Get-Module into

 # the variable $Data

 $Data = (Get-Module -ListAvailable -Name $ModuleName).name

 
 
 # If the contents of $Data is equal to the variable
 
 # $ModuleName, the module is present, return
 
 # True.  If not, return $False.
 
 If ($Data -eq $ModuleName){Return $True}
 
 Else {Return $False}   
 
}



<#
.SYNOPSIS
Ensures that Deletion Protection is set on AD Objects

.DESCRIPTION
Allows you to set the Deletion Protection on specific classes of objects in an Active Directory Environment.
This allows you to set Deletion Protection on both User and Group objects that otherwise do not have this capability in the Set-ADUser and Set-ADGroup cmdlets.

.PARAMETER Enabled
Sets whether to enable or disable Deletion Protection on the specified object classes.  This value must be set as $True or $False.

.PARAMETER OU
Targets the Organizational Units objects in Active Directory.

.PARAMETER Group
Targets the group objects in Active Directory.

.PARAMETER User
Targets the user objects in Active Directory.

.PARAMETER Root
The name of the OU or Container to use as the root for processing the cmdlet . By default, all objects in the domain are processed for the object classes specified.

.EXAMPLE
Set-DeletionProtection $True -OU

Protects all Organization Units in the domain from accidental deletion.

.EXAMPLE
Set-DeletionProtection $True -User -Group

Protects all User and Group objects in the domain from accidental deletion.

.EXAMPLE
Set-DeletionProtection $False -User -Root "IT Managers"

Removes Deletion Protection for all Users in the OU or Container whos' distinguished name contains "IT Managers"

.EXAMPLE
Set-DeletionProtection $False -User -Root "IT"

---------------------------------------------
The following OUs or Containers matched your Root parameter: IT.  Please select the index number of the OU or Container that you want to execute this cmdlet against.


Index DistinguishedName
----- -----------------
    0 CN=ForeignSecurityPrincipals,DC=Contoso,DC=com
    1 CN=IP Security,CN=System,DC=Contoso,DC=com
    2 CN=ComPartitions,CN=System,DC=Contoso,DC=com
    3 CN=ComPartitionSets,CN=System,DC=Contoso,DC=com
    4 OU=IT,DC=Contoso,DC=com
    5 OU=IT Test,OU=IT,DC=Contoso,DC=com

Index number:

In the above example, the cmdlet is attempting to remove deletion protection from all User Objects that is in an OU or Container that contains "IT" in the Distinguished Name.  The problem is that multiple OUs or Containers contain "IT" in them.  The menu presented above to the user will allow the user to choose the index number of the OU or Container to execute the cmdlet against.

.EXAMPLE
Set-Deletionprotection $True -OU -Root "OfficeStaff"

---------------------------------------------
No OU or Container matched your query.
The Cmdlet is terminating with no changes made.

The cmdlet above is attempting to enable Deletion Protection on all OUs or Containers with the name "OfficeStaff" in the Distinguished Name.  In this case, no OU or Container in the domain has the string "OfficeStaff: in it.

.NOTES
The Active Directory Module for PowerShell must be Available

Active Directory Users and Computers will be non- responsive while this cmdlet runs.

.LINK
Get-ADUser
Get-ADGroup
Get-ADOrganizationalUnit
Set-ADObject
Set-ADOrganizationalUnit
Import-Module
#>

function Set-DeletionProtection
{
param (
    [Parameter(Position=0,Mandatory=$True)][Boolean]$Enabled,
    [switch]$OU,
    [switch]$Group,
    [switch]$User,
   $Root = "*"
)


# Verify Boolean value for parameter $Enabled.
if ($Enabled.GetType().Name -ne "Boolean")
    {
    Write-Host "Please supply a Boolean value of $True or $False"
    break
    }

# Test to verify that
if ((Confirm-module ActiveDirectory) -eq $True)
    {
    # Import the Active Directory module.
    Import-Module ActiveDirectory -cmdlet Get-ADOrganizationalUnit, Set-ADOrganizationalUnit,
        Get-ADGroup, Get-ADUser, Set-ADObject
    }
else
    {
    Write-Host "Active Directory Module is not available."
-ForegroundColor Red -BackgroundColor Yellow
    break
    }


# If the $Root parameter is populated, make sure it points to a unique # container or OU.  If not, present the user with a list to choose from.
if ($Root -ne "*")
{


    $ObjList = @()

    $List = Get-ADObject -Filter * |
        Where-Object {($_.DistinguishedName -like "*$root*") -and (($_.ObjectClass -eq "OrganizationalUnit") -or ($_.ObjectClass -eq "Container"))}


    # Creates the index number should the query return
    # multiple matches.
    $i = 0

    # Loop through each returned item and enter the
    # data into an object to be used to determine
    # which object should be used.
    foreach ($Item in $List)
        {
        $Object = New-Object PSObject
        $Object | Add-Member NoteProperty -Name DistinguishedName -Value $Item.DistinguishedName
        $Object | Add-Member NoteProperty -Name Index -Value $i
        $ObjList += $Object
        $i++
        }


    # If more than 1 OU or Container matches the query,
    # Present a menu to the user to choose from.
    if ($ObjList.Count -gt 1)
        {
        Write-Host "---------------------------------------------"
-ForegroundColor Yellow
        Write-Host "The following OUs or Containers matched your"
        Write-Host "Root parameter: $Root.  Please select the"
        Write-Host "index number of the OU or Container that"
        Write-Host "you want to execute this cmdlet against."
        Write-Host " "
        $ObjList | FT Index, DistinguishedName -autosize
        Write-Host " "
        $Selection = Read-Host ("Index number")

        $Root = $ObjList[$Selection].DistinguishedName
        }

    # If no OUs or Containers match the query, send
    # an error message and suspend the cmdlet.
    if (($ObjList.Count -eq 1) -and ($ObjList.DistinguishList -eq $Null))
        {
        Write-Host "---------------------------------------------"
-ForegroundColor Red
        Write-Host "No OU or Container matched your query."
        Write-Host "The Cmdlet is terminating with no changes made."
        }

    # If only one OU or Container matched the query
    # than use it
    if ($ObjList.Count -eq 1)
        {
        $Root = $ObjList[0].DistinguishedName
        }

}


# Configure Deletion protection for OUs.
if ($OU -eq $True)
    {
    Get-ADOrganizationalUnit -Filter * |
    where {$_.DistinguishedName -like "*$root*"} |
    Where-Object {$_.ProtectedFromAccidentalDeletion -ne $Enabled} |
    Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $Enabled
    }
# End configuration for OUs.

# Configure Deletion protection for Groups.
if ($Group -eq $True)
    {
     Get-ADGroup -Filter * |
     where {$_.DistinguishedName -like "*$root*"} |
     Where-Object {$_.ProtectedFromAccidentalDeletion -ne $Enabled} |
     Set-ADObject -ProtectedFromAccidentalDeletion $Enabled

# End configuration for Groups.

# Configure Deletion protection for Users.
if ($User -eq $True)
    {
     Get-ADUser -Filter * |
     where {$_.DistinguishedName -like "*$root*"} |
     Where-Object {$_.ProtectedFromAccidentalDeletion -ne $Enabled} |
     Set-ADObject -ProtectedFromAccidentalDeletion $Enabled
    }
# End configuration for Users.

Write-Host "Deletion protection changes in progress."
Write-Host "Active Directory Users and Computers may be un-responsive"
Write-Host "for a few seconds."
}

Comments

jay c said…
Thanks, Jason! This was the bit of code I needed:

get-aduser | set-adobject -protectedfromaccidentaldeletion $false

Popular posts from this blog

Adding a Comment to a GPO with PowerShell

As I'm writing this article, I'm also writing a customization for a PowerShell course I'm teaching next week in Phoenix.  This customization deals with Group Policy and PowerShell.  For those of you who attend my classes may already know this, but I sit their and try to ask the questions to myself that others may ask as I present the material.  I finished up my customization a few hours ago and then I realized that I did not add in how to put a comment on a GPO.  This is a feature that many Group Policy Administrators may not be aware of. This past summer I attended a presentation at TechEd on Group Policy.  One organization in the crowd had over 5,000 Group Policies.  In an environment like that, the comment section can be priceless.  I always like to write in the comment section why I created the policy so I know its purpose next week after I've completed 50 other tasks and can't remember what I did 5 minutes ago. In the Group Policy module for PowerShell V3, th

Return duplicate values from a collection with PowerShell

If you have a collection of objects and you want to remove any duplicate items, it is fairly simple. # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   # Remove the duplicate values. $Set1 | Select-Object -Unique 1 2 3 4 5 6 7 What if you want only the duplicate values and nothing else? # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   #Create a second collection with duplicate values removed. $Set2 = $Set1 | Select-Object -Unique   # Return only the duplicate values. ( Compare-Object -ReferenceObject $Set2 -DifferenceObject $Set1 ) . InputObject | Select-Object – Unique 1 2 This works with objects as well as numbers.  The first command creates a collection with 2 duplicates of both 1 and 2.   The second command creates another collection with the duplicates filtered out.  The Compare-Object cmdlet will first find items that are diffe

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.