Using a certificate to encrypt credentials in automated PowerShell scripts – An Update!

Early last year I wrote a post about encrypting script credentials using certificates. At the time, someone (thanks Dave Wyatt!) commented on the post suggesting a couple of alternative methods to encrypt and decrypt the data, in particular I was interested in the Protect-CmsMessage and Unprotect-CmsMessage cmdlets included in PowerShell 5.0. Now that PowerShell 5.0 is more widespread I wanted to post a quick update about how these cmdlets can help simplify the process. The process is similar, but there are less steps and it is important to note that the certificate must contain the Data Encipherment or Key Encipherment key usage, and include the Document Encryption Enhanced Key Usage (1.3.6.1.4.1.311.80.1).

Let’s start by first locating our certificate using the Get-ChildItem cmdlet:

1
2
  $Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -like "CN=PowerShell Automation*"}
  

Next we encrypt our password using that certificate:

1
2
  $Password = 'MyPassword'
  Protect-CmsMessage -To $Cert -Content $Password

You’ll notice that the encrypted password is presented a little differently. You will need to include the entire block in your script.

Unencrypting the password in your script basically involves repeating this process in reverse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  $Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -like 'CN=PowerShell Automation*'}
$EncryptedPwd = @'
-----BEGIN CMS-----
MIIBqAYJKoZIhvcNAQcDoIIBmTCCAZUCAQAxggFQMIIBTAIBADA0MCAxHjAcBgNVBAMMFVBvd2Vy
U2hlbGwgQXV0b21hdGlvbgIQOEd4fYDturxF77V7lEytlDANBgkqhkiG9w0BAQcwAASCAQB0z92N
HrgQ84JxSV7RYpwSMPJRuSXlgVubOIew8KsYXr/E8kd/wOyT/2NPi3d+4xb67CLUM4infqOrt9Q+
ReAtINvfVB5EPc9wU8yDpdz+WKProT4RJ94nzGH5qW5SK4O1Siu0VSPJZaCNb+CmYNFNNvLu6MN4
pDqOiqZnv+j/rUxhrHX+U3E+eJq5P0gsZUwRaXZoAgGyV6SvZdUsbPYZ+hMPG0DruF/83SK6MOZM
yVnGOmeP8e8/b/Rk2Y24JvDcROwRvK2+uj2Oy3ukw1WS4TxMy2V4lkjTYvwIO+bukjFCCtaR4Q63
C6fx9OArx+uMbPmzkFgmG0w3jFVNnjjMMDwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEPdMffTC
N+IvYDNFmuWKgZqAELsAZyE9I0POh/j64DNTsLI=
-----END CMS-----
'@
$DecryptedPwd = $EncryptedPwd | Unprotect-CmsMessage -To $Cert | ConvertTo-SecureString -AsPlainText -Force

You can now use $DecryptedPwd to generate your credentials similar to the following:

1
2
3
$MSOLUsername = 'serviceAcc@tenant.onmicrosoft.com'
$MSOLCredentials = New-Object System.Management.Automation.PSCredential ($MSOLUsername,$DecryptedPwd)
Connect-MSOLService -Credential $MSOLCredentials

My Connect-EXO.ps1 script has been updated!

I've just published an updated version of my Connect-EXO.ps1 script. Version 3.1 includes the ability to connect to the Office 365 Security & Compliance Center. Based on the options selected it will connect to either or all services with Exchange Online being the only one selected by default. Here is a screenshot of the new interface:

The update has been published to the TechNet Gallery, it can be downloaded by clicking here…

Using PowerShell to automate Office 365 license assignment

The move to Office 365 almost always requires changes to existing operational processes. One of the processes that inevitably requires an update is the provisioning process and the extent of these changes will differ from organization to organization and depend on the maturity of your identity lifecycle management process. In many environments, license assignment can be easily automated using a scheduled task and PowerShell so I wanted to put together a post that provides an outline on how this can be done.

Before getting into it, I just want to add a little disclaimer to this post – I love PowerShell and because I love PowerShell, I like to use it, but this doesn’t mean it is always fit for purpose. Each environment is different so I would urge you to consider all options before implementing a full blown PowerShell provisioning process because you may already own better tools for the job (FIM/MIM, etc). These tools often take a while to implement when done properly, so PowerShell could also be a great stop-gap solution. This post is intended to provide a foundation that helps you put together your own process and should not necessarily be implemented “as-is”.

