{"id":1923,"date":"2018-05-03T01:00:00","date_gmt":"2018-05-03T01:00:00","guid":{"rendered":"http:\/\/inswwdev.azurewebsites.net\/au\/insights\/uncategorized\/the-beast-that-is-multi-tenancy\/"},"modified":"2023-02-13T00:44:11","modified_gmt":"2023-02-13T00:44:11","slug":"the-beast-that-is-multi-tenancy","status":"publish","type":"post","link":"https:\/\/www.insentragroup.com\/gb\/insights\/geek-speak\/migrations\/the-beast-that-is-multi-tenancy\/","title":{"rendered":"The Beast That is Multi-Tenancy"},"content":{"rendered":"<p style=\"text-align: justify;\">Hi guys, yep it\u2019s me again\u2026the pure awesomeness that got you through the cross forest migrations. Just when you thought your cerebrum, you know, the large part of your brain that does all the thinking, had just been taken through its paces with trying to memorise cross forest migrations, along comes me again! This time around, I\u2019ll take you through the implementation of a multi-tenant Exchange organisation because you know, somewhere along the evolution of email and Exchange platforms, someone thought it would be a splendid idea to be able to host more than one organisation on the same platform! (cue the million dollar question of \u201cwhy?\u201d whilst inserting the crying emoji\u201d)<\/p>\n<p style=\"text-align: justify;\">Easy. Consultants like you and I make the world go around. Our knowledge and expertise of email and Exchange platforms is what helps your finance department send out those all important pay slips so you can finally decide on whether you can splurge on that Tesla you\u2019ve always wanted\u2026unless Elon Musk decides to launch more into space, depleting the Aussie stock of the Model S leaving you with no choice but to purchase a Japanese model electric car whose name we shall not mention. More on electric cars later. Continuing with the topic of the day\u2026multi tenancy and how in the world this ties in with an on-premises Exchange deployment.<\/p>\n<p style=\"text-align: justify;\">Read on my loyal apprentice.<\/p>\n<p style=\"text-align: justify;\">I\u2019ve been labelled a mad man for even attempting to deploy a multi-tenant solution but hey, the knowledge built up in my cerebrum needs to be transferred to my fellow Exchange consultants before we get taken over by AI (we\u2019ve all seen I, Robot!)<\/p>\n<p style=\"text-align: justify;\">So, you purely awesome mad man, tell us how to deploy a multi tenant Exchange platform!<\/p>\n<p style=\"text-align: justify;\">Here we go!<\/p>\n<p style=\"text-align: justify;\">One thing to remember is that deploying an Exchange 2013\/2016 multi tenant solution isn\u2019t as difficult as you might think. It\u2019s nothing compared to the days of Exchange 2010. With 2013\/2016, you can actually get things done via the GUI, BUT (and yes, it\u2019s a big BUT), most of the configuration still needs to be done using PowerShell. Oh did you think we were done with PowerShell commands? You\u2019re an Exchange consultant. PowerShell is life!<\/p>\n<p style=\"text-align: justify;\">If you recall back to my first blog,<span>&nbsp;<\/span><a rel=\"noopener nofollow\" href=\"https:\/\/inswwdev.azurewebsites.net\/au\/the-mother-of-all-cross-forest-migrations\/\" target=\"_blank\">The Mother of All Cross Forest Migrations<\/a>, I provided you with two sets of PowerShell commands containing approx. 4000 cmdlets each. Well, with multi tenant, you\u2019re looking at approx. 4523 cmdlets (in total) so slightly less than cross forest moves but still enough to cause irregular heart beats and loud breathing once you read on and see what the commands are. Don\u2019t worry, I\u2019m here to help!<\/p>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><strong>ACTIVE DIRECTORY<\/strong><\/h3>\n<p style=\"text-align: justify;\">There\u2019s two ways you can do this:<\/p>\n<ul>\n<li>Set up Exchange and the required accounts in a standard Account Forest<\/li>\n<li>Set up Exchange in a Resource Forest and active accounts in an Account Forest, connected via the required trusts with Linked Mailboxes<\/li>\n<\/ul>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><span>Organisational Units<\/span><\/h3>\n<p style=\"text-align: justify;\">First thing to do before you even attempt to run setup.exe to install Exchange is to make sure your Active Directory Organisational Unit (OU) structure is up to scratch. If your customers are going to be logging onto a root domain, you want to make sure the OU structure is segregated. You don\u2019t want customers A, B and C all located in an OU called \u201cUsers\u201d just because you were preoccupied with trying to finally crack the Magicians Code on Channel 10 and didn\u2019t create the proper OU structure, which results in your colleague trying to differentiate between who belongs to customer A, B or C 6 months\u2019 down the track.<\/p>\n<p style=\"text-align: justify;\">In a nutshell, if you\u2019re hosting all your customers under a root domain, you want them segregated in separate OUs to make your administration life easier, kind of like the artwork presented below (Good ol\u2019 Visio never disappoints!)<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" style=\"width: 237px; height: 513px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/hambik_post_image007.png\" alt=\"\" data-udi=\"umb:\/\/media\/5d20d6b8a6284735a8b9790a1b1d28fc\"><\/p>\n<p style=\"text-align: justify;\">Now, no one will think differently of you if you decide to create your OU structure directly from Active Directory Users and Computers, however, if you decide to create it through PowerShell, not only will you be deemed Superior by your colleagues, but you will automatically be upgraded to next level God Mode status.<\/p>\n<p style=\"text-align: justify;\">This is the part where you tell us what the commands are, right? What kind of blog post do you think this would be if I didn\u2019t!<\/p>\n<p>On your Domain Controller, launch PowerShell and run the following command to create the OU that will hold all the data (i.e. the parent OU):<\/p>\n<ul>\n<li>New-ADOrganizationalUnit -Name \u201cHosted Customers\u201d Next, you want to create the child OUs within the parent OU to start segregating Customers A, B and C:<\/li>\n<li>New-ADOrganizationalUnit -Name \u201cHosted Customers\u201d -Path \u201cOU=CompanyA,OU=Hosted Customers,DC=pureawesomeness,DC=com,DC=au\u201d<\/li>\n<\/ul>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><span>User Principal Names<\/span><\/h3>\n<p style=\"text-align: justify;\">Next, you\u2019ll want to start adding in the required UPN suffixes to the AD Forest so that your customers can log in using their desired UPNs (e.g.<span>&nbsp;<\/span><a href=\"mailto:user1@domain.com.au\">user1@domain.com.au<\/a>). Referring back to on one of my previous blogs,<span>&nbsp;<\/span><a rel=\"noopener nofollow\" href=\"https:\/\/inswwdev.azurewebsites.net\/au\/the-mother-of-all-cross-forest-migrations\/\" target=\"_blank\">The Mother of All Cross Forest Migrations<\/a>, I was working in an Account\/Resource Forest scenario, so the UPNs weren\u2019t added in AD in the target forest as users were all authenticating with accounts in the source forest using Linked Mailboxes.<\/p>\n<p style=\"text-align: justify;\">Confused yet? I\u2019ll try and simplify it for you here\u2026<\/p>\n<p style=\"text-align: justify;\">If you&#8217;re soon to be multi-tenant Exchange platform is going to reside in the same forest as your active accounts and you want your customers to log in with their own domain name, run the below command on the Domain Controller:<\/p>\n<ul>\n<li>Set-ADForest -Identity \u201cYour local AD Domain\u201d -UPNSuffixes @{add=\u201ddomain.com.au\u201d}<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Next up, the all important installation of Exchange. I won\u2019t write about the installation process here but it\u2019s basically Next, Next, Next, finish Season 1 of Suits, make a cup of coffee, drink said cup of coffee, come back, reboot server and you\u2019re done! Well sort of\u2026then there\u2019s the basic configuration of the Exchange platform, which guess what, I\u2019ll outline for you in another blog post\u2026only if you subscribe to Insentragram. Oh, as if you didn\u2019t see that one coming ?<\/p>\n<p style=\"text-align: justify;\">Right, so Exchange installed, basic configuration done and now, the juicy part\u2026configuring the platform for multi-tenancy. Strap yourselves in!<\/p>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><strong>ADDRESS BOOK POLICY ROUTING AGENT<\/strong><\/h3>\n<p style=\"text-align: justify;\">Basically, this bad boy tells the users on your Exchange platform which Global Address List they are only allowed to look up. If you don\u2019t want the users who reside in GAL1 to see GAL2 users as external contacts, install the Address Book Routing (ABR) Agent on the Exchange server. Don\u2019t forget to enable it after install. As if trying to say Address Book Policy Routing Agent wasn\u2019t hard enough, now you must not only install it, but enable it! You\u2019re probably panicking now thinking \u201che\u2019s not going to tell us how to do this!\u201d\u2026Take a few deep breaths and proceed to read and guess what\u2026it consists of PowerShell! (this is either a face palm or an Evan Almighty Happy Dance moment)<\/p>\n<ul>\n<li>Launch the Exchange Management Shell and run the following \u2013<\/li>\n<\/ul>\n<p style=\"text-align: justify;\"><span>Install-TransportAgent -Name \u201cABP Routing Agent\u201d -TransportAgentFactory \u201cMicrosoft.Exchange.Transport.Agent.AddressBookPolicyRoutingAgent.AddressBookPolicyRoutingAgentFactory\u201d -AssemblyPath $env:ExchangeInstallPathTransportRolesagentsAddressBookPolicyRoutingAgentMicrosoft.Exchange.Transport.Agent.AddressBookPolicyRoutingAgent.dll<\/span><\/p>\n<p style=\"text-align: justify;\">Next, enable the Transport Routing agent:<\/p>\n<ul>\n<li>Enable-TransportAgent \u201cABP Routing Agent\u201d<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Once done, restart the transport service and verify the ABP Routing agent has been installed:<\/p>\n<ul>\n<li>Restart-Service MSExchangeTransport<\/li>\n<li>Get-TransportAgent\n<ul>\n<li>The ABP Routing Agent should be listed<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Final step is to enable the ABP Routing Agent<\/p>\n<ul>\n<li>Set-TransportConfig -AddressBookPolicyRoutingEnabled $true<\/li>\n<\/ul>\n<p><img decoding=\"async\" style=\"width: 690px; height: 149px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/thebeaststhatismultitenancy_img_22.png\" alt=\"\" data-udi=\"umb:\/\/media\/eeba8617f0d7413db2986d74d005127a\"><\/p>\n<p style=\"text-align: justify;\">Now, quick checklist<\/p>\n<ul>\n<li>Exchange installed \u2714<\/li>\n<li>ABP Routing Agent installed \u2714<\/li>\n<li>Cup of liquid gold consumed \u2714<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Proceed to the next phase of your training\u2026<\/p>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><strong>EMAIL ADDRESS POLICY<\/strong><\/h3>\n<p style=\"text-align: justify;\">Don\u2019t worry, this can be done from the Exchange Admin Centre (I can almost hear you cheering with joy!)<\/p>\n<p style=\"text-align: justify;\">First thing you want to do is create a new Email Address Policy, so the accounts get assigned the correct email addresses because you know, assigning user1 at Company A with a Company B email address is not the greatest thing you could do.<\/p>\n<p style=\"text-align: justify;\">Log into your Exchange 2016 EAC and browse to Mail Flow \u2013 Email Address Policies and click on the + symbol<\/p>\n<ul>\n<li>Give the policy a name that\u2019s easily distinguishable from the others\n<ul>\n<li>Use abbreviations, acronyms, whatever you wish<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\"><img decoding=\"async\" style=\"width: 626px; height: 114px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/thebeast-that-is-multi-tenancy_update_1.jpg\" alt=\"\" data-udi=\"umb:\/\/media\/754e78616cc84a09a7929a272cf50484\"><\/p>\n<ul>\n<li>Set the email address format and make sure you select the correct accepted domain\n<ul>\n<li>g. alias<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Make sure types of recipients is set as All recipient types (unless there\u2019s a specific reason you don\u2019t want the policy applied to all types)<\/li>\n<\/ul>\n<p><img decoding=\"async\" style=\"width: 614px; height: 477px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/thebeast-that-is-multi-tenancy_update_2.jpg\" alt=\"\" data-udi=\"umb:\/\/media\/b718181f349e4d27824b83d3913448f2\"><\/p>\n<ul>\n<li>Make sure types of recipients is set as All recipient types (unless there\u2019s a specific reason you don\u2019t want the policy applied to all types)<\/li>\n<\/ul>\n<p><img decoding=\"async\" style=\"width: 634px; height: 336px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/thebeast-that-is-multi-tenancy_update_3.jpg\" alt=\"\" data-udi=\"umb:\/\/media\/e3ba1c85ae65496bab7c55076a508951\"><\/p>\n<ul>\n<li>Next, click on Add a rule and from the drop down list, select Recipient Container and then select the OU you want to apply the policy to.<\/li>\n<li>Click Save and BOOM! Email Address Policy created BUT (there\u2019s always a BUT), don\u2019t forget to apply it. By default, email address policies aren\u2019t applied. Administrators need to manually apply it (just in case you made a slight boo boo and applied it to the wrong OU!) So double check the settings of the policy before applying and read the prompts you\u2019re presented with! They\u2019re labelled Warning for a reason.<\/li>\n<\/ul>\n<p><img decoding=\"async\" style=\"width: 370px; height: 278px;\" src=\"https:\/\/www.insentragroup.com\/wp-content\/uploads\/sites\/20\/2021\/02\/hambik_post_image003.png\" alt=\"\" data-udi=\"umb:\/\/media\/2eaf32d0a07646d19fe1f63fc4b5b26b\"><\/p>\n<p style=\"text-align: justify;\">You\u2019re on the home stretch now\u2026I promise\u2026maybe\u2026not really\u2026only joking\u2026but seriously\u2026HOME STRETCH!!<\/p>\n<h3 style=\"padding-bottom: 15px; margin-bottom: 30px; margin-top: 40px; border-bottom: 1px solid #f16020;\"><strong>ADDRESS LISTS AND POLICIES<\/strong><\/h3>\n<p style=\"text-align: justify;\">Buckle up because there\u2019s 4523 PowerShell cmdlets to run and that\u2019s just for one customer! Feel free to scream if need be. I\u2019m all ears.<\/p>\n<p style=\"text-align: justify;\">First, we want to create a new Global Address List:<\/p>\n<ul>\n<li>New-GlobalAddressList -Name \u201cGlobal Address List CompanyA\u201d -ConditionalCustomAttribute1 \u201cAttribute1\u201d -IncludedRecipients MailboxUsers,MailGroups,MailContacts -RecipientContainer \u201cpureawesomeness.com.au\/Hosted Customers\/CompanyA\u201d<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Few things to take note of:<\/p>\n<ul>\n<li style=\"text-align: justify;\">Replace CompanyA with the customer you\u2019re creating the GAL for (e.g. CompanyB, CompanyC etc)<\/li>\n<li style=\"text-align: justify;\">Make sure you enter the correct path for the OU as you want the GAL assigned to all recipients in that particular OU and not the wrong one!<\/li>\n<li style=\"text-align: justify;\">CustomAttribute1 is what we\u2019re going to use to assign the policies correctly to the accounts so when the objects are created in Exchange and in AD, don\u2019t forget to assign the correct attribute<\/li>\n<li style=\"text-align: justify;\">The value of CustomAttribute1 can be anything you want \u2013 just make sure it\u2019s different across all your customers (e.g. you don\u2019t want the same value for CompanyA assigned to objects in CompanyB)<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Next up, we want to create the Address Lists for Users, Contacts, Distribution Groups and Rooms:<\/p>\n<ul>\n<li style=\"text-align: justify;\">New-AddressList -Name \u201cAll Rooms CompanyA\u201d -RecipientFilter \u201c(CustomAttribute1 -eq \u2018Attribute1\u2019) -and (ResourcePropertiesDisplay -eq \u2018Equipment\u2019 -or ResourcePropertyDisplay -eq \u2018Room\u2019)\u201d -RecipientContainer \u201cpureawesomeness.com.au\/Hosted Customers\/CompanyA\u201d<\/li>\n<li style=\"text-align: justify;\">New-AddressList -Name \u201cAll Users CompanyA\u201d -RecipientFilter \u201c(CustomAttribute1 -eq \u2018Attribute1\u2019) -and (ObjectClass -eq \u2018User\u2019)\u201d -RecipientContainer \u201d pureawesomeness.com.au\/Hosted Customers\/CompanyA\u201d<\/li>\n<li style=\"text-align: justify;\">New-AddressList -Name \u201cAll Contacts CompanyA\u201d -RecipientFilter \u201c(CustomAttribute1 -eq \u2018Attribute1\u2019) -and (ObjectClass -eq \u2018Contact\u2019)\u201d -RecipientContainer \u201d pureawesomeness.com.au\/Hosted Customers\/CompanyA\u201d<\/li>\n<li style=\"text-align: justify;\">New-AddressList -Name \u201cAll Distribution Lists CompanyA\u201d -RecipientFilter \u201c(CustomAttribute1 -eq \u2018Attribute1\u2019) -and (ObjectClass -eq \u2018Group\u2019)\u201d -RecipientContainer \u201cpureawesomeness.com.au\/Hosted Customers\/CompanyA\u201d<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Almost there\u2026<\/p>\n<p style=\"text-align: justify;\">Now, we need an Offline Address Book:<\/p>\n<ul>\n<li style=\"text-align: justify;\">New-OfflineAddressBook -Name \u201cCompanyA\u201d -AddressLists \u201cGlobal Address List CompanyA\u201d\n<ul>\n<li style=\"text-align: justify;\">Global Address List CompanyA is the name of the GAL you assigned in the very first step<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Finally, we create the Address Book Policy and assign all of the newly created Address Lists to it:<\/p>\n<ul>\n<li style=\"text-align: justify;\">New-AddressBookPolicy -Name \u201cCompanyA Address Book Policy\u201d -AddressLists \u201cAll Users CompanyA\u201d,\u201dAll Distribution Lists CompanyA\u201d,\u201dAll Contacts CompanyA\u201d -RoomList \u201cAll Rooms CompanyA\u201d -OfflineAddressBook \u201cCompanyA\u201d -GlobalAddressList \u201cGlobal Address List CompanyA\u201d<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">There you have it my loyal apprentice. Your Exchange Server 2016 deployment is now configured as a multi-tenant solution\u2026for only one customer! Don\u2019t forget to repeat the above for the other customers you bring on board, but with the required different values!<\/p>\n<p style=\"text-align: justify;\">See, there\u2019s a reason why the title of this blog is called The Beast That Is Multi-Tenancy!<\/p>\n<p>Until next time, signing off!<\/p>\n<p>Yours Truly,<\/p>\n<p>Pure Awesomeness<\/p>\n<p style=\"text-align: justify;\"><em>\u201cYou want to be a writer, don\u2019t know how or when? Find a quiet place, use a humble pen\u201d \u2013 Paul Simon<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi guys, yep it\u2019s me again\u2026the pure awesomeness that got you through the cross forest migrations. Just when you thought your cerebrum, you know, the large part of your brain that does all the thinking, had just been taken through its paces with trying to memorise cross forest migrations, along comes me again! This time&hellip; <a class=\"more-link\" href=\"https:\/\/www.insentragroup.com\/gb\/insights\/geek-speak\/migrations\/the-beast-that-is-multi-tenancy\/\">Continue reading <span class=\"screen-reader-text\">The Beast That is Multi-Tenancy<\/span><\/a><\/p>\n","protected":false},"author":52,"featured_media":6580,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"content-type":"","footnotes":""},"categories":[22],"tags":[],"class_list":["post-1923","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-migrations","entry"],"_links":{"self":[{"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/posts\/1923","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/users\/52"}],"replies":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/comments?post=1923"}],"version-history":[{"count":1,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/posts\/1923\/revisions"}],"predecessor-version":[{"id":15749,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/posts\/1923\/revisions\/15749"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/media\/6580"}],"wp:attachment":[{"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/media?parent=1923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/categories?post=1923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.insentragroup.com\/gb\/wp-json\/wp\/v2\/tags?post=1923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}