Quickly Assess Azure MFA use in your Organization

Microsoft recently released a very helpful script that allows Administrators looking to roll out Azure MFA to their organization with a easy-to-read output that can aid in assessing status, or even recommendations to enhance their use of the technology.


Below is a sample output


Here are some common “Recommendations” from the script

  • ‘Register for MFA, preferably with the Microsoft Authenticator mobile app and also with a phone number, used for SMS or Voice.’
  • ‘Consider adding an alternative phone number for additional resilience.’
  • ‘Consider setting the Microsoft Authenticator mobile app as the default method.’
  • ‘Register at least another authentication method, preferably the Microsoft Authenticator mobile app or hardware OATH token. A user can have up to five hardware OATH tokens or mobile apps registered.’
  • ‘Consider adding an alternative phone number for additional resilience.’


Download the ZIP file from the Microsoft website.


Run the following Powershell commands to Authenticate to your tenant and run the commands

Import-Module MSONLINE


$TenantID = ($skus.AccountObjectID[0]).GUID

.\MfaAuthMethodAnalysis.ps1 –tenantID $TenantID -Location -CsvOutput –Verbose

You’ll may see the following error:


If this occurs, you will need the MSONLINE module, and may need to update as I had to do by running the following Powershell command:

Update-Module MSONLINE


Once updated, try running the command again and you should see the process fire off and save a file in the directory of the script in the format MfaAuthMethodAnalysis_<date>_<time>.csv


This is WAY easier than using the GUI in Azure Active Directory, and allows you to do some sort again the data for taking action, automation, etc.


Updating Exchange Server Certs Error Free

One of the most dreaded events that Administrators loath is the updating of SSL certificates in their environment. The process of creating the CRL plus requesting and obtaining the certificate typically is THAT bad, but it’s the application and restart of services then validation of the environment that can be a challenge.

Exchange is no exception, however with many moving parts between client access and mail transport, ensuring we hit each of the key components.

We’ve installed the certificate on the server using the DigiCert tool and ran the necessary Powershell command to assign the certificate

[PS] C:\Windows\system32>Get-ExchangeCertificate | fl Thumbprint,CertificateDomains,IsSelfSigned,Services

Thumbprint         : A3F7F37A3BA1ADC1AAD2AD1A4FC7CCDE2018A1E0
CertificateDomains : {mail.domain.com, autodiscover.domain.com, hybrid.domain.com}
IsSelfSigned       : False
Services           : IMAP, IIS, SMTP

Thumbprint         : 438F27DB3B7BE7C827A3DACD9D26F27EC2FD7852
CertificateDomains : {s, EX1.corp.domain.com}IsSelfSigned       : True
Services           : POP, SMTP

Thumbprint         : 25D280F5E9D0E5D629717250F73192C7FF88FA49
CertificateDomains : {WMSvc-SHA2-EX1}
IsSelfSigned       : True
Services           : None

Thumbprint         : E0335F09160EA7B611B38549A399F3EF6AC4AAEA
CertificateDomains : {Federation}
IsSelfSigned       : True
Services           : SMTP, Federation

Enable-ExchangeCertificate -Thumbprint A3F7F37A3BA1ADC1AAD2AD1A4FC7CCDE2018A1E0 -Services POP,IMAP,IIS,SMTP

Reference for certificate update


While client access for our mailboxes in the Cloud works just fine, when we go to perform SMTP relay from the on-premises Exchange server out to Office 365 it fails and we see the following errors in the Application log:

Source: MSExchangeTransport
Event ID: 12014

Microsoft Exchange could not find a certificate that contains the domain name <I>CN=DigiCert SHA2 Secure Server CA, O=DigiCert Inc, C=US<S>CN=mail.domain.com, OU=IT, O=”Company, LLC”, L=Minneapolis, S=MN, C=US in the personal store on the local computer. Therefore, it is unable to support the STARTTLS SMTP verb for the connector Default Frontend EXGSRV01 with a FQDN parameter of I>CN=DigiCert SHA2 Secure Server CA, O=DigiCert Inc, C=US<S>CN=mail.domain.com, OU=IT, O=”Company, LLC”, L=Minneapolis, S=MN, C=US. If the connector’s FQDN is not specified, the computer’s FQDN is used. Verify the connector configuration and the installed certificates to make sure that there is a certificate with a domain name for that FQDN. If this certificate exists, run Enable-ExchangeCertificate -Services SMTP to make sure that the Microsoft Exchange Transport service has access to the certificate key.