With that out of the way, there are some requirements to think of as well. The server executing the script will need the following:

  • The ability to connect to Azure AD via remote PowerShell which requires the Azure AD Module –  Click here for more info
  • Remote Server Administration Tools – RSAT
  • A certificate to encrypt and decrypt your service account passwords. This certificate can be from an internal CA – See this post for more info
  • Service accounts with the relevant permissions
  • Relay permission on your Exchange server – Used for send report emails

The scenario I will be addressing in this post is to automate mailbox provisioning and license assignment in a hybrid deployment. All new mailboxes get provisioned as remote mailboxes directly in Office 365 and users are assigned the relevant Office 365 license. Each user account has an entry in the ‘extensionAttribute1’ attribute which determines the license they will be assigned, eg. E3 or Exchange Plan 2. We make use of 2 security groups during this process so users can be created in any OU as long as that OU is being synchronized to Azure AD. These groups are:

  • O365_Provision – Starts the provisioning process. New accounts are added to this group once they have been created in Active Directory
  • O365_License – Used by the script to keep track of users who still need to have licenses assigned

At a high level the workflow looks something like this:

Lets start by looking at the variables and functions we need. Here you can define you license SKUs, service account credentials, etc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Modules
Import-Module ActiveDirectory
# Variables - Edit these
#########################
$ErrorActionPreference = 'Stop'
$ExchangeServer = 'you_exchange_server'
$FromAddress = 'Provisioning Service
<provisioning@yourdomain.com>'
$ToAddress = 'you@yourdomain.com'
$ADUsername = 'YourDomain\service_acc'
$RoutingDomain = 'yourtenant.mail.onmicrosoft.com'
$ADEncryptedPwd = ''
$MSOLUsername = 'service_acc@yourtenant.onmicrosoft.com'
$MSOLEncryptedPwd = ''
$Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -like 'CN=Provisioning Service*'}
$E3SKU = 'yourtenant:ENTERPRISEPACK'
$EP2SKU = 'yourtenant:EXCHANGEENTERPRISE'
#Email Styling
$EmailBody = @"
<html>
<head>
<style>
	.table {
		border:1px solid #F0F0F0;
        border-collapse: collapse;
		padding:10px;
	}
	.table th {
		border:1px solid #F0F0F0;
		padding:10px;
		background:#F0F0F0;
	}
	.table td {
		border:1px solid #F0F0F0;
		padding:10px;
	}
</style>
</head>
<body>
Hello,
This is an automated report from the Office 365 Provisioning Service. The following user accounts have been successfully provisioned in Office 365:
<table class="table">
<thead>
<tr>
<th>Username</th>
<th>Email Address</th>
<th>License Assigned</th>
</tr>
</thead>
<tbody>
"@
$EmailBodyClosure = @"
Regards,
Provisioning Service
</body>
 </html>
"@
###########################
# Functions
# Function to create report email
function Send-Report{
    $Msg = New-Object Net.Mail.MailMessage
    $Smtp = New-Object Net.Mail.SmtpClient($ExchangeServer)
    $Msg.From = $FromAddress
    $Msg.To.Add($ToAddress)
    $Msg.Subject = $EmailSubject
    $Msg.Body = $EmailBody
    $Msg.IsBodyHTML = $true
    $Smtp.Send($Msg)
    }
# Function for Exchange Connection
function Connect-Exchange{
    $ADEncryptedBytes = [System.Convert]::FromBase64String($ADEncryptedPwd)
    $ADDecryptedBytes = $Cert.PrivateKey.Decrypt($ADEncryptedBytes, $true)
    $ADDecryptedPwd = [system.text.encoding]::UTF8.GetString($ADDecryptedBytes) | ConvertTo-SecureString -AsPlainText -Force
    $ADCredentials = New-Object System.Management.Automation.PSCredential ($ADUsername,$ADDecryptedPwd)
    $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$ExchangeServer/PowerShell/ -Authentication Kerberos -Credential $ADCredentials
    Import-PSSession $ExchSession
    }
# Function for MSOL Connection
function Connect-MSOL{
    $MSOLEncryptedBytes = [System.Convert]::FromBase64String($MSOLEncryptedPwd)
    $MSOLDecryptedBytes = $Cert.PrivateKey.Decrypt($MSOLEncryptedBytes, $true)
    $MSOLDecryptedPwd = [system.text.encoding]::UTF8.GetString($MSOLDecryptedBytes) | ConvertTo-SecureString -AsPlainText -Force
    $MSOLCredentials = New-Object System.Management.Automation.PSCredential ($MSOLUsername,$MSOLDecryptedPwd)
    Connect-MSOLService -Credential $MSOLCredentials
    }

