First published at https://nivleshc.wordpress.com

Introduction

A few weeks back, I was tasked with configuring Global Address List (GAL) Segmentation for one of my clients. GAL Segmentation is not a new concept, and if you were to Google it (as you would do in this day and age), you will find numerous posts on it.
However, during my research, I didn’t find any ONE article that helped me. Instead I had to rely on multiple articles/blogposts to guide me into reaching the result.
For those that are new to GAL Segmentation, this can be a daunting task. This actually is the inspiration for this blog, to provide the steps from an implementers view, so that you get the full picture about the preparation, the steps involved and the gotchas so that you feel confident about carrying out this simple yet scary change.
This blog will be focus on GAL Segmentation for an Exchange Online hybrid setup.

So what is GAL Segmentation?

I am glad you asked 😉
By default, in Exchange Online (and On-Premises Exchange environment as well), a global address list is present. This GAL contains all mail enabled objects contained in the Exchange Organisation. There would be mailboxes, contacts, rooms, etc.
This is all well and good, however, at times a company might not want everyone to see all the objects in the Exchange environment. This might be for various reasons, for instance, the company has too many employees and it won’t make sense to have a GAL a mile long. Or, the company might have different divisions, which do not require to correspond to each other. Or the company might be trying to sell off one of its divisions, and to start the process, is trying to separate the division from the rest of the company.
For this blog, we will use the last reason, as stated above. A “filter” will be applied to all users who are in division to be sold off, so that when they open their GAL, they only see objects from their own division and not everyone in the company. In similar fashion, the rest of the company will see all objects except the division that will be sold off. Users will still be able to send/receive emails with that particular division, however the GAL will not show them.
I would like to make it extremely clear that GAL Segmentation DOES NOT DELETE any mail enable objects. It just creates a filtered version of the GAL for the user.

Introducing the stars

Lets assume there was once a company called TailSpin Toys. They owned the email namespace tailspintoys.com and had their own Exchange Online tenant.
One day, the board of TailSpin Toys decided to acquire a similar company called WingTip ToysWingTip Toys had their own Exchange Online Tenant and used the email namespace wingtiptoys.com. After the acquisition, WingTip Toys email resources were merged into the TailSpin Toys Exchange Online tenant, however WingTip Toys still used their wingtiptoys.com email namespace.
After a few years, the board of TailSpin Toys decided it was time to sell of WingTip Toys. As a first step, they decided to implement GAL Segmentation between TailSpin Toys and WingTip Toys users.
Listed below is what was decided

  • TailSpin Toys users should only see email objects in their GAL corresponding to their own email namespace (any object with the primary smtp address of @tailspintoys.com). They should not be able to see any WingTip Toys email objects.
  • Only TailSpin Toys users will be able to see Public Folders in their GAL
  • WingTip Toys users should only see email objects in their GAL corresponding to their own email namespace (any object with the primary smtp address of @wingtiptoys.com). They should not be able to see any TailSpin Toys email objects.
  • The All Contacts in the GAL will be accessible to both WingTip Toys and TailSpin Toys users.

The Steps

Performing a GAL Segmentation is a very low risk change. The steps that will be carried out are as follows

  • Create new Global Address Lists, Address Lists, Offline Address Book and Address Book Policy for TailSpin Toys and WingTip Toys users.
  • Assign the respective policy to TailSpin Toys users and WingTip Toys users