Source: MSExchangeTransport
Event ID: 12035

Exchange was unable to load certificate I>CN=DigiCert SHA2 Secure Server CA, O=DigiCert Inc, C=US<S>CN=mail.domain.com, OU=IT, O=”Company, LLC”, L=Minneapolis, S=MN, C=US. More information: Is FrontEnd Proxy enabled: false. Original backend Server: mail.domain.com. Send Connector Name from the original request: Outbound to Office 365.

So while we updated the Exchange services, we missed an important step of updating the mail transport components that handle the TLS connection (since just about every provider forces its usage today – Microsoft being no exception).

The fix is simple: update the primary Receive and Send Connectors with the certificate name from our new cert & restart the Microsoft Exchange Transport service

$cert = Get-ExchangeCertificate -Thumbprint A3F7F37A3BA1ADC1AAD2AD1A4FC7CCDE2018A1E0

$tlscertificatename = “<i>$($cert.Issuer)<s>$($cert.Subject)”

Set-ReceiveConnector “EX1\Default Frontend EX1” -TlsCertificateName $tlscertificatename

Set-SendConnector -Identity “Outbound to Office 365” -TLSCertificateName $tlscertificatename

Restart-Service MSExchangeTransport

In some cases, the binding for https the Default Web Site can cause errors where login failures are seen as well. You will want to ensure that both https references have the public certificate references, then perform an IISRESET.

Exchange Server 2016 Exchange Administrative Center cannot login

Finally, to test that mail flow is working, we want to send a test email message thru Exchange – we can do this thru Powershell to force a message thru the Receive connector, over to the Send connector to Office 365, and then to the user mailbox.

Import-Module servermanager
Add-WindowsFeature telnet-client

telnet EX1 25
mail from: app1@domain.com
rcpt to: user@domain.com
subject: this is a test message
sending a test message via telnet

Legacy Windows Support for Microsoft Defender ATP

I’ve had several client recently who have talked about what’s entailed to support legacy operation systems (Windows 7/8/Server 2008) in Microsoft Defender ATP. In short, you’re essentially installing the Microsoft Monitoring Agent that’s part of what is legacy OMS (now Azure Security) and the


If your Windows 7 build are up-to-date, you shouldn’t have to install the following 3 items:

Also check your .NET version before install. I attempted to go from version 4.0 to 4.8 on my test VM and it broke the MMS agent where I had to revert, but I was able to go from 4.0 to 4.5 with no disruption to services.

Use the following command:

reg query “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\full” /v version


Download the respective OMS client

Open your MD ATP console to the Onboarding page, and under Windows 7 as the OS copy your WORKSPACE ID and WORKSPACE KEY


Specify <platform> as either x86 or AMD64 then extract the install

MMASetup-<platform>.exe /c /t:c:\MMASETUP-<platform>

Provide the documented WORKSPACE ID and WORKSPACE KEY then run the install


After installation:

  • Check Services.msc to ensure the “Microsoft Monitoring Agent” service is running
  • Also check the Operations Manager event log for entries
    • %SystemRoot%\System32\Winevt\Logs\Operations Manager.evtx

In the Microsoft Defender ATP console you should see your Windows 7 machine:


If you need to remove a machine check out these steps:


Notes From The Field, Volume 1 – The Hybrid AD Device Management Troubleshooting Guide

I always have a rule of thumb “if it takes more than an hour to solve, it deserves sharing”, and that’s always been the story of my blogs over the last decade plus. The biggest struggle is finding the time to sit down, pull all my notes together, and sharing it with the larger IT community. With a holiday weekend and time off, since I’m not WORKING working, I figured why not start a fun series in the Microsoft Modern Workplace space I spend most of my time architecting, deploying & speaking about!

