The AD Recycle Bin: Understanding, Implementing, Best Practices, and Troubleshooting

Ned here again. Starting in Windows Server 2008 R2, Active Directory now implements a true recycle bin. No longer will you need an authoritative restore to recover deleted users, groups, OU’s, or other objects. Instead, it is now possible to use PowerShell commands to bring back objects with all their attributes, backlinks, group memberships, and metadata. AD Recycle Bin (ADRB) was a long time coming and it definitely has its idiosyncrasies, but I think you are going to love it.

Today I am going to talk about a few aspects of this new system:

  • Understanding how ADRB works under the covers.
  • What the requirements are and how to turn ADRB on.
  • Using ADRB, along with some best practices.
  • Troubleshooting common issues people run into with ADRB.

Armed with this information, you should be able to speak with authority on the AD Recycle Bin and perhaps, save your company from a disaster someday.

Let’s get cranking, IT super hero.

How AD Recycle Bin Works

Simply put, ADRB allows you to recover objects immediately, without the need to use your System State backups, latent sites, or 3rd party add-ons. It does this by implementing two new attributes, and using two existing attributes:

  • isDeleted
    • Has existed since Windows 2000
    • Exists on every object
    • Describes if an object is deleted but restorable
  • isRecycled
    • New to Windows Server 2008 R2
    • Exists on every object once it is recycled
    • Describes if an object is deleted but not restorable
  • msDS-deletedObjectLifetime
    • New to Windows Server 2008 R2
    • Is set on the “CN=Directory Service,CN=Windows NT, CN=Services, CN=Configuration, DC=COMPANY,DC=COM” container
    • Describes how long a deleted object will be restorable
  • tombstoneLifetime
    • Has existed since Windows 2000
    • Is set on the “CN=Directory Service,CN=Windows NT, CN=Services, CN=Configuration, DC=COMPANY,DC=COM” container
    • Describes how long a deleted object will not be restorable

Note: I am not mentioning another dozen new attributes that were created for ADRB, just covering the ones that really glue it all together. To see all new attributes in the 2008 R2 Schema for ADRB review Windows Server 2008 R2: Schema Updates.

Now pay close attention; this gets complicated:

1. You have a live object - a user account called SaraDavisthat lives in the Sales OU in the Contoso.comdomain.

2. An administrator deletes the SaraDavis object.

3. SaraDavis is moved into the container CN=Deleted Objects,DC=Contoso,DC=Com.

4. SaraDavis has its isDeleted attribute set to TRUE.

Note: At this point, SaraDavis is a logically deleted object that can be recovered by the administrator, and will contain all of its data. The amount of time that SaraDavis can be recovered is controlled by the Deleted Object Lifetime (DOL). This time range can be set on the msDS-deletedObjectLifetime attribute. By default, it will be the same number of days as the Tombstone Lifetime (TSL). The TSL set for a new forest since Windows Server 2003 SP1 has been 180 days*, and since by default DOL = TSL, the default number of days that an object can be restored is therefore 180 days. If tombstoneLifetime is NOT SET or NULL, the tombstone lifetime is that of the Windows default: 60 days. This is all configurable by the administrator. Stay with me here.

5. After the Deleted Object Lifetime has been exceeded - remember, 180 days by default - SaraDavis has its isRecycled attribute set to TRUE. Its isDeleted attribute stays set to TRUE. The SaraDavis object stays in the CN=Deleted Objects,DC=Contoso,DC=Com container.

Note: At this point, SaraDavis is a recycled object that cannot be recovered by an administrator, and no longer contains all of its attribute data. Its only purpose now is to let other DC’s know that the object is gone and that the object is now a normal, run of the mill tombstone.

6. After the SaraDavis recycled object has existed for the value of the Tombstone Lifetime, it is then physically deleted from the database via garbage collection. At the next online defrag, that whitespace will be recovered from the database.

* The tombstone lifetime in a  new forest is always 180 days.

 

That’s a pretty hard read, so here’s a diagram that hopefully fills in the gaps for you:

image

By the way: when I use the term “FALSE” for these attributes, I’m simplifying things. A more precise term would be “NOT TRUE”, as if the value is not set, it counts as FALSE. Also, the isRecycled attribute will not exist on an object until the object is actually recycled.