Next we have the ‘licensing phase’ – This phase also generates the email report because a user is considered to be fully provisioned once they have a license assigned. We can also catch any errors and generate an error report email for those.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# Licensing Phase - Check if any users need to have licenses assigned
$NeedLicense = Get-AdGroupMember -Identity O365_License
If ($NeedLicense) {
        $HasMbxArray = @()
        Connect-MSOL
        Foreach ($User in $NeedLicense) {
            $UserInfo = Get-ADUser $User.SamAccountName -Properties *
            $Username = $UserInfo.SamAccountName
            $UserEmail = $UserInfo.Mail
            $UserLic = $UserInfo.extensionAttribute1
            $UserLoc = $UserInfo.c
            $UPN = $UserInfo.UserPrincipalName
            $MsolUser = Get-MsolUser -UserPrincipalName $UPN
            $HasLic = $MsolUser.IsLicensed
                If ($MsolUser -and $UserLic -and $UserLoc) {
                    Try {
						If ($HasLic) {
	                    $ExistingLic = $MsolUser.Licenses.AccountSkuId
	                    Set-MsolUserLicense -UserPrincipalName $UPN -RemoveLicenses $ExistingLic
	                    }
	                    If ($UserLic -eq 'Exchange 2') {
	                    Set-MsolUser -UserPrincipalName $UPN -UsageLocation $UserLoc
	                    Set-MsolUserLicense -UserPrincipalName $UPN -AddLicenses $EP2SKU
                            Remove-AdGroupMember -Identity O365_License -Members $Username -Confirm:$False
	                    }
	                    ElseIf ($UserLic -eq 'E3') {
	                    Set-MsolUser -UserPrincipalName $UPN -UsageLocation $UserLoc
	                    Set-MsolUserLicense -UserPrincipalName $UPN -AddLicenses $E3SKU
                            Remove-AdGroupMember -Identity O365_License -Members $Username -Confirm:$False
                       }
					 }
					Catch {
        			$EmailSubject = 'Office 365 Provisioning Error'
        			$EmailBody = @"
<html>
<head>
</head>
<body>
Hello,
This is an automated report from the Office 365 Provisioning Service. The following errors occurred when attempting to provision users in Office 365:
$Error
Additional Diagnostic Info:
Username: $Username
Email Address: $UserEmail
License Assigned: $UserLic
Usage Location: $UserLoc
Regards,
Provisioning Service
</body>
</html>
"@
Send-Report
			        }
$EmailBody += '<tr>'
$EmailBody += "<td>$Username</td>"
$EmailBody += "<td>$UserEmail</td>"
$EmailBody += "<td>$UserLic</td>"
$EmailBody += '</tr>'
}
}
$Licenses = Get-MsolAccountSku
$E3Consumed = $Licenses[0].ConsumedUnits
$E3Total = $Licenses[0].ActiveUnits
$E3Remaining = $E3Total - $E3Consumed
$ExP2Consumed = $Licenses[1].ConsumedUnits
$ExP2Total = $Licenses[1].ActiveUnits
$ExP2Remaining = $ExP2Total - $ExP2Consumed
$EmailBodyLic = @"
	</tbody>
</table>
<strong>License Summary:</strong>
<ul>
<li>You have consumed <strong>$E3Consumed</strong> Exchange Online (Plan 2) licenses and have <strong>$E3Remaining</strong> remaining</li>
<li>You have consumed <strong>$ExP2Consumed</strong> Office 365 Enterprise E3 licenses and have <strong>$ExP2Remaining</strong> remaining</li>
</ul>
"@
	        $EmailSubject = 'Office 365 Provisioning Report'
	        $EmailBody += $EmailBodyLic
	        $EmailBody += $EmailBodyClosure
	        Send-Report
    }