Volume 1 will cover a topic that has been near and dear (and a pain in my rear) to me, and it has to do with the Microsoft Device Management story as it pertains to Hybrid AD devices. Azure AD is the nirvana, mountain top goal that all organizations should be aiming, but as a realist in recognizing that takes time, time, and more time, starting off with Cloud management is a baby step in bringing the rest of an organization.

To meet the prerequisites for the SCCM Co-Management story, Hybrid AD and Intune registered devices for MDM are necessary; see:

In a Hybrid AD scenario this requires line of sight to a domain controller (which also applies to AutoPilot and Hybrid AD, but that’s for another Volume), but what happens with a remote workforce? Let’s dig into the “gotchas” to bring these devices into the fold.

Continue reading “Notes From The Field, Volume 1 – The Hybrid AD Device Management Troubleshooting Guide” »

Where Hast Thou Gone, Workplacejoin.exe?

In looking to help a customer Azure AD join downlevel Windows 7 devices to their tenant, Microsoft has broken the download link (go ahead, try it yourself)


Thankfully a colleague of mine has been working on a project and had those executables for 32 and 64 bit on their network. So I’ve got them ZIP’d up and on my server here. Enjoy!


Journey in Hybrid Cloud Print

I don’t take the term “journey” lightly because now a month in I’m edging closer and closer to the finish but I still feel like I have a long way to go. From lots of reading and even some advise to “abandon the idea”, I’m not one to be a quitter

Thought I’d decide to give it a shot, but definitely fell short with the Microsoft documentation given all of the intricacies of the deployment:

Thanks to Sandy’s blog post I certainly got closer, even took the effort to build out an deployment Powershell script (which you can find here on my GitHub), and the server side portions are definitely getting further than ever. My final steps are shoring up the Intune policy in my lab and then the Windows 10 printer setup (which I hear is the final hurdle to the mountain top)

But when I took the script to run in my client’s production environment, I was missing files in the MophiaPrint folder in the inetpub\wwwroot directory, as well as the EnterpriseCloudPrint virtual directory:


But in my lab:


See? Both the EnterpriseCloudPrint and MopriaCloudService are there, which is evident by the EnterpriseCloudPrint virtual directory

Of course my first thing to do was crack open the Powershell script for installation

cd ‘C:\Program Files\WindowsPowerShell\Modules\PublishCloudPrinter\’
notepad .\CloudPrintDeploy.ps1

Then I looked at the lines of code

Write-Output “** Deploying Enterprise Cloud Print binaries”
“** Installing Enterprise Cloud Print binaries” | Out-File $LogFile -append
dism /online /Add-Capability /CapabilityName:Print.EnterpriseCloudPrint~~~~ >> $LogFile
Write-Output “** Deploying Mopria Discovery Service binaries”
“** Installing Mopria Discovery Service binaries” | Out-File $LogFile -append
dism /online /Add-Capability /CapabilityName:Print.MopriaCloudService~~~~ >> $LogFile

In said CloudPrintDeploy.log

** Installing Enterprise Cloud Print binaries

Deployment Image Servicing and Management tool
Version: 10.0.14393.0

Image Version: 10.0.14393.2457

Error: 87

No Windows features were specified on the command line.
Use the /Get-Features option to find the name of the feature in the image and try the command again.

The DISM log file can be found at C:\Windows\Logs\DISM\dism.log
** Installing Mopria Discovery Service binaries

Deployment Image Servicing and Management tool
Version: 10.0.14393.0

Image Version: 10.0.14393.2457

Error: 87

No Windows features were specified on the command line.
Use the /Get-Features option to find the name of the feature in the image and try the command again.

So I try to run the dism command outside of Powershell. Duh, same result.

So I found the command DISM /online /get-capabilities to see what capabilities were available for this build on the client server

DISM /online /get-capabilities

Deployment Image Servicing and Management tool
Version: 10.0.14393.0

Image Version: 10.0.14393.2457

Capability listing:

Capability Identity : Language.Basic~~~en-GB~
State : Installed

Capability Identity : Language.Basic~~~en-US~
State : Installed

Capability Identity : Language.Handwriting~~~en-US~
State : Installed

Capability Identity : Language.OCR~~~en-US~
State : Installed

Capability Identity : Language.Speech~~~en-US~
State : Installed