If you’re wondering why isRecycled actually means ‘not recoverable’, remember that plenty of applications know about isDeleted from the past 10 years. We couldn’t go change what isDeleted meant!

Requirements and Enabling

Forest Requirements

In order to turn AD Recycle Bin you will need to have implemented a Windows Server 2008 R2 Forest Functional Level. Wait, come back! Despite the terror it seems to inspire in our customers, increasing functional levels is not a big deal. In order to do it, you must:

  1. Have extended your schema to Windows Server 2008 R2.
  2. Have only Windows Server 2008 R2 DC’s in your forest.
  3. Raise your domain(s) functional level.
  4. Raise your forest’s functional level.

Note: Did you know that in Windows Server 2008 R2, you can actually lower the functional level back to 2008? As long as you have not turned the Recycle Bin feature on, the domain and forest functional levels that are at 2008 R2 can be reverted to 2008 with a simple PowerShell command. Here's an example of lowering it back to 2008 when it was already at 2008 R2:

 Set-AdForestMode -identity contoso.com -server dc1.contoso.com -forestmode Windows2008Forest
 Set-AdDomainMode -identity contoso.com -server dc2.child.contoso.com -forestmode Windows2008Domain

This means you can go to the R2 functional level, make sure your environment is not having any issues, then if you are satisfied you can enable the Recycle Bin. At that point you can no longer revert.

Ok, back on topic.

Enabling AD Recycle Bin

To turn on the Recycle Bin you will use AD PowerShell. Don’t you roll your eyes at me! I know there are some PowerShell haters out there but if you want to recycle, you are going to have to bend a little. Don’t worry, it won’t hurt.

1. Logon to your “Domain Naming Master” DC as an Enterprise Administrator and start PowerShell.exe - it’s that big blue icon on your taskbar.

 2. Load the AD PowerShell module: 

Import-module ActiveDirectory

image

3. Run the following cmdlet to turn on the Recycle Bin:

 Enable-ADOptionalFeature 'Recycle Bin Feature' -Scope ForestOrConfigurationSet -Target <your forest root domain name> 

So for example, where my forest root domain is contoso.com:

image

4. The command will prompt you for a last chance. Enter “Y” to turn the Recycle Bin on.

image

5. That’s it, you’re done.

Note: If you just can’t be bothered to logon to your domain naming master or type in forest names, you can use the following PowerShell command to do everything for you (and learn a useful technique for using object properties):

 Enable-ADOptionalFeature "Recycle Bin Feature" -server ((Get-ADForest -Current LocalComputer).DomainNamingMaster) -Scope ForestOrConfigurationSet -Target (Get-ADForest -Current LocalComputer)

I don’t mind if you copy and paste. ;-)

A final critical point: The AD Recycle bin is not retroactive. Turning it on after someone has deleted all your users will not help you!

Controlling the Lifetime of Deleted Objects

To control the length of a time that deleted objects will be recoverable, you will need to modify the msDS-deletedObjectLifetime attribute that lives on the Directory Service container. Microsoft really hopes you won’t mess with it but I know you will, so here’s how to do it correctly in PowerShell. Remember that you are setting this value in days:

 Set-ADObject -Identity "CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=<your forest root domain>" -Partition "CN=Configuration,DC=<your forest root domain>" -Replace:@{"msDS-DeletedObjectLifetime" = <value in days>}

For example, in my Contoso.com forest I will set my Deleted Object Lifetime to 365 days:

image

To see the current Deleted Object Lifetime, I use Get-AdObject:

image

Using the Recycle Bin

Restoring Single Objects

We’ve got everything setup, so let’s start with a simple restore scenario. Again, we will use PowerShell to do all the work.

The Sales OU contains a few users, including SaraDavis:

image

Last night one of the administrators was told that an employee named Sarah Davis had left the company and her account needed to be deleted. Unfortunately, the email from HR misspelled her name, and so the Administrator deleted Sara Davis. Let’s look at a few ways to examine the deleted user information with PowerShell:

 Get-ADObject -filter 'isdeleted -eq $true -and name -ne "Deleted Objects"' -includeDeletedObjects -property *

The command above will list out all deleted objects and all the attribute data on those objects. So I run it:

image image

