Hide user from the GAL in Microsoft 365 synchronized from Active Directory

TL;DR

This post will go over how to sync a custom attribute from on-premises Active Directory to Azure Active Directory to hide a user from the GAL, without the need of extending your Active Directory schema.

Problem we had

Few days ago, I had a chance to troubleshoot an interesting problem that my customer had. To understand what happened, hereā€™s a background of their infrastructure. They had an Active Directory Domain Services and an Exchange Server 2016. Pretty standard infrastructure for small business to say the least. Then they decided to move to Microsoft 365 2 years ago and decommission Exchange Server.

After a while, their AD DS got a bit messy and so they decided to build new AD DS and this time implement it properly like it should be - use Tiering Model. Still with me? Mkay. After the implementation of new AD DS, it was my time to shine. I had to install new Azure Active Directory Connect and pair all new on-premises identities with old identities in Microsoft 365.

Now to get to the problem they had. When you use Exchange Server, your Active Directory gets extended by tons of msExch* attributes including msExchHideFromAddressLists. This attribute is there to hide user from Global Address List. They used this attribute to hide some mailboxes. HOWEVER, when you decommission Exchange server and reimplement Domain Services, that attribute is gone. POOF! You donā€™t see it in new AD DS anymore. But in Exchange Online, this attribute is still set to true. And more importantly, you canā€™t change the attribute back to false in Exchnage admin center either, it throws an Operation failed error.

Nor you can change it in Exchange Online Powershell using this command:

Set-Mailbox -Identity XYZ@domain.com -HiddenFromAddressListsEnabled $false

The error message you get when trying said command is:

The operation on mailbox "XYZ" failed because it's out of the current user's write scope. The action 'Set-Mailbox', 'HiddenFromAddressListsEnabled', can't be performed on the object 'XYZ' because the object is being synchronized from your on-premises organization. This action should be performed on the object in your on-premises organization.

So thatā€™s it. You have no way to change the Exchange Online parameter

HiddenFromAddressListsEnabled
. Your hidden user will stay hidden forever. Or will it?

Solution

The first thing that comes to mind is to extend your Active Directory Domain Services with all msExch* attributes again, change said attribute and sync it to Microsoft 365. VoilĆ ! You have your user back in GAL in Microsoft 365. But extending your AD DS schema is an irreversible change. Those attributes - and thereā€™s loads of them - are here to stay forever, or at least until you reimplement AD DS again.

More ideal solution that I went with is to use one of msDS-CloudExtensionAttribute1 attributes that already is in your AD DS. You can create custom rule in AAD Connect Sync Rule Editor. This post will go over how to sync a custom attribute from on-premises Active Directory to Azure Active Directory to hide a user from the GAL, without the need of extending your Active Directory schema.

Synchronize extension attribute to cloud

First, you have to ensure, that the attribure msDS-CloudExtensionAttribute1 is in scope of synchronization.

NOTE: If msDS-CloudExtensionAttribute1 is in scope already, skip this step.

  1. Go to start and look for Azure AD Connect Synchronization Service. Open it.
  2. Go to Connectors tab and select Active Directory domain (not *.onmicrosoft.com) > Properties
  3. In Select Attributes window, find msDS-CloudExtensionAttribute1 attribute and check the box next to it (if you are using Extension attributes for other purposes, choose whichever suits you)
Add attribute to scope
Add attribute to scope

Create a custom sync rule

To get the value of msDS-CloudExtensionAttribute1 attribute to Exchange Online msExchHideFromAddressLists attribute, you need to create a custom synchronization rule and map one to the other.

  1. Open Azure AD Connect Synchronization Rules Editor
  2. Click on the Add new rule button (make sure direction shows Inbound)
  3. Set new rule
    • Name: Hide user Global Adress List without extending AD DS schema
    • Description: If msDS-CloudExtensionAttribute1 attribute is set to HIDE, hide user from Exchange Online Global Address List.
    • Connected System: Your Active Directory domain name (e.g.: ad.domain.com)
    • Connected System Object Type: user
    • Metaverse Object Type: person
    • Link Type: Join
    • Precedence: 50 (can be any number less than 100; if you created custom rules already, just endure that there are no duplicate numbers)
Add new rule
Add new rule
  1. Leave Scoping filter and Join rules blank
  2. On Transformation page, click Add transformation and fill the form
    • FlowType: Expression
    • Target Attribute: msExchHideFromAddressLists
    • Source:
      IIF(IsPresent([msDS-cloudExtensionAttribute1]),IIF([msDS-cloudExtensionAttribute1]="HIDE",True,False),NULL)
Transformation rule
Transformation rule

The rule here is fairly simple. There are two nested conditions. First if is asking if the msDS-cloudExtensionAttribute1 even exists in your AD DS schema. If it does NOT, it does nothing. However if it does, it goes into the second condition, which asks if the attribute is set to ā€˜HIDEā€™. If it is, then the msExchHideFromAddressLists in Azure AD is set to True, otherwise it is set to False.

Test and run Initial sync

Now that you created custom rule, you should test it. Go to a server with Active Directory Users and Computers installed and set users msDS-CloudExtensionAttribute1 to ā€˜HIDEā€™.

Set the attribute to HIDE
Set the attribute to HIDE

NOTE: If you donā€™t see Attribute Editor in userā€™s properties, you need to turn on Advanced Features of Active Directory Users and Computers in View > Advanced Features.

Afterwards at server with Azure Active Directory Connect, run powershell command

Start-ADSyncSyncCycle -PolicyType Initial
to start an initial synchronization. Running
Start-ADSyncSyncCycle -PolicyType Delta
is only sufficient when you skipped first step.

Verify that it worked

To verify that all those shenanigans worked, you have 3 options. Go to either Exchange Online PowerShell and run

Get-Mailbox -Identity <username> | fl HiddenFromAddressListsEnabled

Validate result using PowerShell
Validate result using PowerShell

Or go to Exchange Admin Center and on said mailbox, click on Hide mailbox check that Hide from Address List is set to On.

Check in Admin Center
Check in Admin Center

Last thing where you can verify that it indeed did work is in Azure Active Directory Connect itself. Go to Synchronization Service. In there, find (presumably) last Export to *.onmicrosoft.com - AAD connector. There should be 1 action. When you click on that the Updates link, window with exported objects will open. Go to the exported object and look for HiddenFromAddressListsEnabled attribute. Itā€™s value will be True!

AAD Connect Export to onmicrosoft.com domain
AAD Connect Export to onmicrosoft.com domain
AAD Connect exported objects
AAD Connect exported objects

And youā€™re DONE!

If you found this blog post helpful in one way or the other, consider subscribing to my mailing list. You will get notified once new post is added or when something special is going to happen. If you have further questions, do not hesitate to contact me on twitter or linkedIn. šŸ˜‰

Until next time, have a nice day.




Subscribe

Do you want to get notified when a new post is released? Register bellow.


NOTE: Gatsby plugin used for this Subscription form does not show, that your mail is already subscribed, like it used to. I'm working on a fix. Until then, keep that in mind.