The ‘mailbox enablement phase’ connects to the local Exchange server and creates a new remote mailbox. See this post for more information on this process. This phase also attempts to generate error notification emails.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Mailbox Enablement Phase - Check if any new mailboxes need to be provisioned
$NeedMailbox = Get-AdGroupMember -Identity O365_Provisioning
If ($NeedMailbox) {
    Connect-Exchange
    Foreach ($User in $NeedMailbox) {
    $Username = $User.SamAccountName
    $UserInfo = Get-ADUser $Username -Properties *
    $UserLic = $UserInfo.extensionAttribute1
    $UserLoc = $UserInfo.c
    If ($UserLic -and $UserLoc){
        Try {
            Enable-RemoteMailbox $Username -RemoteRoutingAddress "$Username@$RoutingDomain"
            Add-ADGroupMember -Identity O365_License -Members $Username
            Remove-AdGroupMember -Identity O365_Provisioning -Members $Username -Confirm:$False
                }
        Catch {
        $EmailSubject = 'Office 365 Provisioning Error'
        $EmailBody = @"
<html>
<head>
</head>
<body>
Hello,
This is an automated report from the Office 365 Provisioning Service. The following errors occurred when attempting to mail-enable users:
<span style="color:#B22222;">$Error</span>
<strong>Additional Diagnostic Info:</strong>
Username: $Username
Regards,
Provisioning Service
</body>
</html>
"@
        Send-Report
        }
        }
    Else {
        $EmailSubject = 'Office 365 Provisioning Error'
        $EmailBody = @"
<html>
<head>
</head>
<body>
Hello,
This is an automated report from the Office 365 Provisioning Service. The following user could not be provisioned, please check to ensure that the required license type has been correctly entered in the "Company" field and that the "Country/region" has been set:
<span style="color:#B22222;">User: $Username</span>
Regards,
Provisioning Service
</body>
</html>
"@
        Send-Report
        }
    }
}

Putting this all together will hopefully form be a great foundation to help you build your own workflow. Once done, you can simply schedule your script to run using task scheduler.

Azure AD Connect gets a big update!

In case you missed it, the latest version of Azure AD Connect (version 1.1.105.0) was recently made available for download. One of the big changes and great new additions in this version is the new built-in scheduler which was separate to the sync engine in previous releases and would run as a scheduled task in Windows task scheduler:

Another big change is the fact that the default synchronization frequency has been updated and is now 30 minutes which is a big change from the previous default of 3 hours. In addition, this value can now be configured which is something that was not supported previously – I know this change is going to be very well received by many organizations. The scheduler can be viewed and configured using the

1
  Get-ADSyncScheduler

and

1
  Set-ADSyncScheduler

cmdlets. You can also manually start a synchronization cycle with the

1
  Start-ADSyncSyncCycle

cmdlet

As before, the upgrade process from previous versions is very simple – The wizard will detect the previous installation and ask to if you would like to upgrade:

You will notice after the upgrade that the old Azure AD Sync Scheduler task no longer exists in Windows task scheduler

Other new features in this release are:

  • Automatic upgrade feature for Express settings customers.
  • Support for the global admin using MFA and PIM in the installation wizard.
  • Support changing the user's sign-in method after initial install.
  • Allows Domain and OU filtering in the installation wizard.

For more information on these and other new features, click here

For more information about the new built-in scheduler, click here

How to create a remote “Office 365” mailbox in a hybrid deployment

I’ve recently seen the same issue pop up in a few different environments so I thought I would put together a short post that explains how to create a “Office 365” mailbox when using a hybrid deployment of Exchange. One of the questions I’ve had had answer a few times recently is “Why do newly created Exchange Online mailboxes not appear in the on-premises Exchange Admin Center as “Office 365” mailboxes like migrated mailboxes do?”

There appears to be some confusion around provisioning of new user mailboxes once a hybrid deployment has been configured as this issue is caused when the mailbox has not be correctly provisioned in the on-premises environment.

While it is technically possible to create a new user account in Active Directory, wait for AAD Connect to provision that account to AAD and then assign an Exchange Online license to that user to create their mailbox, but the problem with that process is that it does not set the msExchRecipientType (and other) Exchange related attributes for that user object and that is why it will never appear in the on-premises Exchange Admin Center:

In order to correctly popular these attributes, you either need to create the new user and mailbox via the Exchange Admin Center by clicking on the “+” icon and selecting “Office 365 Mailbox” or you need to enable a remote mailbox for a previously created user using the Enable-RemoteMailbox cmdlet

Many organizations already have automated provisioning processes in place so adjusting the mailbox enablement workflow may be the preferred method, an example of the cmdlet is shown below:

1
2
#Syntax is: Enable-RemoteMailbox <user> &ndash;RemoteRoutingAddress <user@tenant.mail.onmicrosoft.com><br />
Enable-RemoteMailbox homer -RemoteRoutingAddress homer@gooselabs.mail.onmicrosoft.com<br />

The Enable-RemoteMailbox cmdlet can be run immediately after creating the user account in Active Directory so there is no need to wait for the next AAD Connect synchronization cycle to complete before enabling the mailbox. Once the user account has been provisioned to AAD, the mailbox will automatically created and the appropriate license should then be assigned to the user.

More information on the Enable-RemoteMailbox cmdlet can be found on TechNet here

Multiple tenant domains with a single Yammer network

I recently worked with a customer who had a large number of different business units and each one had their own domain. As part of their Office 365 enablement project they wanted to enable Yammer Enterprise for their tenant and allow users from the different business units to collaborate with each other using the same Yammer network. Yammer integration with Office 365 has come a long way over the last few years and while merging multiple networks or adding domains into the same network is possible, there are a few things to think about before initiating the process and I wanted to post some of my notes.

Firstly, here are some of the key points to remember:

  • Yammer no longer requires the use of Yammer Directory Sync and can now make use of Azure AD Connect
  • Once Yammer has been activated and a Yammer Enterprise network has been created for the tenant, any user who was a valid account in the tenant will be able to log on to Yammer without any additional license assignment
  • Yammer users are created the first time they log on and will therefore not appear in the Yammer people directory prior to that
  • Office 365 supports one activated Yammer Enterprise network per tenant
  • Yammer content is not copied during the merge process

Since Office 365 supports only one activated Yammer Enterprise network per tenant, it is recommended that in environments with multiple domains the home network is activated using the domain that accommodates the majority of users. Once this network has been created, adding a domain to a network is very simple.  log into the Office 365 portal, submit a service request and once you have completed the request form (pictured below) it only takes a day or two to complete.

Capture1

If a domain already has a Yammer Basic network, you can choose to either upgrade that network to an Enterprise network or create a new Enterprise network and merge the old Basic one, but it is important to understand that during the merge process the old Yammer content will not be copied. This network migration process no longer requires a service request and can be performed by Yammer admins. There is some great documentation available here. 

Some additional documentation on upgrading your Yammer network is available here.

Exchange Hybrid Deployment and Sizing

In September, I posted about the great new Office 365 Hybrid Configuration Wizard and while there is no question that the HCW is a great help when configuring hybrid deployments, there are a few other important considerations to take into account when deploying Exchange Hybrid. I've helped many organizations deploy hybrid configurations and move mailboxes to the cloud over the last few years and often to come across the same questions and misconceptions, so I thought I'd address some of these in a blog post.

 

"Help!, I need to implement a hybrid server!"
That is not necessarily true, Exchange Hybrid is a configuration state and should not be thought of as a server role. A Hybrid deployment uses existing Exchange workloads like Autodiscover and Exchange Web Services (EWS) so if you already have Exchange 2010/2013/2016 deployed according to best practices then chances are you already have everything you need to configure Exchange Hybrid. Sure, there is some additional functionality available if you use the most recent version of Exchange, but do you need that functionality? I've seen so many environments that have correctly sized and load balanced Exchange servers and then have a tiny virtual machine deployed as a "hybrid server". This type of configuration creates a single point of failure and inevitably becomes a migration bottleneck.

If you are looking to migrate from a legacy version of Exchange then you will need to implement additional servers in order to deploy Hybrid. For Exchange 2003 your only option for going hybrid is to deploy a correctly sized Exchange 2010 deployment. For those on Exchange 2007 it is recommended that Exchange 2013 is used instead.

 

"Can I virtualize my servers for Hybrid?" or "How do I size my servers for Hybrid?"
If you are in a position where you are looking to upgrade your Exchange Organization prior to a migration to Exchange Online or you need to implement new Exchange servers because you are on a legacy version, you can definitely make use of virtualization. Virtualization in the Exchange world has long been a hot topic and isn’t really something that I’ll get into in this post. In my experience, incorrectly configured or undersized virtual Exchange servers are by far the most common issue I’ve come across in the field so it is often simpler to use physical hardware which is also the recommended practice.