Note how all the attribute data has been preserved, including group memberships - SaraDavis was a member of the Sales VPs group. Ouch, deleting an executive is never good for a career.

There is a ton of data being returned here, and while interesting I’m not sure I care all that much. When restoring users I just need the bare minimum information to make sure that this is the right object I need to get back; I don’t want this whole Sarah/Sara debacle again. So I’ll narrow the output with some pipelining:

 Get-ADObject -filter 'isdeleted -eq $true -and name -ne "Deleted Objects"' -includeDeletedObjects -property * | Format-List samAccountName,displayName,lastknownParent

image

By adding the pipeline like above, I am feeding the query results to the Format-List cmdlet, and return the user’s logon ID, display name, and last known parent location when it was deleted; much more concise. I can use a couple methods to restore the user, such as querying for the user and feeding it through a pipeline to Restore-ADObject:

 Get-ADObject -Filter 'samaccountname -eq "SaraDavis"' -IncludeDeletedObjects | Restore-ADObject

I can also simply call Restore-ADObject directly as long as I have dumped out the user’s distinguished name or GUID:

image

Either way, the user is restored.

Restoring multiple objects

In this next scenario it turns out that someone dropped an apple on their keyboard and deleted all the users in the Sales OU (yes, I have heard that reason in real life). Until I get those users back they can’t do their work, and my company can’t sell its products. Knowing what I know now from the first scenario, this starts getting easier and more familiar.

Since there have been a bunch of users deleted, returning the data in a list format isn’t ideal. This time I’ll use a table format:

 Get-ADObject -filter 'isdeleted -eq $true -and name -ne "Deleted Objects"' -includeDeletedObjects -property * | Format-Table msds-lastKnownRdn,lastknownParent -auto -wrap

To restore the actual users, I will simply base my query on the last known parent OU. Since all the users in Sales were deleted, my query simply finds all objects in that OU and pipelines them to Restore-ADobject:

 Get-ADObject -filter 'lastKnownParent -eq "OU=Sales,DC=Contoso,DC=com"' -includeDeletedObjects | restore-adobject

image

Restoring all objects based on time and date

In a large complex environment I may not simply want to restore all users deleted from an OU. For example, if I had all my users stored in the default Users container, simply restoring every object could bring back users that were supposed to be deleted. In that case I can use a date and time rule to simply restore all the objects that were deleted by a provisioning script went berserk at 1:40AM. To get these users back, I will first populate a variable that describes the time criteria:

 $changedate = New-Object Datetime(2009, 8, 22, 1, 40, 00)
 This variable stores the output of the Datetime conversion for 1:40:00 AM, August 22, 2009. Now I can search for any objects deleted after that time using a variation on my usual syntax. Part of my filter will now include ‘whenChanged is greater than <date time>’:
 Get-ADObject -filter 'whenChanged -gt $changedate -and isDeleted -eq $true' -includeDeletedObjects -property * | ft samaccountname,lastknownparent -auto -wrap

image

Having examined what I could be restoring, I then restore those objects:

image

This is one of the powers of AD Recycle Bin over the older authoritative restore system. You never had this much control before, and were stuck restoring extraneous objects even if they were intentionally deleted. Not to mention they were usually from yesterday, not 30 minutes ago.

Restoring all objects in a deleted OU

A key point to understand and remember with AD Recycle Bin is that you must restore hierarchically; a parent object must be restored before a child object. So if I was to delete an entire OU and all its contents, I must first restore the OU before I can restore its contents.

 This time someone managed to delete the entire Sales OU and its five users. In order to demonstrate how objects are stored in the Deleted Objects container I will be doing a few extra steps here. First, I’ll dump out all deleted objects with their last known parents and its last known relative distinguished name.
 Get-ADObject -filter 'isDeleted -eq $true' -and name -ne "Deleted Objects"' -includeDeletedObjects -property * | ft msds-lastKnownRdn,lastKnownParent -auto -wrap

image

 Neat, I can see all the deleted users including the Sales OU. Note how lastKnownParent attribute for the deleted users is actually the deleted Sales OU distinguished name. If I tried to restore those child objects right now nothing would happen, as their parent is deleted. So I’d better restore the Sales OU first; to do that I will specify the OU’s last known RDN and its last known parent:
 Get-ADObject -filter 'msds-lastKnownRdn -eq "Sales" -and lastKnownParent -eq "DC=contoso,DC=com"' -includeDeletedObjects | Restore-ADObject