Capability Identity : Language.TextToSpeech~~~en-US~
State : Installed

But when I go to run the same on my regular 14393 build, I get a TON more features….

PS C:\Windows\system32> DISM /online /get-capabilities

Deployment Image Servicing and Management tool
Version: 10.0.14393.0

Image Version: 10.0.14393.0

Capability listing:

Ill Save you the hassle of all the language packs and get to the meat of it:

Capability Identity : Language.Handwriting~~~en-US~
State : Installed

Capability Identity : Language.OCR~~~en-US~
State : Installed

Capability Identity : Language.Speech~~~en-US~
State : Installed

Capability Identity : Language.TextToSpeech~~~en-US~
State : Installed

Capability Identity : Print.EnterpriseCloudPrint~~~~
State : Installed

Capability Identity : Print.MopriaCloudService~~~~
State : Installed

After working with the client, turns out if you’re using WSUS or SCCM, and do not have the feature packs enabled, it can cause the features to not be found. This blog from Stephen Wagner helps point out a work around:

Enable download of “Optional features” directly from Windows Update
  1. Open the group policy editor on your domain
    and create a new GPO scoped to the server in question, OR open secpol.msc on your server to modify the settings locally

  2. Navigate to “Computer Configuration”, “Policies”, “Administrative Templates”, and then “System”.
  3. Double click or open “Specify settings for optional component installation and component repair”
  4. Make sure “Never attempt to download payload from Windows Update” is NOT checked
  5. Make sure “Download repair content and optional features directly from Windows Update instead of Windows Server Update Services (WSUS)” IS checked.
  6. Wait for your GPO to update, or run “gpupdate /force” on the machine.

Get Exchange Install Path, Version and Role

I’ve been fighting for a while to find a GOOD script that can do everything from one machine and still work on Exchange 2010 while supporting Exchange 2013/2016. I spent the day working on this sucker so i can send it off to a client to perform an assessment without physically touching the environment and here it is. Enjoy!

Update: I’ve taken my whole script and put it out on my GitHub – check it out!

#Get Exchange Server Versions
#Be sure Powershell Remoting is enabled
#To enable on each server run winrm quickconfig
#Created by Chris Blackburn https://memphistech.net

$exchangeservers = Get-ExchangeServer

$report = @()

foreach ($srv in $exchangeservers)

$srv = Get-ExchangeServer $srv

$server = $srv.Name
if ($srv.AdminDisplayVersion -match “Version 14”) {$ver = “V14”}
if ($srv.AdminDisplayVersion -match “Version 15”) {$ver = “V15”}

Write-Host “Checking $server”

$installpath = $null

$installpath = Invoke-Command –Computername $server -ScriptBlock {$env:ExchangeInstallPath} -ErrorAction STOP
Write-Warning $_.Exception.Message
$installpath = “Unable to connect to server”

Write-host “Install Path is: ” + $installpath
$Path = $installpath + “Bin\ExSetup.exe”
$fileversion = (Get-Command $Path).FileVersionInfo
Write-Host “File Version is: ” + $FileVersion.fileversion

$serverObj = New-Object PSObject
$serverObj | Add-Member NoteProperty -Name “Server Name” -Value $server
$serverObj | Add-Member NoteProperty -Name “Install Path” -Value $installpath
$serverObj | Add-Member NoteProperty -Name “Server Role” -Value $srv.serverrole
$serverObj | Add-Member NoteProperty -Name “Server Version” -Value $fileversion.fileversion

$report += $serverObj

Clear-variable srv
Clear-variable server
Clear-variable installpath
Clear-variable ver

$report | export-csv exchangeversions.csv -notype

Quickly Change Authentication models in Azure AD / Office 365

In 2017 Microsoft has made some major improvements to their Managed authentication model to make it a viable competitor to the cumbersome Federated model. As a refresher, Federated identity requires Microsoft ADFS infrastructure deployed (along with ADConnect for AD Sync), and to make it highly available entails multiple servers deployed in multiple datacenters/Azure, global load balancing of the internet-facing URL with Azure Traffic Manager – dependencies on your private cloud to authenticate to the public cloud. Managed identity still uses ADConnect for AD Sync but the biggest drawback is that you didn’t get the “seamless” single signon (SSO) experience that ADFS provides, only “same sign on” (SSO) and needing to reenter your credentials.

