By default Azure AD Connect (AADC) does not honour account expiry in AD. So if you set an expiry date for an AD user thinking that will stop them accessing your synced Office 365 tenancy past a certain date, you’d be wrong! Why Microsoft haven’t implemented this I really don’t know, but it’s easy to resolve, and important if you ask me. Here’s how I do it…
First some background on the accountExpires attribute. This attribute is not a datetime attribute, it’s another of the annoying AD attributes that have to be converted. Thankfully the later versions of AADC now have lots of handy functions to allow the creation of some complex sync rules, so this is actually possible now. Make sure you’re on the latest version of AADC if you can. As of writing this it’s up to v188.8.131.52, available from the following download url: https://www.microsoft.com/en-us/download/details.aspx?id=47594
When an account has NOT expired the attribute can actually take one of three different values:
Null (no value)
When the account is going to expire the attribute value will be a value in the future, and when it has expired it’ll be now or in the past, of course.
So we already have some rather odd behaviour. There’s no single “never expires” value, and two of the values that do indicate no expiry are also possible candidates for expiry! We need to be mindful of these and filter for them when we configure our new sync rule.
- We’ll be creating a new user->person join rule on the AD connector that acts only on accounts that have an accountExpires value of relevance, and also only on accounts that have not already been disabled – we don’t need to worry about those because the enabled/disabled state is something AADC already honours.
- Our new rule needs to validate if the accountExpires value is in the past or not, and if it is set AccountEnabled to False. If the account has not expired yet then it needs to tell the sync engine to ignore the rule output so other rules can act on the property if the need to. We do that by providing a Null output in this instance.
Let’s get on with the rule…
1. Open the Sync Rules Editor and add a new Inbound rule. Give it an appropriate title, and set the precedence to something smaller than 100 so that it is a higher priority than the built-in rules.
2. Click next and create 4 clauses as below.
accountExpires : ISNOTNULL (ignore accounts without an expiry value)
userAccountControl : ISBITNOTSET : 2 (ignore disabled accounts)
accountExpires : GREATERTHAN : 0 (ignore non-expiring accounts)
accountExpires : LESSTHAN : 9223372036854775807 (ignore non-expiring accounts)
3. Click next twice and add a transformation as below.
Expression : accountEnabled : IIF(([accountExpires])<NumFromDate(Now()),False,NULL)
Then we click Save.
Now this is NOT going to work straight away, and that is because AADC does not store the accountExpires attribute from AD out of the box. So we need to tell it to start reading the attribute.
4. Open your Synchronization Service Manager, making sure that no syncs are underway. If they are just wait for them to finish.
5. We should stop our AD sync scheduler so that we have some control over what’s happening. Launch PowerShell and run this command stop disable the scheduler:
6. Back in the sync service manager double-click your AD connector. Switch to the Attributes section of the connector’s properties window, click on “Show All” at the top-right and check the box next to “accountExpires”
7. Click OK to close the properties.
8. Now we need to run a full import to get this new data into AADC. Select the AD connector and click on Run from the actions on the right.
9. Now select “Full Import” and click OK.
AADC will now import all the accountExpires values for the AD accounts. Once this completes we need to do a Full Synchronization as well or the new rule we’ve created won’t be applied to existing accounts.
10. Repeat step 8. and choose “Full Synchronization” from the list.
In a large environment this step usually takes quite a while. It can appear that a lot of changes are being made, but that will be because a full synchronization re-applies all the rules to the whole connector space. It’s likely that very few will actually change, if any – unless you have lots of expired accounts.
Last but not least we need to export the changes and give control back to the scheduler.
11. Repeat step 8. again but this time choose the Azure AD connector instead, and when you click Run choose the “Export” option.
12. Wait for step 11 to complete, then go back to PowerShell and fire this command to re-enable the scheduler: