Moving an Office 365 domain to a new tenant

There are times when companies acquire other companies to increase their portfolio. When this happens, the acquired company’s IT infrastructure normally gets merged with the parent company. The opposite of this situation is also true. There are also times when a company sells off one of its acquired companies or divisions. In this scenario, the company that is being sold off must have all its IT infrastructure separated from the parent company.

In this blog I will show the steps that can be used to separate a previously acquired company’s email system from its parent company, after the child company has been sold off.

Background

To provide some context, let me provide some details for the parent company and the child company that is being sold off

  • The parent company is called Tail Spin Toys and owns the domain name tailspintoys.com
  • Tail Spin Toys have their own Active Directory Forest called tailspintoys.com and this is synchronised to Azure Active Directory using Azure Active Directory Connect (AADC) server.
  • Tail Spin Toys has a hybrid Exchange Online setup. Their Office 365 tenant is called tailspintoys and has the tenant address of tailspintoys.onmicrosoft.com
  • Tail Spin Toys users have their userprincipalname and primary email address in the form of firstname.lastname@tailspintoys.com
  • The previously acquired company (referred to as child company in this blog) is trading as Wing Tip Toys and owns the domain name wingtiptoys.com. This domain has been added to Tail Spin Toys Office 365 tenant as an additional domain.
  • Wing Tip Toys have their own Active Directory Forest called wingtiptoys.net and all their users, computers and servers are part of this Active Directory Forest.
  • Wing Tip Toys users have their mailboxes provisioned in Tail Spin Toys Office 365 tenant (the process will be explained in the next bullet point). Wing Tip Toys only use email services in Office 365.
  • Each Wing Tip Toys user has two identities. The first is in the wingtiptoys.net Active Directory Domain, which is used to login to their computers and to access their local resources (fileshares, printers etc).
  • The other identity is a user object created in Tail Spin Toys Active Directory Domain. This is used to provision a mailbox in Tail Spin Toys Office 365 tenant. Unfortunately, for Wing Tip Toys users, their Office 365 experience is not very elegant since their userprincipalname for Office 365 is of the form firstname.lastname@tailspintoys.com but their primary email address is of the form firstname.lastname@wingtiptoys.com. The users login to their computers using the wingtiptoys.net samaccountname. However, all users are aware of this and it doesn’t affect them too much.
  • To ensure users are not burdened with having to manage both the user object passwords, Password Change Notification System has been implemented. This replicates any password changes in the wingtiptoys.net Active Directory domain to the respective user object in tailspintoys.com Active Directory domain.

Requirement

Now that Wing Tip Toys has been sold off, all of its data must be separated from Tail Spin Toys. The following will be done for its emails.

  • A new Office 365 tenant will be provisioned for Wing Tip Toys
  • All mailbox data will be migrated to the new Office 365 tenant
  • Once all mailbox data has been migrated, after a few weeks, the Wing Tip Toys mailboxes in Tail Spin Toys Office 365 tenant will be disabled (or deleted)

Migration Plan

Ok, lets get started.

  • Due to the small size of Wing Tip Toys, it has been decided to use a Cloud-Only Office 365 Deployment. ( details on how to configure a Cloud-Only Office 365 deployment can be found here ) however a hybrid Exchange Online environment will still work with the following steps ( a few extra steps will have to be added)
  • BitTitan MigrationWiz will be used to copy the mailbox data from Tail Spin Toys Office 365 tenant to Wing Tip Toys Office 365 tenant