Microsoft has recently added Seamless Single Signon and Pass-Thru Authentication (as an alternative to password-hash synchronization in high security environments, but out of scope for this article) to ADConnect, in efforts to further eliminate the ADFS dependencies previously mentioned, and with this I’ve been working a large number of projects in planning / executing a move away from ADFS.

What I’ve found is that it’s always been a grey area on how long this process takes, given most of the documentation calls for using the Convert-MSOLDomainToStandard cmdlet and dealing with the password conversion process. If you follow these steps there’s an easier way to do it.

Step 1 – Check Local Active Directory

The first step is ensuring that you have local AD setup and able to support Password Sync. One of the Microsoft Premier Field Engineers (PFE) wrote a great blog on this in 2016:

“First, ensure your Azure AD Connect Sync ID has “Replicate Directory Changes” and “Replicate Directory Changes All” permissions in AD (For Password Sync to function properly). If you did not set this up initially, you will have to do this prior to configuring”

This can be done thru Active Directory Users & Computers


Continue reading “Quickly Change Authentication models in Azure AD / Office 365” »

Office 365 Whitelist URLs for Firewalls & Trusted Sites

With the ever growing list of Microsoft Office 365 services comes a growing number of URLs to whitelist on web application firewalls, proxies, and IE trusted sites lists. The full list, which can be found at https://support.office.com/en-us/article/Office-365-URLs-and-IP-address-ranges-8548a211-3fe7-47cb-abb1-355ea5aa88a2, is quite intensive and for my own sake (and that of my clients) I’ve created the abbreviated list below to save not only the community but myself some time!


Creating an Offline install of Office 365 Pro Plus

So how do you create an offline installation of Office 365 Pro Plus for distribution on machines when you don’t want them all chewing up the internet connection at once?

First, download the Office 2016 Deployment Tool from:


(Note: you can reuse this tool to download Current branch versions each month, however Microsoft does update this to support new deployment features and resolve deployment bugs so check back often for new versions!)

Run the EXE and extract to a folder – It will only produce setup.exe

image image

Open a command prompt and browse to the extract folder, and run setup.exe /download


This will sit here for a bit while it downloads the current build to the subfolder under \Office\Data with the build number. As you can see here, the build is primarily 32-bit but provides 64-bit support as part of the installation.

In this case, this folder sits on a file share (which we’ll get to in a moment) that will serve as our “SourcePath”




The next part to performing the deployment as part of an administrative install is to create the configure XML file. You can read more about the syntax, formatting, etc at:

In an enterprise environment, it’s typical that you will have a Deferred and a Current branch (to borrow from Microsoft terminology).

The SourcePath is our Deferred that goes as the core install for all our machines, and the Updates path (towards the bottom) is another folder that we run our download process again on a monthly basis for the Current branch. Whenever a new version of the current branch is downloaded to the Updates folder, it will “update Office to the newest version. Only the files that have changed in the new version will be updated”

To perform the actual install, we need a configuration XML to use in conjunction with the setup file to perform the full Offline install. For this I like to use the online XML Configuration File editor, located at https://officedev.github.io/Office-IT-Pro-Deployment-Scripts/XmlEditor.html

<Add OfficeClientEdition=“32” Channel=“Current” SourcePath=“\\network\path”> <Product ID=“O365ProPlusRetail”>
<Language ID=“en-us”/>
<Property Name=“AUTOACTIVATE” Value=“1”/>
<Property Name=“FORCEAPPSHUTDOWN” Value=“TRUE”/>
<Property Name=“SharedComputerLicensing” Value=“0”/>
<Property Name=“PinIconsToTaskbar” Value=“TRUE”/>
<Logging Level=“Standard” Path=“c:\windows\temp”/>
<Display Level=“None” AcceptEULA=“TRUE”/>
<Updates Enabled=“TRUE” Channel=“Current” UpdatePath=“\\network\path”/> </Configuration>

From our workstation we can manually run (or use a deployment tool like SCCM to push out Office 2016 to the enterprise) using the setup.exe /configure switch.

Then before you know it, volia!