The only issue is that by default, no users are assigned an Address Book Policy (ABP) in Exchange Online (ABPs are the “filter” that specifies what a user sees in the GAL).
Due to this, when we are creating the new address lists, users might see them in their GAL as well and get confused as to which one to use. If you wish to carry out this change within business hours, the simple remedy to the above issue is to provide clear communications to the users about what they could expect during the change window and what they should do (in this case use the GAL that they always use). Having said that, it is always a good practice to carry carry out changes out of business hours.
Ok, lets begin.

  • By default, the Address Lists Management role is not assigned in Exchange Online. The easiest way to assign this is to login to the Exchange Online Portal using a Global Administrator account and add this role to the Organization Management role group. This will then provide all the Address List commands to the Global Administratos.
  • Next, connect to Exchange Online using PowerShell
  • For TailSpin Toys
    • Create a default Global Address List called Default TST Global Address List
    • New-GlobalAddressList -Name "Default TST Global Address List" -RecipientFilter {((Alias -ne $null) -and (((ObjectClass -eq 'user') -or (ObjectClass -eq 'contact') -or (ObjectClass -eq 'msExchSystemMailbox') -or (ObjectClass -eq 'msExchDynamicDistributionList') -or (ObjectClass -eq 'group') -or (ObjectClass -eq 'publicFolder'))) -and (WindowsEmailAddress -like "*@tailspintoys.com") )}
    • Create the following Address Lists
      • All TST Distribution Lists
      • New-AddressList -Name "All TST Distribution Lists" -RecipientFilter {((Alias -ne $null) -and (ObjectCategory -like 'group') -and (WindowsEmailAddress -like "*@tailspintoys.com"))}
      • All TST Rooms
      • New-AddressList -Name "All TST Rooms" -RecipientFilter {((Alias -ne $null) -and (((RecipientDisplayType -eq 'ConferenceRoomMailbox') -or (RecipientDisplayType -eq 'SyncedConferenceRoomMailbox'))) -and (WindowsEmailAddress -like "*@tailspintoys.com"))}
      • All TST Users
      • New-AddressList -Name "All TST Users" -RecipientFilter {((Alias -ne $null) -and (((((((ObjectCategory -like 'person') -and (ObjectClass -eq 'user') -and (-not(Database -ne $null)) -and (-not(ServerLegacyDN -ne $null)))) -or (((ObjectCategory -like 'person') -and (ObjectClass -eq 'user') -and (((Database -ne $null) -or (ServerLegacyDN -ne $null))))))) -and (-not(RecipientTypeDetailsValue -eq 'GroupMailbox')))) -and (WindowsEmailAddress -like "*@tailspintoys.com"))}
    • Create an Offline Address Book called TST Offline Address Book (this uses the Default Global Address List that we had just created)
    • New-OfflineAddressBook -Name "TST Offline Address Book" -AddressLists "Default TST Global Address List"
    • Create an Address Book Policy called TST ABP
    • New-AddressBookPolicy -Name "TST ABP" -AddressLists "All Contacts", "All TST Distribution Lists", "All TST Users", “Public Folders” -RoomList "All TST Rooms" -OfflineAddressBook "TST Offline Address Book" -GlobalAddressList "Default TST Global Address List"
  • For WingTip Toys
    • Create a default Global Address List called Default WTT Global Address List
    • New-GlobalAddressList -Name "Default WTT Global Address List" -RecipientFilter {((Alias -ne $null) -and (((ObjectClass -eq 'user') -or (ObjectClass -eq 'contact') -or (ObjectClass -eq 'msExchSystemMailbox') -or (ObjectClass -eq 'msExchDynamicDistributionList') -or (ObjectClass -eq 'group') -or (ObjectClass -eq 'publicFolder'))) -and (WindowsEmailAddress -like "*@wingtiptoys.com") )}
    • Create the following Address Lists
      • All WTT Distribution Lists
      • New-AddressList -Name "All WTT Distribution Lists" -RecipientFilter {((Alias -ne $null) -and (ObjectCategory -like 'group') -and (WindowsEmailAddress -like "*@wingtiptoys.com"))}
      • All WTT Rooms
      • New-AddressList -Name "All WTT Rooms" -RecipientFilter {((Alias -ne $null) -and (((RecipientDisplayType -eq 'ConferenceRoomMailbox') -or (RecipientDisplayType -eq 'SyncedConferenceRoomMailbox'))) -and (WindowsEmailAddress -like "*@wingtiptoys.com"))}
      • All WTT Users
      • New-AddressList -Name "All WTT Users" -RecipientFilter {((Alias -ne $null) -and (((((((ObjectCategory -like 'person') -and (ObjectClass -eq 'user') -and (-not(Database -ne $null)) -and (-not(ServerLegacyDN -ne $null)))) -or (((ObjectCategory -like 'person') -and (ObjectClass -eq 'user') -and (((Database -ne $null) -or (ServerLegacyDN -ne $null))))))) -and (-not(RecipientTypeDetailsValue -eq 'GroupMailbox')))) -and (WindowsEmailAddress -like "*@wingtiptoys.com"))}
    • Create an Offline Address Book called WTT Offline Address Book (this uses the Default Global Address List that we had just created)
    • New-OfflineAddressBook -Name "WTT Offline Address Book" -AddressLists "Default WTT Global Address List"
    • Create an Address Book Policy called WTT ABP
    • New-AddressBookPolicy -Name "WTT ABP" -AddressLists "All Contacts", "All WTT Distribution Lists", "All WTT Users" -RoomList "All WTT Rooms" -OfflineAddressBook "WTT Offline Address Book" -GlobalAddressList "Default WTT Global Address List"
  • Once you create all the Address Lists, after a few minutes, you will be able to see them using Outlook Client or Outlook Web Access. One of the obvious things you will notice is that they are all empty! If you are wondering if the recipient filter is correct or not, you can use the following to confirm the membership
  • Get-Recipient -RecipientPreviewFilter (Get -AddressList -Identity {your address list name here}).RecipientFilter

    Aha, you might say at this stage. I will just run the Update-AddressList cmdlet. Unfortunately, this won’t work since this cmdlet is only available for On-Premises Exchange Servers. There is none for Exchange Online. Hmm. How do I update my Address Lists ? Its not too difficult. All you have to do is change some attribute of the members and they will start popping into the Address List! For a hybrid setup, this means we will have to change the setting using On-Premise Exchange Server and use Azure Active Directory Connect Server to replicate the changes to Azure Active Directory, which in turn will update Exchange Online objects, thereby updating the newly created Address Lists. Simple? Yes. Lengthly? Yes indeed

  • I normally use CustomAttribute for such occasions. Before using any CustomAttribute, ensure it is not used by anything else. You might    be able to ascertain this by checking if for all objects, that CustomAttribute currently holds any value or not. Lets assume CustomAttribute10 can be used.
    #Get all On-Premise Mailboxes
    $OnPrem_MBXs = Get-Mailbox -Resultsize unlimited
    #Get all Exchange Online Mailboxes
    $EXO_MBXs = Get-RemoteMailbox -Resultsize Unlimited
    #Get all the Distribution Groups
    $All_DL = Get-DistributionGroup -Resultsize unlimited
    #Update the CustomAttribute10 Value
    #Since Room mailboxes are a special type of Maibox, the following update will
    #address Room Mailboxes as well
    $OnPrem_MBXs | Set-Mailbox -CustomAttribute10 “GAL”
    $EXO_MBXs | Set-RemoteMailbox -CustomAttribute10 “GAL”
    $All_DL | Set-DistributionGroup -CustomAttribute10 “GAL”
  • Using your Azure Active Directory Connect server run a synchronization cycle so that the updates are synchronized to Azure Active Directory and subsequently to Exchange Online
  • One Gotcha here is if you have any Distribution Groups that are not synchronised from OnPremises. You will have to find these and update their settings as well. One simple way to find them is to use the property isDirSynced. Connect to Exchange Online using PowerShell and then use the following command
  • $All_NonDirsyncedDL = Get-DistributionGroup -Resultsize unlimited| ?{$_.isdirsynced -eq $FALSE}   
    #Now, we will update CustomAttribute10 (please check to ensure this customAttribute doesn't have any values)
    $All_NonDirSyncedDL | Set-DistributionGroup -CustomAttribute10 "GAL"
  • Check using Outlook Client or Outlook Address Book to see that the new Address Lists are now populated
  • Once confirmed that the new Address Lists have been populated, lets go assign the new Address Book Policies to TailSpin Toys and WingTip Toys users It can take anywhere from 30min – 1hr for the Address Book Policy to take effect
  • $allUserMbx = Get-Mailbox -RecipientTypeDetails UserMailbox -Resultsize unlimited
    #assign "TST ABP" Address Book Policy to TailSpin Toys users
    $allUserMbx | ?{($_.primarysmtpaddress -like "*@tailspintoys.com")} | Set-Mailbox -AddressBooksPolicy “TST ABP”
    #assign "WTT ABP" Address Book Policy to WingTip Toys users
    $allUserMbx | ?{($_.primarysmtpaddress -like "*@wingtiptoys.com")} | Set-Mailbox -AddressBooksPolicy “WTT ABP”
  • While waiting, remove the CustomAttribute10 values you had populated. Using PowerShell on On-Premises Exchange Server, run the following
  • #Get all On-Premise Mailboxes
    $OnPrem_MBXs = Get-Mailbox -Resultsize unlimited
    #Get all Exchange Online Mailboxes
    $EXO_MBXs = Get-RemoteMailbox -Resultsize Unlimited
    #Get all the Distribution Groups
    $All_DL = Get-DistributionGroup -Resultsize unlimited
    #Set the CustomAttribute10 Value to null
    #Since Room mailboxes are a special type of Maibox, the following update will
    #address Room Mailboxes as well
    $OnPrem_MBXs | Set-Mailbox -CustomAttribute10 $null
    $EXO_MBXs | Set-RemoteMailbox -CustomAttribute10 $null
    $All_DL | Set-DistributionGroup -CustomAttribute10 $null
  • Connect to Exchange Online using PowerShell and remove the value that was set for CustomAttribute10 for nonDirSynced Distribution Groups
  • $All_NonDirsyncedDL = Get-DistributionGroup -Resultsize unlimited| ?{$_.isdirsynced -eq $FALSE}   
    #Change CustomAttribute10 to $null
    $All_NonDirSyncedDL | Set-DistributionGroup -CustomAttribute10 $null

     
    Thats it folks! Your GAL Segmentation is now complete! Users from TailSpin Toys will only see TailSpin Toys mail enabled objects and WingTip Toys users will only see WingTip Toys mail enabled objects