To illustrate this, here is an example of some actual performance data I gathered when working with a customer. This particular customer was migrating from Exchange 2007 and had implemented virtual Exchange 2013 servers. Everything worked great until they attempted to migrate several mailboxes at the same time and they noticed that it was taking a considerable amount of time for small mailboxes to migrate. After confirming that the issue wasn’t bandwidth related we decided to take a closer look at the new virtual servers. These servers sized with 4 CPU cores and 32 GB of RAM but didn’t appear to be performing correctly. Our initial performance tests indicated that the servers seemed to be CPU constrained and after a lot of testing and much discussion with their virtualization team we found that simply changing the configuration from 2 sockets with 2 cores each (4 cores total) to 1 socket with 4 cores (still 4 cores) greatly improved the performance. The same 100 mailboxes were used in both tests:

CPU

If you are planning to virtualize, make sure you follow Microsoft’s best practices for virtualizing Exchange and always use the Exchange Server Role Requirements Calculator to correctly size your deployments.

 

"The cloud is awesome, I plan to remove all my on-premises Exchange servers!"
There is no denying that moving to the cloud makes sense for a lot of organizations and in many instances there is a desire to remove all on-premises workloads. I always advise my customers to be very careful when it comes to decommissioning their entire Exchange Organization. When using directory synchronization with your Office 365 tenant, your users are synchronized from your on-premises Active Directory and therefore most of the attributes associated with these users cannot be managed in Office 365 or Exchange Online and must be managed on-premises. Completely removing your on-premises Exchange Organization makes managing mailbox attributes more difficult so I would definitely recommend retaining at least one Exchange server for user object management. You don’t need to retain all your Exchange servers though, so I many environments there will still be a significant reduction in servers.

Retaining an on-premises Exchange server could also be really useful in SMTP relay scenarios where you have on-premises applications and devices that need to send email.

Microsoft also has a lot in great resources available to help answer your Hybrid questions, here are a few:

A look at the Microsoft Office 365 Hybrid Configuration Wizard

In case you missed it, Microsoft recently announced the Microsoft Office 365 Hybrid Configuration Wizard (HCW). The HCW has come a long way since it was first introduced in Exchange 2010 SP2, prior to that configuring a hybrid deployment required ~50 manual steps. This is the third version of the HCW and one of the most notable changes is that it is a standalone application which decouples it from the Exchange update cycle. The HCW will download the latest version every time it is run which will ensure that the latest version is always used.

The new HCW is available for use with Exchange 2013 CU8 or higher, however you will need to have Exchange 2013 CU10 installed if you would like see the new HCW landing page (pictured below) which is accessible via the “Hybrid” menu item in your on-premises Exchange Admin Center:

cap1

Those using Exchange 2013 CU8 or CU9 can download the new HCW here.

The wizard itself with take you through a series of configuration pages very similar to the pervious version, however there are improvements to error handling and a number of changes under the covers that greatly improve performance and efficiency.

cap2

cap12

cap13

It is worth noting that the log file location has changed from “%ProgramFiles%\Microsoft\Exchange Server\V15\Logging\Update-HybridConfiguration”  to “%AppData%\Microsoft\Exchange Hybrid Configuration”

The Exchange Team has a detailed post about all the great new features in the Microsoft Office 365 Configuration Wizard, I'd encourage you to check it out here.

Migrating Office for Mac users to Exchange Online

I recently worked with a customer who has a workstation fleet that is almost entirely made up of Macintosh computers. Users make use of Outlook 2011 for Mac and were being migrated to Exchange Online. We found that there wasn’t a great deal of documentation around that covers this scenario so I wanted to post some of my notes here.

According to the “Office 365 system requirements” page on office.com, Office 365 is designed to work with the following software:

  • The current or immediately previous version of Internet Explorer or Firefox, or the latest version of Chrome or Safari.
  • Any version of Microsoft Office in mainstream support.

Microsoft Support Lifecycle indicates that you would need at least Microsoft Office for Mac 2011 SP3 and I can confirm after some testing that anything prior to Office for Mac 2011 SP2 simply won’t even connect. The latest update currently available for Microsoft Office for Mac 2011 will bring the version number to 14.5.4. There is of course also the new Office 2016 for Mac.

The user experience when migrating a Mac user is similar to what we experience in the Windows world, with one exception – no restart of Outlook is required. Autodiscover will detect the mailbox move and prompt the user to re-configure. Here are some examples of this prompt in Outlook for Mac 2011 and Outlook 2016 for Mac:

2011

2016

Not sure what version your clients have installed? You can use Log Parser Studio to parse the IIS logs on your CAS servers to help determine the versions you have out there.