Here are the steps

  1. Add an additional UPN suffix (wingtiptoys.com) to the Wing Tip Toys Active Directory Domain
  2. Configure all Wing Tip Toys users in the wingtiptoys.net domain to have a userprincipalname of the form firstname.lastname@wingtiptoys.com
  3. For all the Wing Tip Toys users in the Tail Spin Toys Office 365 tenant, export their email addresses (we are after the proxyaddresses). Ensure the X500 addresses are also exported.
  4. In the wingtiptoys.net Active Directory domain, for each user, find their email addresses from the export that was done in step 3 and import it into the proxyaddresses attribute of their Active Directory user object. Ensure only email addresses for the domain wingtiptoys.com are imported (if you import any email address for which the domain hasn’t been added to wingtiptoys Office 365 tenant, these will display as the default Office 365 tenant address [@wingtiptoys.onmicrosoft.com] instead of the actual email address). Also, make sure the X500: addresses are also imported. Check to ensure the proxyaddress firstname.lastname@wingtiptoys.com is prefixed with an uppercase SMTP:. This will make it the primary smtp address
  5. Create a new Office 365 tenant for Wing Tip Toys. For simplicity, we will assume that the tenant name is wingtiptoys and the tenant address is wingtiptoys.onmicrosoft.com. Since the domain wingtiptoys.com is already attached to the Tail Spin Toys Office 365 tenant, we won’t be able to attach it to the new tenant just yet.
  6. Install Azure Active Directory Connect (AADC) Server and configure it to synchronise objects from the wingtiptoys.net Active Directory domain to the Wing Tip Toys Azure AD. For Single Sign On, we will enable AADC server for password hash synchronisation however Active Directory Federation Services (ADFS) servers can also be used.
  7. If required, configure the transport rules in Wing Tip Toys Office 365 tenant to match those in Tail Spin Toys Office 365 tenant. For example, to apply disclaimers to all outgoing emails.
  8. Export configuration of all Distribution groups in Tail Spin Toys Office 365 tenant that belong to Wing Tip Toys.
  9. Create a user in Tail Spin Toys Office 365 tenant with the upn migrationwiz@tailspintoys.onmicrosoft.com. For all Wing Tip Toys mailboxes in Tail Spin Toys Office 365 tenant, give migrationwiz@tailspintoys.onmicrosoft.com full mailbox access. This account will be used by Bittitan MigrationWiz.
  10. Create a user in Wing Tip Toys Office 365 tenant with the upn migrationwiz@wingtiptoys.onmicrosoft.com and give it Global Administrator access. This account will be used by Bittitan MigrationWiz.
  11. Provision Office 365 licenses (at least Exchange Online Plan 2) to all user objects in Wing Tip Toys Office 365 tenant that have been synchronised from the on-premise Active Directory domain. This will create mailboxes for them. At this stage, they will only have the email address firstname.lastname@wingtiptoys.onmicrosoft.com (this is because the domain wingtiptoys.com hasn’t been added to this tenant).
  12. Create an account at Bittitan and purchase licenses for MigrationWiz. One license is required for one mailbox data migration, so purchase the required number of licenses ( when you create an account, you are provided with 3 trial licenses. You can use these to test out the migration process).
  13. Use the steps listed at https://help.bittitan.com/hc/en-us/articles/115008106827-Office-365-to-Office-365-Migration-Guide-While-Keeping-the-Same-Domain-Name to configure Bittitan MigrationWiz. The source and destination mailboxes within MigrationWiz must be specified using the Office 365 tenant address, for example in our case, the source mailboxes will be firstname.lastname@tailspintoys.onmicrosoft.com and the destination mailboxes will be firstname.lastname@wingtiptoys.onmicrosoft.com
  14. Pre-Stage the mailbox data for the Wing Tip Toys mailboxes by using MigrationWiz to copy everything except the last 20 days of data from the Tail Spin Toys Office 365 tenant to the Wing Tip Toys Office 365 tenant mailboxes (the more data you pre-stage, the faster the cut-over will be).
  15. Add wingtiptoys.com domain to the Wing Tip Toys Office 365 tenant. You will get a TXT record, which must be used to create a DNS entry in wingtiptoys.com domain, to prove domain owership. Create the DNS record and have the TTL set to 300s (5min). You won’t be able to verify the domain in Wing Tip Toys Office 365 tenant as it is currently attached to the Tail Spin Toys Office 365 tenant.
  16. Change the TTL for the MX DNS entry for wingtiptoys.com to 300s (5min). Make a note of the existing MX entries.
  17. At this stage, all the preparation has been done and we are ready for the cut-over. I would suggest planning the cutover out of office hours, preferably on a Friday evening. Send out user communications at least a week prior to cut-over so that everyone is aware of the change. In the communications, ensure you state that users will not be able to receive new emails in their Mobile and Outlook clients until it has been reconfigured to use the new Office 365 tenant. Provide instructions on how users can reconfigure their Outlook and Mobile clients and also provide the Outlook Web App address (this would be similar to https://outlook.office.com/wingtiptoys.com/ )
  18. Twenty minutes prior to cut-over time, change the MX for wingtiptoys.com to invalid.outlook.com. Setting the MX record to an invalid domain just ahead of the migration causes the sender’s email server to queue the emails and retry later. This will reduce the possibility of Office 365 sending a “recipient not found” Non Delivery Receipt if the email is received for a Wing Tip Toys user after the wingtiptoys.com domain has been removed from the Tail Spin Toys Office 365 tenant but hasn’t been added to the Wing Tip Toys Office 365 tenant.
  19. At cut-over time, remove the domain wingtiptoys.com from Tail Spin Toys Office 365 tenant. A message will be displayed stating that user logins and email addresses will need to be reconfigured. It will also state that the automatic domain removal process will change them to the default domain (tailspintoys.com) and that they will no longer receive emails at wingtiptoys.com. Click Remove. The time taken to remove the domain depends on the amount of mailboxes that have to be reconfigured to use the tenant email address.
  20. Add wingtiptoys.com to the Wing Tip Toys Office 365 tenant. If you receive an error stating that the domain is already attached to another Office 365 tenant, wait for a few minutes and then try again.
  21. Run a Full Synchronisation using Azure Active Directory Connect server and wait for it to complete. Confirm that the userprincipalname and primary smtp address for the users in the Wing Tip Toys Office 365 tenant has now changed to the format firstname.lastname@wingtiptoys.com.
  22. Change the MX for wingtiptoys.com to the value shown in the Wing Tip Toys Office 365 Portal under Domain Settings.
  23. Run a full migration using MigrationWiz so that the remaining mailbox data is copied across.
  24. Create a DNS entry in the internal and external DNS server for autodiscover.wingtiptoys.com. The value for this is shown in the Wing Tip Toys Office 365 Portal, under the Domains section.
  25. Test the following scenarios
    • you can login using Outlook Web App to a mailbox in the Wing Tip Toys Office 365 tenant and access all emails.
    • you can configure Outlook client and a Mobile email client to access a mailbox in the new Wing Tip Toys Office 365 tenant using autodiscover (this depends on the autodiscover.wingtiptoys.com dns record. If there are errors, check to ensure this record has been correctly populated and is pointing to the value shown in the Office 365 portal)
    • emails from external senders are successfully received in a wingtiptoys mailbox in the Wing Tip Toys Office 365 tenant.
    • emails sent from a wingtiptoys user in the Wing Tip Toys Office 365 tenant to an external recipient is successfully received
    • emails sent between wingtiptoys users in the Wing Tip Toys Office 365 tenant is successfully received
  26. Import the Distribution groups that were exported from Tail Spin Toys Office 365 tenant
  27. The cut-over is now complete.
  28. By now, users must be able to access their emails using Outlook Web App. If they have followed the instructions, their Outlook and Mobile devices must be working as well.
  29. The mailboxes belonging to the Wing Tip Toys users in the Tail Spin Toys Office 365 tenant can be kept active for at least 30 days (this will come in handy for those cases where a user reports that some emails were not copied across). After this, the mailboxes can be backed up and then deleted (If the Wing Tip Toys user mailboxes in the Tail Spin Toys Office 365 tenant had other email aliases, on which emails were being received, it would be a good idea to configure an Out of Office rule to state that all emails sent to this user should instead be sent to firstname.lastname@wingtiptoys.com)

 

Thats it folks. After following the above steps, you would have moved an additional Office 365 domain to a new Office 365 tenant and would have also moved their mailbox data to the new tenant.

I hope the above helps those that are looking at getting this done.

Have a great day 😉

Advertisements

A tool to find mailbox permission dependencies

When planning to migrate mailboxes to Office 365, a lot of care must be taken around which mailboxes are moved together. The rule of the thumb is “those that work together, move together”. The reason for taking this approach is due to the fact that there are some permissions that do not work cross-premises and can cause issues. For instance, if a mailbox has delegate permissions to another mailbox (these are permissions that have been assigned using Outlook email client) and if one is migrated to Office 365 while the other remains on-premises, the delegate permissions capability is broken as it does not work cross-premises.

During the recent Microsoft Ignite, it was announced that there are a lot of features coming to Office 365 which will help with the cross-premises access issues.

I have been using Roman Zarka’s Export-MailboxPermissions.ps1 (part of https://blogs.technet.microsoft.com/zarkatech/2015/06/11/migrate-mailbox-permissions-to-office-365/ bundle) script to export all on-premises mailboxes permissions then using the output to decide which mailboxes move together. Believe me, this can be quite a challenge!

Recently, while having a casual conversation with one of my colleagues, I was introduced to an Excel  spreadsheet that he had created. Being the Excel guru that he is, he was doing various VLOOKUPs into the outputs from Roman Zarka’s script, to find out if the mailboxes he was intending to migrate had any permission dependencies with other mailboxes. I just stared at the spreadsheet with awe, and uttered the words “dude, that is simply awesome!”

I was hooked on that spreadsheet. However, I started craving for it to do more. So I decided to take it on myself to add some more features to it. However, not being too savvy with Excel, I decided to use PowerShell instead. Thus was born Find_MailboxPermssions_Dependencies.ps1

I will now walk you through the script and explain what it does

 

  1. The first pre-requisite for Find_MailboxPermissions_Dependencies.ps1 are the four output files from Roman Zarka’s Export-MailboxPermissions.ps1 script (MailboxAccess.csv, MailboxFolderDelegate.csv, MailboxSendAs.csv, MaiboxSendOnBehalf.csv)
  2. The next pre-requisite is details about the on-premises mailboxes. The on-premises Exchange environment must be queried and the details output into a csv file with the name OnPrem_Mbx_Details.csv. The csv must contain the following information (along the following column headings)“DisplayName, UserPrincipalName, PrimarySmtpAddress, RecipientTypeDetails, Department, Title, Office, State, OrganizationalUnit”
  3. The last pre-requisite is information about mailboxes that are already in Office 365. Use PowerShell to connect to Exchange Online and then run the following command (where O365_Mbx_Details.csv is the output file)
    Get-Mailbox -ResultSize unlimited | Select DisplayName,UserPrincipalName,EmailAddresses,WindowsEmailAddress,RecipientTypeDetails | Export-Csv -NoTypeInformation -Path O365_Mbx_Details.csv 

    If there are no mailboxes in Office 365, then create a blank file and put the following column headings in it “DisplayName”, “UserPrincipalName”, “EmailAddresses”, “WindowsEmailAddress”, “RecipientTypeDetails”

  4. Next, put the above files in the same folder and then update the variable $root_dir in the script with the path to the folder (the path must end with a )
  5. It is assumed that the above files have the following names
    • MailboxAccess.csv
    • MailboxFolderDelegate.csv
    • MailboxSendAs.csv
    • MailboxSendOnBehalf.csv
    • O365_Mbx_Details.csv
    • OnPrem_Mbx_Details.csv
  6.  Now, that all the inputs have been taken care of, run the script.
  7. The first task the script does is to validate if the input files are present. If any of them are not found, the script outputs an error and terminates.
  8. Next, the files are read and stored in memory
  9. Now for the heart of the script. It goes through each of the mailboxes in the OnPrem_Mbx_Details.csv file and finds the following
    • all mailboxes that have been given SendOnBehalf permissions to this mailbox
    • all mailboxes that this mailbox has been given SendOnBehalf permissions on
    • all mailboxes that have been given SendAs permissions to this mailbox
    • all mailboxes that this mailbox has been given SendAs permissions on
    • all mailboxes that have been given Delegate permissions to this mailbox
    • all mailboxes that this mailbox has been given Delegate permissions on
    • all mailboxes that have been given Mailbox Access permissions on this mailbox
    • all mailboxes that this mailbox has been given Mailbox Access permissions on
    • if the mailbox that this mailbox has given the above permissions to or has got permissions on has already been migrated to Office 365
  10. The results are then output to a csv file (the name of the output file is of the format Find_MailboxPermissions_Dependencies_{timestamp of when script was run}_csv.csv
  11. The columns in the output file are explained below
Column Name Description
PermTo_OtherMbx_Or_FromOtherMbx? This is Y if the mailbox has given permissions to or has permissions on other mailboxes. Is N if there are no permission dependencies for this mailbox
PermTo_Or_PermFrom_O365Mbx? This is TRUE if the mailbox that this mailbox has given permissions to or has permissions on is  already in Office 365
Migration Readiness This is a color code based on the migration readiness of this permission. This will be further explained below
DisplayName The display name of the on-premises mailbox for which the permission dependency is being found
UserPrincipalName The userprincipalname of the on-premises mailbox for which the permission dependency is being found
PrimarySmtp The primarySmtp of the on-premises mailbox  for which the permission dependency is being found
MailboxType The mailbox type of the on-premises mailbox  for which the permission dependency is being found
Department This is the department the on-premises mailbox belongs to (inherited from Active Directory object)
Title This is the title that this on-premises mailbox has (inherited from Active Directory object)
SendOnBehalf_GivenTo emailaddress of the mailbox that has been given SendOnBehalf permissions to this on-premises mailbox
SendOnBehalf_GivenOn emailaddress of the mailbox that this on-premises mailbox has been given SendOnBehalf permissions to
SendAs_GivenTo emailaddress of the mailbox that has been given SendAs permissions to this on-premises mailbox
SendAs_GivenOn emailaddress of the mailbox that this on-premises mailbox has been given SendAs permissions on
MailboxFolderDelegate_GivenTo emailaddress of the mailbox that has been given Delegate access to this on-premises mailbox
MailboxFolderDelegate_GivenTo_FolderLocation the folders of the on-premises mailbox that the delegate access has been given to
MailboxFolderDelegate_GivenTo_DelegateAccess the type of delegate access that has been given on this on-premises mailbox
MailboxFolderDelegate_GivenOn email address of the mailbox that this on-premises mailbox has been given Delegate Access to
MailboxFolderDelegate_GivenOn_FolderLocation the folders that this on-premises mailbox has been given delegate access to
MailboxFolderDelegate_GivenOn_DelegateAccess the type of delegate access that this on-premises mailbox has been given
MailboxAccess_GivenTo emailaddress of the mailbox that has been given Mailbox Access to this on-premises mailbox
MailboxAccess_GivenTo_DelegateAccess the type of Mailbox Access that has been given on this on-premises mailbox
MailboxAccess_GivenOn emailaddress of the mailbox that this mailbox has been given Mailbox Access to
MailboxAccess_GivenOn_DelegateAccess the type of Mailbox Access that this on-premises mailbox has been given
OrganizationalUnit the Organizational Unit for the on-premises mailbox

The color codes in the column Migration Readiness correspond to the following

  • LightBlue – this on-premises mailbox has no permission dependencies and can be migrated
  • DarkGreen  – this on-premises mailbox has got a Mailbox Access permission dependency to another mailbox. It can be migrated while the other mailbox can remain on-premises, without experiencing any issues as Mailbox Access permissions are supported cross-premises.
  • LightGreen – this on-premises mailbox can be migrated without issues as the permission dependency is on a mailbox that is already in Office 365
  • Orange – this on-premises mailbox has SendAs permissions given to/or on another on-premises mailbox. If both mailboxes are not migrated at the same time, the SendAs capability will be broken. Lately, it has been noticed that this capability can be restored by re-applying the SendAs permissions to both the migrated and on-premises mailbox post migration
  • Pink – the on-premises mailbox has FolderDelegate given to/or on another on-premises mailbox. If both mailboxes are not migrated at the same time, the FolderDelegate capability will be broken. A possible workaround is to replace the FolderDelegate permission with Full Mailbox access as this works cross-premises, however there are privacy concerns around this workaround as this will enable the delegate to see all the contents of the mailbox instead of just the folders they had been given access on.
  • Red – the on-premises mailbox has SendOnBehalf permissions given to/or on another on-premises mailbox. If both mailboxes are not migrated at the same time, the SendOnBehalf capability will be broken. A possible workaround could be to replace SendOnBehalf with SendAs however the possible implications of this change must be investigated

12. Yay, the output has now been generated. All we need to do now is to make it look pretty in Excel 🙂

Carry out the following steps

  • Import the output csv file into Excel, using the semi-colon “;” as the delimiter (I couldn’t use commas as the delimiter as sometimes department,titles etc fields use them and this causes issues with the output file)
  • Create Conditional Formatting rules for the column Migration Readiness so that the fill color of this cell corresponds to the word in this column (for instance, if the word is LightBlue then create a rule to apply a light blue fill to the cell)

Thats it Folks! The mailbox permissions dependency spreadsheet is now ready. It provides a single-pane view to all the permissions across your on-premises mailboxes and gives a color coded analysis on which mailboxes can be migrated on their own without any issues and which might experience issues if they are not migrated in the same batch with the ones they have permissions dependencies on.

In the output file, for each on-premises mailbox, each line represents a permission dependency (unless the column PermTo_OtherMbx_Or_FromOtherMbx? is N). If there are more than one set of permissions applicable to an on-premises mailbox, these are displayed consecutively underneath each other.

It is imperative that the migration readiness of the mailbox be evaluated based on the migration readiness of all the permissions associated with that mailbox.

Find_MailboxPermissions_Dependencies.ps1 can be downloaded from  GitHub

A sample of the spreadsheet that was created using the output from the Find_MailboxPermissions_Dependencies.ps1 script can be downloaded from https://github.com/nivleshc/arm/blob/master/Sample%20Output_MailboxPermissions%20Dependencies.xlsx

I hope this script comes in handy when you are planning your migration batches and helps alleviate some of the headache that this task brings with it.

Till the next time, have a great day 😉

[Updated] How are email addresses created for Office 365 Mailboxes?

Background

Over the past few weeks, I have been doing some Cloud-Only Office 365 deployments using Azure AD Connect . As you might imagine, this deployment is abit different to the Hybrid Office 365 deployment.

One of the things that got me thinking was, how are the email addresses created for my Office 365 mailboxes? As I was synchronising objects from my on-premises Active Directory, this question held the answer to what values I needed to change in my on-premises Active Directory user object, to get the desired email addresses populated in the Office 365 mailbox that will be created for it.

Preparation

To find the above answer, I devised a simple experiment.

I decided to create four on-premises Active Directory user objects, with different combinations of Netbios, UserPrincipalName (UPN), Mail attribute and ProxyAddresses and trace what happens to these values as they are used to create their corresponding Azure AD object. I will then assign an Office 365 Exchange Online Plan 2 license to these Azure AD objects and see what email addresses got assigned to the resulting Office 365 mailbox.

Simple? Lets begin.

The four user accounts I created in on-premises Active Directory had the following properties (ProxyAddresses were populated using ADSIEdit). The domains used by the UPN, Email and proxyaddresses attributes are all internet routable domains.

FirstName     :Ross
LastName      :McCary
DisplayName.  :Ross McCary
Netbios       :CONTOSO\R.McCary
UPN           :Ross.McCary@contoso.com
Email         :{blank}
ProxyAddresses:{blank}

FirstName.    :Angela
LastName      :Jones
DisplayName.  :Angela Jones
Netbios       :CONTOSO\A.Jones
UPN           :Angela.Jones@contoso.com
Email         :An.Jones@contoso.com
ProxyAddresses:{blank}

FirstName     :Zada
LastName      :Daley
DisplayName.  :Zada Daley
Netbios       :CONTOSO\Z.Daley
UPN           :Zada.Daley@contoso.com
Email         :Zada.Daley@tailspintoys.com
ProxyAddresses:{blank}

FirstName     :Bob
LastName      :Brown
DisplayName   :Bob Brown
Netbios       :CONTOSO\B.Brown
UPN           :Bob.Brown@contoso.com
Email         :Bob.Brown@contoso.com
ProxyAddresses:SMTP:Bo.Brown@contoso.com
               smtp:Bob@contoso.com
               smtp:Bobi@tailspintoys.com

The Experiment

I initiated an Azure AD Connect delta synchronisation cycle and waited. After a few minutes, I saw new objects created in my Office 365 tenant’s Azure AD that corresponded to the ones that I had created in the on-premises Active Directory.

Here are the values that Azure AD Connect (AADC) added for the newly created AAD objects (tenantid is the id for the Office 365 tenant)

FirstName     :Ross
LastName      :McCary
DisplayName   :Ross McCary
SignInName    :Ross.McCary@contoso.com
UPN           :Ross.McCary@contoso.com
ProxyAddresses:{blank}

FirstName     :Angela
LastName      :Jones
DisplayName   :Angela Jones
SignInName    :Angela.Jones@contoso.com
UPN           :Angela.Jones@contoso.com
ProxyAddresses:{SMTP:An.Jones@contoso.com}

FirstName     :Zada
LastName      :Daley
DisplayName   :Zada Daley
SignInName.   :Zada.Daley@contoso.com
UPN           :Zada.Daley@contoso.com
ProxyAddresses:{SMTP:Zada.Daley@tailspintoys.com}

FirstName     :Bob
LastName      :Brown
DisplayName   :Bob Brown
SignInName.   :Bob.Brown@contoso.com
UPN           :Bob.Brown@contoso.com
ProxyAddresses:{SMTP:Bo.Brown@contoso.com,
                smtp:Bob@contoso.com,
                smtp:Bobi@tailspintoys.com,
                smtp:Bo.Brown@tenantid.onmicrosoft.com,
                smtp:Bob.Brown@contoso.com}

Now, this was quite interesting. AADC added proxyaddresses for only those Azure AD (AAD) objects that had the email field populated in their corresponding on-premises Active Directory user objects. Also, for Bob Brown, two additional proxy addresses had been added. Interesting indeed! (the additional attributes are in orange above)

I then proceeded to assigning an Office 365 Exchange Online Plan 2 license to all the above AAD objects so that a mailbox would be provisioned for them. After waiting a few minutes, I checked to confirm that the mailboxes had been successfully provisioned. I then went back to Azure AD and checked the attributes again.

Below is what I saw (additional values that got added after license assignment are in Orange)

FirstName     :Ross
LastName      :McCary
DisplayName   :Ross McCary
SignInName    :Ross.McCary@contoso.com
UPN           :Ross.McCary@contoso.com
ProxyAddresses:{SMTP:Ross.McCary@tenantid.onmicrosoft.com,
                smtp:Ross.McCary@contoso.com}

FirstName     :Angela
LastName      :Jones
DisplayName   :Angela Jones
SignInName    :Angela.Jones@contoso.com
UPN           :Angela.Jones@contoso.com
ProxyAddresses:{SMTP:An.Jones@contoso.com,
                smtp:Angela.Jones@contoso.com,
                smtp:An.Jones@tenantid.onmicrosoft.com}

FirstName     :Zada
LastName      :Daley
DisplayName   :Zada Daley
SignInName    :Zada.Daley@contoso.com
UPN           :Zada.Daley@contoso.com
ProxyAddresses:{SMTP:Zada.Daley@tailspintoys.com,
                smtp:Zada.Daley@contoso.com,
                smtp:Zada.Daley@tenantid.onmicrosoft.com}

FirstName     :Bob
LastName      :Brown
DisplayName   :Bob Brown
SignInName.   :Bob.Brown@contoso.com
UPN           :Bob.Brown@contoso.com
ProxyAddresses:{SMTP:Bo.Brown@contoso.com,
                smtp:Bob@contoso.com,
                smtp:Bobi@tailspintoys.com,
                smtp:Bo.Brown@tenantid.onmicrosoft.com,
                smtp:Bob.Brown@contoso.com}

For the mailboxes, below is what I saw

FirstName     :Ross
LastName      :McCary
DisplayName   :Ross McCary
UserID        :Ross.McCary@contoso.com
ProxyAddresses:{SMTP:Ross.McCary@tenantid.onmicrosoft.com,
                smtp:Ross.McCary@contoso.com}

FirstName     :Angela
LastName      :Jones
DisplayName   :Angela Jones
UserID        :Angela.Jones@contoso.com
ProxyAddresses:{SMTP:An.Jones@contoso.com,
                smtp:Angela.Jones@contoso.com,
                smtp:An.Jones@tenantid.onmicrosoft.com}

FirstName     :Zada
LastName      :Daley
DisplayName.  :Zada Daley
UserID        :Zada.Daley@contoso.com
ProxyAddresses:{SMTP:Zada.Daley@tailspintoys.com,
                smtp:Zada.Daley@contoso.com,
                smtp:Zada.Daley@tenantid.onmicrosoft.com}

FirstName     :Bob
LastName      :Brown
DisplayName   :Bob Brown
UserID        :Bob.Brown@contoso.com
ProxyAddresses:{SMTP:Bo.Brown@contoso.com,
                smtp:Bob@contoso.com,
                smtp:Bobi@tailspintoys.com,
                smtp:Bo.Brown@tenantid.onmicrosoft.com,
                smtp:Bob.Brown@contoso.com}

Quite interesting (hmm well not really 😉 ). The newly created mailboxes had the same proxyaddresses as the proxyaddresses assigned to their corresponding AAD object.

The Result

After looking at the results, I could easily see a pattern between the on-premises Active Directory user object’s email and proxyaddresses values and the Azure AD and Office 365 mailbox email addresses.

From my experiment, I deduced the following process that is used to create email addresses for the Office 365 mailboxes

  1. When provisioning Azure AD objects, AADC first checks to see if the on-premises AD user object has proxyaddresses assigned. If there are any, these are added as proxyaddresses for the Azure AD object (the proxyaddress with the SMTP: prefix (uppercase smtp) will be the primarySMTP for the AAD object). If the email attribute is not part of the proxyaddresses, it is added as an additional proxyaddress. Next, the primarySMTP’s part before the @ is prefixed to the tenant email domain to create the mailbox’s routing email address and then added as an additional proxyaddress (for instance Ross.McCary@tenantid.onmicrosoft.com)
  2. If the on-premises Active Directory user object does not have any proxyaddresses, then the email attribute is assigned as the primarySMTP address for the AAD object. If the email attribute is not the same as the UPN, then the UPN is added as an additional proxy address. Next, the primarySMTP’s part before the @ is prefixed to the tenant email domain to create the mailbox’s routing email address and then added as an additional proxyaddress (for instance Ross.McCary@tenantid.onmicrosoft.com)
  3. In cases where both the email attribute and proxyAddresses are blank, the part of the UPN before the @ is prefixed to the tenant email domain to create the mailbox’s routing email address. In this instance, the routing email address is set as the primarySMTP address. The UPN is then added as an additional proxyaddress.

An interesting thing to note is that even before assigning an Office 365 license, you can see what email addresses will be assigned, by using PowerShell to check the proxyaddresses attribute of the Azure AD object.

I hope the above provides some clarity around how email addresses are created for Office 365 mailboxes and helps with your Cloud-Only Office 365 architectures.

Have a great day 😉

[Update] There could be instances, where by some mistake

  • (a) a new user is assigned an email attribute that is already attached to an existing mailbox in Office 365
  • (b) a new user is assigned a proxyaddress that is already attached to an existing mailbox in Office 365

For issue (a), AADC will not create the new user in AAD and instead display an error in the AADC console when doing an exporting to AAD. The error will be similar to below

“Unable to update this object because the following attributes associated with this object have values that may already be associated with another object in your local directory services: [ProxyAddresses xxxxxxxxx;]. Correct or remove the duplicate values in your local directory.”

The error will provide detailed information regarding the values that are causing the issue. It will also contain the ObjectIdInConflict. This is the id of the existing Object that the new user is in conflict with.

Using the ObjectIdInConflict value, search the AADC Metaverse with the clause “cloudAnchor contains ObjectIdInConflict“. (replace ObjectIdInConflict with the ObjectIdInConflict value as shown in the error). This will show the metaverse record of the object that the new user is conflicting with. In this case, remediate the issue in the on-premises Active Directory and then initiate another AADC delta synchronisation cycle.

For issue (b), AADC will create a new user in AAD however it will remove the proxyAddress that is causing the conflict from the new user object in AAD. It will also create a record in the Office 365 Admin Center, under Settings\DirSync errors, with details of the new user, the existing user that it is in conflict with and also the attribute that is in conflict. In this case, remediate the issue in the on-premises Active Directory and initiate another AADC delta synchronisation cycle.

Note: In both cases above, the technical contact for the Office 365 tenant gets sent an email with details of the errors.

Deploying Cloud-only mailboxes in Office 365 using On-Premises Directory objects

In this blog, I will show you how to create Cloud-only mailboxes in Exchange Online (Exchange Online is the messaging part of Office 365) that are bound to objects synchronised from your on-premises Active Directory. The Cloud-only approach is different to the Hybrid approach because you do not need an Exchange server deployed in your on-premises environment.

There are a few reasons why you would want to link your Cloud-only mailboxes to your on-premises Active Directory. The most important reason is to ensure you don’t have multiple identities for the same user. Another reason is to provide the notion of single-sign-on. This can be established by using the password synchronisation feature of Azure AD Connect (this will be discussed abit later).

Ok, lets get started.

The diagram below shows what we will be doing. In a nutshell, we will replicate our on-premises Active Directory objects to Azure AD (these will be filtered so that only required objects are synchronised to Azure AD) using Azure AD Connect Server. Once in Azure AD, we will appropriately license the objects using the Office 365 Admin portal (any license bundle that contains the Exchange Online Plan 2 license is fine. Even Exchange Online Plan 2 by itself is sufficient).

Onpremise AD Objects Synchronised AAD

Prepare your Office 365 Tenant

Once you have obtained your Office 365 tenant, add and verify the domain you will be using for your email addresses (for instance, if your email address will be tom.jones@contoso.com, then add contoso.com in Office 365 Admin Center under Setup\Domains). You will be provided with a TXT entry that you will need to use to create a DNS entry under the domain, to prove ownership.

Once you have successfully verified the domain ownership, you will be provided with the MX entry value for the domain. This must be used to create an MX entry DNS record for the domain so that all emails are delivered to Office 365.

Prepare your on-premises Active Directory

You must check to ensure your on-premises Active Directory does not contain any objects that are incompatible with Azure AD. To perform this check, run idFix in your environment.

Note of advice - idFix, by default runs across all your Active Directory objects. You do not have to fix objects that you won't be synchronising to Azure AD

It is highly recommended that your on-premise Active Directory user objects have their userprincipalname (upn) matched to their primary email address. This will remove any confusion that users might face when accessing the Office 365 services via a web browser as Office 365 login pages refer to username as “email address”.

Next, ensure that the E-mail field for all users in Active Directory contains the UPN for the user.

ADUser

Deploy and Configure Azure AD Connect Server

Ensure all the prerequisites have been met, as outlined at https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-prerequisites

Next, follow the article at https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-select-installation to deploy and configure your Azure AD Connect (AADC) Server.

During the configuration of AADC, you will be asked to specify which on-premise Active Directory objects should be synchronised to Azure AD. Instead of synchronising all your on-premise Active Directory objects, choose the Organisational Unit that contains all the users, groups and contacts you want to synchronise to Azure AD.

Choose the Password Synchronisation option while installing the AADC server. This will synchronise your on-premise password hashes to Azure AD, enabling users to use their on-premises credentials to access Office 365 services

At this stage, your AADC server would have already done an initial run, which would have created objects in Azure AD. These are visible using the Office 365 Admin Center.

After the initial sync, AADC runs an automatic synchronisation every 30 minutes to Azure AD

Provision Mailboxes

Now that everything has been done, open Office 365 Admin Center. Under Users\Active Users you will see all the on-premise users that have been synchronised.

Click on each of the users and then in the next screen click Edit beside Product licenses and select the location of the user and also the combination of license options you want to assign the user. Ensure you select at least Exchange Online (Plan 2) as this is needed to provision a user mailbox. Click on Save.

As soon as you assign the Exchange Online (Plan 2) license, the mailbox provisioning starts. This shouldn’t take more than 10 minutes to finish. You can check the progress by clicking the user in Office 365 Admin Center and then Mail Settings at the bottom of the screen. Once the mailbox has been successfully provisioned, the We are preparing a mailbox for this user message will disappear and instead details about the user mailbox will be shown.

Once the mailbox has been provisioned, open the Exchange Admin Center and then click on recipients from the left menu. In the right hand side screen, click mailboxes. This will show you details about the mailboxes that have been provisioned so far. The newly created user mailbox should be listed there as well.

Thats it folks! You have successfully created an Exchange Online mailbox that is attached to your on-premises Active Directory user object.

Any changes to the Office 365 object (display name etc) will have to be done via the on-premises Active Directory. These changes will be synchronised to Azure AD every 30 minutes and will be reflected in the Exchange Online mailbox

If you try to modify any of the attributes via the Office 365 or Exchange Online Admin Center, you will receive the following error

The action '<cmdlet>', '<property>', can't be performed on the object '<name>' because the object is being synchronized from your on-premises organisation.

Some Additional Information

Please note that the following is not supported by Microsoft.

There are times when you need to have additional email aliases attached to a user mailbox. To do this, follow the below steps

  1. Open Active Directory Users and Computers in your on-premises Active Directory
  2. In the top menu, click View and then select Advanced Features
  3. Navigate to the user object that you want to add additional email aliases to and double click to open its settings
  4. From the tabs click on Attribute Editor
  5. Under Attributes locate proxyAddresses and click on Edit (or double click) to open it
  6. In the values field, first enter the current email address, prefixed with SMTP: (ensure the smtp is in upper case).
  7. Then add all the email aliases that you want to assign to this user. Ensure each email alias is prefixed with smtp:  The email domain for the aliases has to be a domain that is already added and verified in Office 365 Admin Center.
  8. If you need to change the reply-to (primary smtp) address for the user then remove the value that currently has the upper case SMTP: assigned to it and then re-add it, however prefix it with a lower case smtp:. Then remove the alias that  you want to assign as the reply-to (primary smtp) and re-add it, however prefix it with an upper case SMTP:

ADUser_ProxyAddresses

I hope the blog helps out those who might be wanting to use the Cloud Only instead of the Hybrid deployment approach to Office 365.

Have a great day 😉

Continuous Credential Prompt when accessing MIM Password Registration Portal

Recently I was at a customer site, setting up a Microsoft Identity Manager (MIM) 2016 environment, which included the deployment of the Self Service Password Registration and Self Service Password Reset portals. For additional security, I was using Kerberos instead of the default NTLM.

I finished installing the MIM Portal, Service, Password Registration and Password Reset Portals without any issues.

I then proceeded to securing all http endpoints by enabling them for SSL and after that removing the http bindings, so that you could access the MIM Portal, Password Registration and Password Reset Portals only via https. No issues there as well.

By this time I was pretty pleased with myself 😉 Everything was going as planned, no issues faced at all. Finally, lady luck was showering me with her blessings.

Having finished the installation and configuration, I proceeded to testing the solution.

The first thing to check was the MIM Portal site. I opened up a web browser and navigated to the Microsoft Identity Manager Portal. When prompted, I logged in with the mimadmin domain account credentials. I was successfully logged in and could access all the parts without any hitch.

Now kids, if you are faint at heart, be very wary of what happens next (hint. this is the time when you cover your eyes with your hands when watching a horror movie).

I then tried accessing the Self Service Password Registration Portal and got prompted for credentials.

SSPRegistration_CredentialPrompt

I entered the mimadmin account credentials and pressed enter. Just as I thought I had successfully logged in, the credential prompt returned! hmm, that is weird. I was pretty sure I had typed the username and password correctly. Oh well, maybe I didn’t.

I typed the credentials again and pressed enter. Quick as a flash, the credential prompt returned! Uh? What was happening here?{scratching my head} Hmm, I seem to be making a lot of typos today. I carefully entered the username and password again, taking my time this time, to ensure I was entering it correctly. I then pressed enter and waited.

Well, I didn’t have to wait for long since within a second, I got greeted with the Not Authorized screen!

SSPRegistration_NotAuthorised

Fascinating. It seems that lady luck had flown away because here indeed was an issue with the Self Service Password Registration Portal! Ok, Mister. Lets have a look at whats causing this kerfuffle!

I opened up the event viewer on the Self Service Password Registration server and went through each of the logged events in the Application and System logs, however I couldn’t find any clue as to why the credentials were not working. I secretly had suspicions that the issue could be due to Kerberos token errors, however I couldn’t find anything in the event logs to substantiate my suspicion. Hmm, the plot was indeed getting thicker!

I next started doing some Google searches, thinking that someone else might have encountered the same issue. Alas, it seemed that I was alone in my woes as the results seemed to be quite thin in regards to any possible solution for my issue.

Finally, I decided to follow my dear ol’ Sherlock’s advice “when you have eliminated the impossible, whatever remains, however improbable, must be the truth”

I went through the whole Self Service Password Registration setup process, checking each and every part of the configuration, to ensure that the values were as expected. After 10 minutes, I was almost done checking and no clues so far 😦

Lastly, I opened IIS Manager and checked all the settings. Nothing here as well. Hey back up a bit. What is this?

The Self Service Password Registration Portal site had its useAppPoolCredentials set to False.

SSPRegistration_useAppPoolCredentialsFalse

Now, this should be True! Is this what was causing the issue?

I quickly changed the value for useAppPoolCredentials from False to True.

SSPRegistration_useAppPoolCredentialsTrue

I then opened my web browser again and navigated to the Self Service Password Registration Portal. Once again the familiar credential prompt came up. I entered the same credentials as before and pressed enter.

Woo hoo!! This time around I was successfully logged in.

I sincerely hope that this post helps others who might be encountering the same error.

Have a great day 😉

 

Ok Google Email me the status of all vms – Part 2

In my last blog, we configured the backend systems necessary for accomplishing the task of asking Google Home “OK Google Email me the status of all vms” and it sending us an email to that effect. If you haven’t finished doing that, please refer back to my last blog and get that done before continuing.

In this blog, we will configure Google Home.

Google Home uses Google Assistant to do all the smarts. You will be amazed at all the tasks that Google Home can do out of the box.

For our purposes, we will be using the platform IF This Then That or IFTTT for short. IFTTT is a very powerful platform as it lets you create actions based on triggers. This combination of triggers and actions is called a recipe.

Ok, lets dig in and create our IFTTT recipe to accomplish our task

1.1   Go to https://ifttt.com/ and create an account (if you don’t already have one)

1.2   Login to IFTTT and click on My Applets menu from the top

IFTTT_MyApplets_Menu

1.3   Next, click on New Applet (top right hand corner)

1.4   A new recipe template will be displayed. Click on the blue + this choose a service

IFTTT_Reicipe_Step1

1.5   Under Choose a Service type “Google Assistant”

IFTTT_ChooseService

1.6   In the results Google Assistant will be displayed. Click on it

1.7   If you haven’t already connected IFTTT with Google Assistant, you will be asked to do so. When prompted, login with the Google account that is associated with your Google Home and then approve IFTTT to access it.

IFTTT_ConnectGA

1.8   The next step is to choose a trigger. Click on Say a simple phrase

IFTTT_ChooseTrigger

1.9   Now we will put in the phrases that Google Home should trigger on.

IFTTT_CompleteTrigger

For

  • What do you want to say? enter “email me the status of all vms
  • What do you want the Assistant to say in response? enter “no worries, I will send you the email right away

All the other sections are optional, however you can fill them if you prefer to do so

Click Create trigger

1.10   You will be returned to the recipe editor. To choose the action service, click on + that

IFTTT_That

1.11  Under Choose action service, type webhooks. From the results, click on Webhooks

IFTTT_ActionService

1.12   Then for Choose action click on Make a web request

IFTTT_Action_Choose

1.13   Next the Complete action fields screen is shown.

For

  • URL – paste the webhook url of the runbook that you had copied in the previous blog
  • Method – change this to POST
  • Content Type – change this to application/json

IFTTT_CompleteActionFields

Click Create action

1.13   In the next screen, click Finish

IFTTT_Review

 

Woo hoo. Everything is now complete. Lets do some testing.

Go to your Google Home and say “email me the status of all vms”. Google Home should reply by saying “no worries. I will send you the email right away”.

I have noticed some delays in receiving the email, however the most I have had to wait for is 5 minutes. If this is unacceptable, in the runbook script, modify the Send-MailMessage command by adding the parameter -Priority High. This sends all emails with high priority, which should make things faster. Also, the runbook is currently running in Azure. Better performance might be achieved by using Hybrid Runbook Workers

To monitor the status of the automation jobs, or to access their logs, in the Azure Automation Account, click on Jobs in the left hand side menu. Clicking on any one of the jobs shown will provide more information about that particular job. This can be helpful during troubleshooting.

Automation_JobsLog

There you go. All done. I hope you enjoy this additional task you can now do with your Google Home.

If you don’t own a Google Home yet, you can do the above automation using Google Assistant as well.

Ok Google Email me the status of all vms – Part 1

Technology is evolving at a breathtaking pace. For instance, the phone in your pocket has more grunt than the desktop computers of 10 years ago!

One of the upcoming areas in Computing Science is Artificial Intelligence. What seemed science fiction in the days of Isaac Asimov, when he penned I, Robot seems closer to reality now.

Lately the market is popping up with virtual assistants from the likes of Apple, Amazon and Google. These are “bots” that use Artificial Intelligence to help us with our daily lives, from telling us about the weather, to reminding us about our shopping lists or letting us know when our next train will be arriving. I still remember my first virtual assistant Prody Parrot, which hardly did much when you compare it to Siri, Alexa or Google Assistant.

I decided to test drive one of these virtual assistants, and so purchased a Google Home. First impressions, it is an awesome device with a lot of good things going for it. If only it came with a rechargeable battery instead of a wall charger, it would have been even more awesome. Well maybe in the next version (Google here’s a tip for your next version 😉 )

Having played with Google Home for a bit, I decided to look at ways of integrating it with Azure, and I was pleasantly surprised.

In this two-part blog, I will show you how you can use Google Home to send an email with the status of all your Azure virtual machines. This functionality can be extended to stop or start all virtual machines, however I would caution against NOT doing this in your production environment, incase you turn off some machine that is running critical workloads.

In this first blog post, we will setup the backend systems to achieve the tasks and in the next blog post, we will connect it to Google Home.

The diagram below shows how we will achieve what we have set out to do.

Google Home Workflow

Below is a list of tasks that will happen

  1. Google Home will trigger when we say “Ok Google email me the status of all vms”
  2. As Google Home uses Google Assistant, it will pass the request to the IFTTT service
  3. IFTTT will then trigger the webhooks service to call a webhook url attached to an Azure Automation Runbook
  4. A job for the specified runbook will then be queued up in Azure Automation.
  5. The runbook job will then run, and obtain a status of all vms.
  6. The output will be emailed to the designated recipient

Ok, enough talking 😉 lets start cracking.

1. Create an Azure AD Service Principal Account

In order to run our Azure Automation runbook, we need to create a security object for it to run under. This security object provides permissions to access the azure resources. For our purposes, we will be using a service principal account.

Assuming you have already installed the Azure PowerShell module, run the following in a PowerShell session to login to Azure

Import-Module AzureRm
Login-AzureRmAccount

Next, to create an Azure AD Application, run the following command

$adApp = New-AzureRmADApplication -DisplayName "DisplayName" -HomePage "HomePage" -IdentifierUris "http://IdentifierUri" -Password "Password"

where

DisplayName is the display name for your AD Application eg “Google Home Automation”

HomePage is the home page for your application eg http://googlehome (or you can ignore the -HomePage parameter as it is optional)

IdentifierUri is the URI that identifies the application eg http://googleHomeAutomation

Password is the password you will give the service principal account

Now, lets create the service principle for the Azure AD Application

New-AzureRmADServicePrincipal -ApplicationId $adApp.ApplicationId

Next, we will give the service principal account read access to the Azure tenant. If you need something more restrictive, please find the appropriate role from https://docs.microsoft.com/en-gb/azure/active-directory/role-based-access-built-in-roles

New-AzureRmRoleAssignment -RoleDefinitionName Reader -ServicePrincipalName $adApp.ApplicationId

Great, the service principal account is now ready. The username for your service principal is actually the ApplicationId suffixed by your Azure AD domain name. To get the Application ID run the following by providing the identifierUri that was supplied when creating it above

Get-AzureRmADApplication -IdentifierUri {identifierUri}

Just to be pedantic, lets check to ensure we can login to Azure using the newly created service principal account and the password. To test, run the following commands (when prompted, supply the username for the service principal account and the password that was set when it was created above)

$cred = Get-Credential 
Login-AzureRmAccount -Credential $cred -ServicePrincipal -TenantId {TenantId}

where Tenantid is your Azure Tenant’s ID

If everything was setup properly, you should now be logged in using the service principal account.

2. Create an Azure Automation Account

Next, we need an Azure Automation account.

2.1   Login to the Azure Portal and then click New

AzureMarketPlace_New

2.2   Then type Automation and click search. From the results click the following.

AzureMarketPlace_ResultsAutomation

2.3   In the next screen, click Create

2.4   Next, fill in the appropriate details and click Create

AutomationAccount_Details

3. Create a SendGrid Account

Unfortunately Azure doesn’t provide relay servers that can be used by scripts to email out. Instead you have to either use EOP (Exchange Online Protection) servers or SendGrid to achieve this. SendGrid is an Email Delivery Service that Azure provides, and you need to create an account to use it. For our purposes, we will use the free tier, which allows the delivery of 2500 emails per month, which is plenty for us.

3.1   In the Azure Portal, click New

AzureMarketPlace_New

3.2   Then search for SendGrid in the marketplace and click on the following result. Next click Create

AzureMarketPlace_ResultsSendGrid

3.3   In the next screen, for the pricing tier, select the free tier and then fill in the required details and click Create.

SendGridAccount_Details

4. Configure the Automation Account

Inside the Automation Account, we will be creating a Runbook that will contain our PowerShell script that will do all the work. The script will be using the Service Principal and SendGrid accounts. To ensure we don’t expose their credentials inside the PowerShell script, we will store them in the Automation Account under Credentials, and then access them from inside our PowerShell script.

4.1   Go into the Automation Account that you had created.

4.2   Under Shared Resource click Credentials

AutomationAccount_Credentials

4.3    Click on Add a credential and then fill in the details for the Service Principal account. Then click Create

Credentials_Details

4.4   Repeat step 4.3 above to add the SendGrid account

4.5   Now that the Credentials have been stored, under Process Automation click Runbooks

Automation_Runbooks

Then click Add a runbook and in the next screen click Create a new runbook

4.6   Give the runbook an appropriate name. Change the Runbook Type to PowerShell. Click Create

Runbook_Details

4.7   Once the Runbook has been created, paste the following script inside it, click on Save and then click on Publish

Import-Module Azure
$cred = Get-AutomationPSCredential -Name 'Service Principal account'
$mailerCred = Get-AutomationPSCredential -Name 'SendGrid account'

Login-AzureRmAccount -Credential $cred -ServicePrincipal -TenantID {tenantId}

$outputFile = $env:TEMP+ "\AzureVmStatus.html"
$vmarray = @()

#Get a list of all vms 
Write-Output "Getting a list of all VMs"
$vms = Get-AzureRmVM
$total_vms = $vms.count
Write-Output "Done. VMs Found $total_vms"

$index = 0
# Add info about VM's to the array
foreach ($vm in $vms){ 
 $index++
 Write-Output "Processing VM $index/$total_vms"
 # Get VM Status
 $vmstatus = Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status

# Add values to the array:
 $vmarray += New-Object PSObject -Property ([ordered]@{
 ResourceGroupName=$vm.ResourceGroupName
 Name=$vm.Name
 OSType=$vm.StorageProfile.OSDisk.OSType
 PowerState=(get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")[1])
 })
}
$vmarray | Sort-Object PowerState,OSType -Desc

Write-Output "Converting Output to HTML" 
$vmarray | Sort-Object PowerState,OSType -Desc | ConvertTo-Html | Out-File $outputFile
Write-Output "Converted"

$fromAddr = "senderEmailAddress"
$toAddr = "recipientEmailAddress"
$subject = "Azure VM Status as at " + (Get-Date).toString()
$smtpServer = "smtp.sendgrid.net"

Write-Output "Sending Email to $toAddr using server $smtpServer"
Send-MailMessage -Credential $mailerCred -From $fromAddr -To $toAddr -Subject $subject -Attachments $outputFile -SmtpServer $smtpServer -UseSsl
Write-Output "Email Sent"

where

  • ‘Service Principal Account’ and ‘SendGrid Account’ are the names of the credentials that were created in the Automation Account (include the ‘ ‘ around the name)
  • senderEmailAddress is the email address that the email will show it came from. Keep the domain of the email address same as your Azure domain
  • recipientEmailAddress is the email address of the recipient who will receive the list of vms

4.8   Next, we will create a Webhook. A webhook is a special URL that will allow us to execute the above script without logging into the Azure Portal. Treat the webhook URL like a password since whoever possesses the webhook can execute the runbook without needing to provide any credentials.

Open the runbook that was just created and from the top menu click on Webhook

Webhook_menu

4.9   In the next screen click Create new webhook

4.10  A security message will be displayed informing that once the webhook has been created, the URL will not be shown anywhere in the Azure Portal. IT IS EXTREMELY IMPORTANT THAT YOU COPY THE WEBHOOK URL BEFORE PRESSING THE OK BUTTON.

Enter a name for the webhook and when you want the webhook to expire. Copy the webhook URL and paste it somewhere safe. Then click OK.

Once the webhook has expired, you can’t use it to trigger the runbook, however before it expires, you can change the expiry date. For security reasons, it is recommended that you don’t keep the webhook alive for a long period of time.

Webhook_details

Thats it folks! The stage has been set and we have successfully configured the backend systems to handle our task. Give yourselves a big pat on the back.

Follow me to the next blog, where we will use the above with IFTTT, to bring it all together so that when we say “OK Google, email me the status of all vms”, an email is sent out to us with the status of all the vms 😉

I will see you in Part 2 of this blog. Ciao 😉