A few words of wisdom

In the above steps, I would advise that once the new Address Lists have been populated

  • apply the Address Book Policy to a few test mailboxes
  • wait between 30min – 1 hour, then confirm that the Address Book Policy has been successfully applied to the test mailboxes and has the desired result
  • once you have confirmed that the test mailboxes had the desired result for ABP, then and ONLY then continue to the rest of the mailboxes

This will give you confidence that the change will be successful. Also, if you find that there are issues, the rollback is not too difficult and time consuming.
Another thing to note is that when users have their Outlook client configured to use  cached mode, they might notice that their new GAL is not fully populated. This is because their Outlook client uses the Offline Address Book to show the GAL and at that time, the Offline Address Book would not have regenerated to include all the new members. Unfortunately in Exchange Online, the Offline Address Book cannot be regenerated on-demand and we have to wait for the the Exchange Online servers to do this for us. I have noticed the regeneration happens twice in 24 hours, around 4am and 4pm AEST (your times might vary). So if users are complaining that their Outlook Client GAL doesn’t show all the users, confirm using Outlook Web Access that the members are there (or you can run Outlook in non-cached mode) and then advise the users that the issue will be resolved when the Offline Address Book gets re-generated (in approximately 12 hours). Also, once the Offline Address Book has regenerated, it is best for users to manually download the latest Offline Address Book, otherwise Outlook client will download it at a random time in the next 24 hours.
The next gotcha is around which Address Lists are available in Offline mode (refer to the screenshot below)
GAL01
When in Offline mode, the only list available is Offline Global Address List . This is the one that is pointed to by the  green arrow. Note that the red arrow is pointing to Offline Global Address List as well however this is an “Address List” that has been named Offline Global Address List by Microsoft to confuse people! To repeat, the Offline Global Address List pointed to by the green arrow is available in Offline mode however the one pointed to by red is not!
In our case, the Offline Global Address List is named Default TST Global Address List and Default WTT Global Address List).
If you try to access any others in the drop down list when in Offline mode, you will get the following error
AddressListError
This has always been the case, unfortunately hardly anyone tries to access all the Address Lists in Offline mode. However, after GAL Segmentation, if users receive the above error, it is very easy to blame the GAL Segmentation implementation 🙁 Rest assured, this is not the case and this “feature” has always been present.
Lastly, the user on-boarding steps will have to be modified to ensure that when their mailbox is created, the appropriate Address Book Policy is applied. This will ensure they only see the address lists that they are supposed to (on the flip side, if no address book policy is applied, they will see all address lists, which will cause a lot of confusion!)
With these words, I will now stop. I hope this blog comes in handy to anyone trying to implement GAL Segmentation.
If you have any more gotchas or things you can think of regarding GAL Segmentation, please leave them in the comments below.
Till the next time, Enjoy 😉
 
 
 
 
 
 

Category:
Exchange, Office 365, PowerShell
Tags:
, , , , ,

Join the conversation! 1 Comment

  1. What did you use the customattribute10 for?

Comments are closed.