image

Just for grins, before I restore the user objects I’ll take a look at the same query I ran originally. Notice how the last known parent has magically changed! Now if I run the restore, pointing the last known parent to the Sales OU, all the child objects are restored.

image

Restoring multiple objects and nested OU’s

Ok, last one. Consider this complex restore scenario:

image

We have multiple child OU’s, each with child user objects. And now someone has gone and deleted the parent Sales OU. Restoring all those parent-child relationships is going to be a bit of a drag, right?

Not if you keep this script handy: https://technet.microsoft.com/en-us/library/dd379504(WS.10).aspx

By running this script and specifying a last known RDN and perhaps last known parent, it will walk all child objects and do the work for you. It even has pretty colors. Slick and simple.

image

Best Practices

After the last year’s testing experience, here are some of the best practices MS Support have come up with. This list may grow, but I doubt it will shrink. ;-)

  • Keep taking real System State backups – The AD recycle Bin makes object restores quick and easy. But it is not going to help you if your only four DC’s are ruined by the same leaky plumbing in your data center. And you won’t be restoring the deleted contents of SYSVOL with the recycle bin. And you won’t be using the Recycle Bin to undo the damage from script that replaces every user’s mailbox attribute with the wrong server name.
  • Lowering deleted object lifetime not recommended – There may be a temptation to drop the msds-DeletedObjectLifetimedown to a few days in order to save space in your AD database. The longer you keep deleted objects around the better; you wouldn’t believe how old some of the restores I’ve walked a customer through. And when it gets down to it – hard drive disk space is ridiculously cheap. A massive AD database would be 40GB; you cannot buy a platter-based hard drive at a Best Buy that’s smaller than 160GB. In fact, when I looked at the lowest end small business servers offered by HP and Dell, their smallest drives were 160GB too. And this is a sub-$300USD Dell!
  • Practice and train – Don’t just turn on the Recycle Bin. Run through disaster recovery exercises periodically to make sure you and your staff know what they are doing. You don’t want to be figuring out how to recover your CEO’s user account; it should simply be a routine restore operation. Hyper-V makes test labs cheap and easy.
  • Turn on DS change auditing for deletions– The Recycle Bin will not tell you who deleted your users, groups, and computers. Principal deletions are rare operations in AD and should definitely be audited. I can tell you from many, many CritSits here that after the objects are back, the next thing your management will want to know is “what happened?” Make sure you have an answer, or your own account may be deleted. :-)

And since you are using Windows Server 2008 R2 at this point, you can even make use of the new group policies for granular auditing:

image

  • Use PowerShell, not LDP.exe – There are a number of limitations within LDP.EXE, such as its clunky interface and need for cryptic optional settings. The biggest one I see though is that when displaying deleted objects, it cannot display all the attribute data, such as the critical memberOf that shows you group memberships.

Yes, I know – woooo, scary, there’s no GUI! It’s just a little command-line work; I have faith in you.

Troubleshooting common issues

Here are a few errors people tend to run into the first time they start using the Recycle Bin. Don’t worry, they happen to everyone and have straightforward solutions:

Error: An attempt was made to add an object to the directory with a name that is already in use

Cause: Someone has created an object with the same distinguished name. This may be because someone jumped the gun and tried to ‘fix’ the deleted user by recreating it. Just move it elsewhere temporarily, make sure it has no other attribute duplications as well, finish the restore of the real object, then go figure out what happened.

Error: The operation could not be performed because the object's parent is either uninstantiated or deleted

Cause: The object’s parent was also deleted and hasn’t been restored. Usually it’s an OU. Restore that parent first.

Error: Illegal modify operation. Some aspect of the modification is not permitted

Cause: Often this is caused by trying to restore an object without having the Recycle Bin enabled. You may see this error in other scenarios though.

References and Final Notes

Make sure you bookmark these sites – they cover tons of info about the Recycle Bin and PowerShell:

Oh yeah – Recycle Bin works with AD Lightweight Directory Services too. That’s for another blog post.

That’s all for now. Good luck saving your environment, IT super hero.

- Ned ’10 cent deposit’ Pyle